From patchwork Fri Jul 17 13:37:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 1331143 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=XQmRKq5c; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4B7XJC563Mz9sTS for ; Fri, 17 Jul 2020 23:38:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726512AbgGQNiT (ORCPT ); Fri, 17 Jul 2020 09:38:19 -0400 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:34079 "EHLO us-smtp-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726665AbgGQNiS (ORCPT ); Fri, 17 Jul 2020 09:38:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594993097; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZEia1iyS9kteob5Qg+X0J7hYEECiauY8z/tZvjJdw/Q=; b=XQmRKq5cieCPrnMQbdsdU8kFUIlaQHUm17+SSUpW0EVSYArtlvwzSwDwmFMJ2Bx4S61FI3 BZd5Mu6WwIfH34A4Q3CowKk2toQHEZDkQQbi/fNHQIY7ydXdH2a/xI069kcKifo94XioK3 cbomWoT1Qbu987F0WOIqYwGP54UsRfQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-455-XJlNu97EPXWIujvfHaO0Vw-1; Fri, 17 Jul 2020 09:38:13 -0400 X-MC-Unique: XJlNu97EPXWIujvfHaO0Vw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D7432E92C; Fri, 17 Jul 2020 13:38:11 +0000 (UTC) Received: from x1.localdomain.com (ovpn-112-162.ams2.redhat.com [10.36.112.162]) by smtp.corp.redhat.com (Postfix) with ESMTP id 120CC8FA27; Fri, 17 Jul 2020 13:38:08 +0000 (UTC) From: Hans de Goede To: Thierry Reding , =?utf-8?q?Uwe_Kleine-K=C3=B6n?= =?utf-8?q?ig?= , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= , "Rafael J . Wysocki" , Len Brown Cc: Hans de Goede , linux-pwm@vger.kernel.org, intel-gfx , dri-devel@lists.freedesktop.org, Andy Shevchenko , Mika Westerberg , linux-acpi@vger.kernel.org Subject: [PATCH v5 04/16] pwm: lpss: Add range limit check for the base_unit register value Date: Fri, 17 Jul 2020 15:37:41 +0200 Message-Id: <20200717133753.127282-5-hdegoede@redhat.com> In-Reply-To: <20200717133753.127282-1-hdegoede@redhat.com> References: <20200717133753.127282-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org When the user requests a high enough period ns value, then the calculations in pwm_lpss_prepare() might result in a base_unit value of 0. But according to the data-sheet the way the PWM controller works is that each input clock-cycle the base_unit gets added to a N bit counter and that counter overflowing determines the PWM output frequency. Adding 0 to the counter is a no-op. The data-sheet even explicitly states that writing 0 to the base_unit bits will result in the PWM outputting a continuous 0 signal. When the user requestes a low enough period ns value, then the calculations in pwm_lpss_prepare() might result in a base_unit value which is bigger then base_unit_range - 1. Currently the codes for this deals with this by applying a mask: base_unit &= (base_unit_range - 1); But this means that we let the value overflow the range, we throw away the higher bits and store whatever value is left in the lower bits into the register leading to a random output frequency, rather then clamping the output frequency to the highest frequency which the hardware can do. This commit fixes both issues by clamping the base_unit value to be between 1 and (base_unit_range - 1). Fixes: 684309e5043e ("pwm: lpss: Avoid potential overflow of base_unit") Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- Changes in v5: - Use clamp_val(... instead of clam_t(unsigned long long, ... Changes in v3: - Change upper limit of clamp to (base_unit_range - 1) - Add Fixes tag --- drivers/pwm/pwm-lpss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 43b1fc634af1..da9bc3d10104 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -97,6 +97,8 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, freq *= base_unit_range; base_unit = DIV_ROUND_CLOSEST_ULL(freq, c); + /* base_unit must not be 0 and we also want to avoid overflowing it */ + base_unit = clamp_val(base_unit, 1, base_unit_range - 1); on_time_div = 255ULL * duty_ns; do_div(on_time_div, period_ns); @@ -105,7 +107,6 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, orig_ctrl = ctrl = pwm_lpss_read(pwm); ctrl &= ~PWM_ON_TIME_DIV_MASK; ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT); - base_unit &= (base_unit_range - 1); ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; ctrl |= on_time_div;