From patchwork Thu Sep 3 11:23:24 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: 1356687 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=UzfIJ8Yg; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4Bj4KD2tD0z9sW7 for ; Fri, 4 Sep 2020 01:21:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728465AbgICPVf (ORCPT ); Thu, 3 Sep 2020 11:21:35 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:54624 "EHLO us-smtp-1.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728456AbgICLYX (ORCPT ); Thu, 3 Sep 2020 07:24:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1599132238; 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=ZukzWkoKOICgMwClnkSHfjft9LoCEglKBEzHtiqOOV4=; b=UzfIJ8Yg+GGJlz4Dm57uaPWRb+8+9tblrRDJ0Tz9XZaF7ncJ0IkcgbLep46S0ji3FuZMzV u0Qe4BxJd56eQoW0nL7NI+QGgu7jsdLsLRwoKBPcht62Ykyt7RagHmkkWTmOgsKjJ0LW4G 017e2v/ePqDJBvW/5zDn2xza7PS9/eQ= 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-10-pdpVvNiWPduzJMNpzU_yqA-1; Thu, 03 Sep 2020 07:23:56 -0400 X-MC-Unique: pdpVvNiWPduzJMNpzU_yqA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A117C10ABDB8; Thu, 3 Sep 2020 11:23:54 +0000 (UTC) Received: from x1.localdomain (ovpn-113-3.ams2.redhat.com [10.36.113.3]) by smtp.corp.redhat.com (Postfix) with ESMTP id EB0625C1C2; Thu, 3 Sep 2020 11:23:51 +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 v10 04/17] pwm: lpss: Add range limit check for the base_unit register value Date: Thu, 3 Sep 2020 13:23:24 +0200 Message-Id: <20200903112337.4113-5-hdegoede@redhat.com> In-Reply-To: <20200903112337.4113-1-hdegoede@redhat.com> References: <20200903112337.4113-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 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 Acked-by: Thierry Reding 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;