From patchwork Tue Nov 4 22:36:56 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: tthayer@opensource.altera.com X-Patchwork-Id: 5231301 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A6789C11AC for ; Tue, 4 Nov 2014 22:36:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D6D082015A for ; Tue, 4 Nov 2014 22:36:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F34752012B for ; Tue, 4 Nov 2014 22:36:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751325AbaKDWgs (ORCPT ); Tue, 4 Nov 2014 17:36:48 -0500 Received: from mail-bl2on0084.outbound.protection.outlook.com ([65.55.169.84]:49509 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751324AbaKDWgs (ORCPT ); Tue, 4 Nov 2014 17:36:48 -0500 Received: from dinh-ubuntu.altera.com (64.129.157.38) by BN1PR03MB122.namprd03.prod.outlook.com (10.255.201.19) with Microsoft SMTP Server (TLS) id 15.1.6.9; Tue, 4 Nov 2014 22:36:44 +0000 From: To: CC: , , , , , Thor Thayer Subject: [PATCH] spi: dw: Fix dynamic speed change Date: Tue, 4 Nov 2014 16:36:56 -0600 Message-ID: <1415140617-2028-1-git-send-email-tthayer@opensource.altera.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Originating-IP: [64.129.157.38] X-ClientProxiedBy: BLUPR11CA0019.namprd11.prod.outlook.com (10.141.240.29) To BN1PR03MB122.namprd03.prod.outlook.com (10.255.201.19) X-MS-Exchange-Transport-FromEntityHeader: Hosted X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:BN1PR03MB122; X-Forefront-PRVS: 03853D523D X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(199003)(189002)(77156002)(33646002)(81156004)(107046002)(2351001)(62966003)(120916001)(99396003)(97736003)(229853001)(106356001)(77096003)(31966008)(95666004)(46102003)(105586002)(69596002)(40100003)(122386002)(53416004)(42186005)(86362001)(93916002)(48376002)(50466002)(19580395003)(87286001)(64706001)(86152002)(92726001)(87976001)(4396001)(92566001)(21056001)(19580405001)(20776003)(89996001)(110136001)(50986999)(102836001)(66066001)(101416001)(88136002)(104166001)(50226001)(47776003); DIR:OUT; SFP:1101; SCL:1; SRVR:BN1PR03MB122; H:dinh-ubuntu.altera.com; FPR:; MLV:sfv; PTR:InfoNoRecords; A:0; MX:1; LANG:en; X-OriginatorOrg: opensource.altera.com Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, 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: Thor Thayer Changing SPI transfer speed using a utility such as spi_config with spidev updates chip->speed_hz which is compared to the next transfer speed. When speed_hz is not declared in a SPI transfer, the transfer speed is not updated for the next read/write on /dev/spidevX.Y. The element spi_transfer->speed_hz is filled with spi->max_speed_hz. The test of if (transfer->speed_hz != speed) doesn't work because the chip->speed_hz matches transfer->speed_hz and the clock divider is not updated. This fix: On each transfer update the clock divider, compare to the previous clock divider and update if necessary. This fixes another bug where the clock divider calculation at the top of the pump_transfers() function could be an odd-number. Reported-by: Vlastimil Setka Signed-off-by: Vlastimil Setka Signed-off-by: Thor Thayer --- drivers/spi/spi-dw.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 72e12ba..3456b34 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -376,9 +376,6 @@ static void pump_transfers(unsigned long data) chip = dws->cur_chip; spi = message->spi; - if (unlikely(!chip->clk_div)) - chip->clk_div = dws->max_freq / chip->speed_hz; - if (message->state == ERROR_STATE) { message->status = -EIO; goto early_exit; @@ -415,21 +412,27 @@ static void pump_transfers(unsigned long data) cr0 = chip->cr0; - /* Handle per transfer options for bpw and speed */ - if (transfer->speed_hz) { - speed = chip->speed_hz; + /* Always calculate the desired clock divider */ + speed = transfer->speed_hz ? transfer->speed_hz : chip->speed_hz; + + if (speed > dws->max_freq) { + dev_err(&spi->dev, "Unsupported SPI freq: %d Hz\n", speed); + message->status = -EIO; + goto early_exit; + } + + /* clk_div doesn't support odd number */ + clk_div = dws->max_freq / speed; + clk_div = (clk_div + 1) & 0xfffe; - if (transfer->speed_hz != speed) { - speed = transfer->speed_hz; + /* Determine if the clock divider changed, if so update chip struct */ + if (clk_div != chip->clk_div) + chip->clk_div = clk_div; + else + clk_div = 0; /* Prevent register programming below */ - /* clk_div doesn't support odd number */ - clk_div = dws->max_freq / speed; - clk_div = (clk_div + 1) & 0xfffe; + chip->speed_hz = speed; - chip->speed_hz = speed; - chip->clk_div = clk_div; - } - } if (transfer->bits_per_word) { bits = transfer->bits_per_word; dws->n_bytes = dws->dma_width = bits >> 3;