From patchwork Sat Jan 30 04:26:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "David Rivshin (Allworx)" X-Patchwork-Id: 8169501 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 726FF9FBE9 for ; Sat, 30 Jan 2016 04:30:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9DEB120142 for ; Sat, 30 Jan 2016 04:30:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8F87120398 for ; Sat, 30 Jan 2016 04:30:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755706AbcA3Eah (ORCPT ); Fri, 29 Jan 2016 23:30:37 -0500 Received: from mail-qk0-f194.google.com ([209.85.220.194]:33254 "EHLO mail-qk0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754080AbcA3Eaf (ORCPT ); Fri, 29 Jan 2016 23:30:35 -0500 Received: by mail-qk0-f194.google.com with SMTP id q184so2656429qkb.0; Fri, 29 Jan 2016 20:30:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=d1vnCutbeV5s2NJkeHGdV/wuPkLm/NOR+2qOsI3m1D8=; b=Stel/552aWXyqPDHtRuZjD1CnCqO0IT9HMmMlm71wMii0XLZdQB1btal5CjpGHfrww NkSIOAZ6oXrmRblNS7DEb4vwfipDjLVP/b4IZKImliSXCZORX0lPC8R6/WgXUmhAA5Ba Zk6gzvtRpiTADdhY9cYtQ/t3iBgIpOEzDGuZ09/4dMsoOEyRbxIEpWhdmYb0OpuIreCk kR3yjq3ZeIt3VlB358JWBGkkfx0VHbiSg1hC+dBPcP+7T+O8oLIoQUJYyoGJUEf+TLUa +5OLBNxzB5EGX52xWFG09EPy15R+oNgfkeGNb4tA6NOAtd7GQET7r5HLbIrjrQmS8hp9 Pjug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=d1vnCutbeV5s2NJkeHGdV/wuPkLm/NOR+2qOsI3m1D8=; b=UugiFc+HS/ubrmX8VZZm88ypWxax1pk4ICAtTngJpX4qrzU1qSBFxkEw4YxCkisrZ3 5G/OKu6r6HlBI6Ch1POqHKzlxl/Rf/j/3GMGJxJu0qIZGj2thxTigcoGc9Q4bXBfRG3t 99IfhFvQ5BmjFfYbZkoqTytCtRaMXma3ZAXDgAIRP2vMdDmNdW08bxyWY+ZMvXwlRmKo a4ZaXEGxvi4Gd8XSUlWhghS2RGC+sAWaW+wbx4nA2RJYD96nvAYFbjbAyWye6xgXFD2j Yx9KX7aJnfo0vFLC/iWBPirANwupIlZQTtOR11Za1QLd4AbOBK+7Dt8OFAuLITGVcPoU dZiw== X-Gm-Message-State: AG10YORG2+W3WB76CTkgrBBXEJ8G9IfHPg4zuTocM9xwN+hHNLliy4xDHCvzNLQbfGXDcA== X-Received: by 10.55.192.7 with SMTP id o7mr15110082qki.93.1454128234419; Fri, 29 Jan 2016 20:30:34 -0800 (PST) Received: from drivshin-linux.crosskeys.inscitek.com ([24.213.148.66]) by smtp.gmail.com with ESMTPSA id y104sm8404563qgd.33.2016.01.29.20.30.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Jan 2016 20:30:34 -0800 (PST) From: "David Rivshin (Allworx)" To: linux-pwm@vger.kernel.org, Thierry Reding , Neil Armstrong Cc: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Tony Lindgren , Grant Erickson , NeilBrown , Joachim Eastwood Subject: [PATCH 2/4] pwm: omap-dmtimer: add sanity checking for load and match values Date: Fri, 29 Jan 2016 23:26:52 -0500 Message-Id: <1454128014-22866-3-git-send-email-drivshin.allworx@gmail.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1454128014-22866-1-git-send-email-drivshin.allworx@gmail.com> References: <1454128014-22866-1-git-send-email-drivshin.allworx@gmail.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: David Rivshin Add sanity checking to ensure that we do not program load or match values that are out of range if a user requests period or duty_cycle values which are not achievable. The match value cannot be less than the load value (but can be equal), and neither can be 0xffffffff. This means that there must be at least one fclk cycle between load and match, and another between match and overflow. Fixes: 6604c6556db9 ("pwm: Add PWM driver for OMAP using dual-mode timers") Signed-off-by: David Rivshin Acked-by: Neil Armstrong --- drivers/pwm/pwm-omap-dmtimer.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 0083e75..103d729 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -119,15 +119,13 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, fclk = omap->pdata->get_fclk(omap->dm_timer); if (!fclk) { dev_err(chip->dev, "invalid pmtimer fclk\n"); - mutex_unlock(&omap->mutex); - return -EINVAL; + goto err_einval; } clk_rate = clk_get_rate(fclk); if (!clk_rate) { dev_err(chip->dev, "invalid pmtimer fclk rate\n"); - mutex_unlock(&omap->mutex); - return -EINVAL; + goto err_einval; } dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); @@ -142,6 +140,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, * The non-active time is the remainder: (DM_TIMER_MAX-match_value) * clock cycles. * + * NOTE: It is required that: load_value <= match_value < DM_TIMER_MAX + * * References: * OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11 * AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6 @@ -149,6 +149,24 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns); duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns); + if (period_cycles < 2) { + dev_info(chip->dev, + "period %dns is too short for clock rate %luHz\n", + period_ns, clk_rate); + goto err_einval; + } + if (duty_cycles < 1) { + dev_dbg(chip->dev, + "duty cycle %dns is too short for clock rate %luHz, using minimum of 1 clock cycle\n", + duty_ns, clk_rate); + duty_cycles = 1; + } else if (duty_cycles >= period_cycles) { + dev_dbg(chip->dev, + "duty cycle %dns is too long for period %dns at clock rate %luHz, using maximum of 1 clock cycle less than period\n", + duty_ns, period_ns, clk_rate); + duty_cycles = period_cycles - 1; + } + load_value = (DM_TIMER_MAX - period_cycles) + 1; match_value = load_value + duty_cycles - 1; @@ -179,6 +197,11 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, mutex_unlock(&omap->mutex); return 0; + +err_einval: + mutex_unlock(&omap->mutex); + + return -EINVAL; } static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,