From patchwork Tue Jan 27 13:37:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gaetan Hug X-Patchwork-Id: 433507 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id E92B8140161 for ; Wed, 28 Jan 2015 01:09:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752855AbbA0OJU (ORCPT ); Tue, 27 Jan 2015 09:09:20 -0500 Received: from mail-am1on0145.outbound.protection.outlook.com ([157.56.112.145]:51552 "EHLO emea01-am1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752056AbbA0OJU (ORCPT ); Tue, 27 Jan 2015 09:09:20 -0500 X-Greylist: delayed 1891 seconds by postgrey-1.27 at vger.kernel.org; Tue, 27 Jan 2015 09:09:19 EST Received: from [192.168.0.121] (91.183.127.4) by DB3PR01MB0684.eurprd01.prod.exchangelabs.com (25.160.50.26) with Microsoft SMTP Server (TLS) id 15.1.75.20; Tue, 27 Jan 2015 13:37:45 +0000 Message-ID: <54C794A6.3040805@induct.be> Date: Tue, 27 Jan 2015 14:37:42 +0100 From: Gaetan Hug User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.4.0 MIME-Version: 1.0 To: Armadeus Forum ML , Subject: Found bug in pwm-mxs.c X-Originating-IP: [91.183.127.4] X-ClientProxiedBy: DB3PR01CA0064.eurprd01.prod.exchangelabs.com (10.242.133.167) To DB3PR01MB0684.eurprd01.prod.exchangelabs.com (25.160.50.26) Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=induct.be; X-DmarcAction-Test: None X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(3005004);SRVR:DB3PR01MB0684; X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004); SRVR:DB3PR01MB0684; X-Forefront-PRVS: 046985391D X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6049001)(6009001)(92566002)(23676002)(74482002)(46102003)(87976001)(87266999)(54356999)(42186005)(47776003)(66066001)(83506001)(65816999)(229853001)(107886001)(80316001)(50986999)(62966003)(77156002)(64126003)(86362001)(117156001)(59896002)(33656002)(50466002)(77096005)(122386002)(36756003)(40100003); DIR:OUT; SFP:1102; SCL:1; SRVR:DB3PR01MB0684; H:[192.168.0.121]; FPR:; SPF:None; MLV:sfv; LANG:en; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:; SRVR:DB3PR01MB0684; X-OriginatorOrg: induct.be X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jan 2015 13:37:45.4591 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR01MB0684 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Hello folks, I found a bug in the pwm-mxs.c driver for the i.MX28 platform. The driver computes from the desired period which clock divider it should be using. This computation assumes that the link between the register value and the actual divider value is raising 2 to the power of the registry value. div = 1 << regvalue This is true only for the first 5 values out of 8. Next values are 64, 256 and, 1024. This affects only the user only if he requests a period > 0.04369s. I solved this by replacing the computation of the divider value with a lookup table. If I should provide it in a different manner for it to be included in the kernel, please let me know. Best regards Gaetan Hug ------ } --- To unsubscribe from this list: send the line "unsubscribe linux-pwm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git i/drivers/pwm/pwm-mxs.c w/drivers/pwm/pwm-mxs.c index c2c5a4f..cb89f7e 100644 --- i/drivers/pwm/pwm-mxs.c +++ w/drivers/pwm/pwm-mxs.c @@ -51,16 +51,17 @@ static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned int period_cycles, duty_cycles; unsigned long rate; unsigned long long c; + unsigned const int cdiv[PERIOD_CDIV_MAX] = {1, 2, 4, 8, 16, 64, 256, 1024}; rate = clk_get_rate(mxs->clk); while (1) { - c = rate / (1 << div); + c = rate / cdiv[div]; c = c * period_ns; do_div(c, 1000000000); if (c < PERIOD_PERIOD_MAX) break; div++; - if (div > PERIOD_CDIV_MAX) + if (div >= PERIOD_CDIV_MAX) return -EINVAL;