From patchwork Tue Sep 2 09:01:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Barry Song X-Patchwork-Id: 4823741 Return-Path: X-Original-To: patchwork-linux-arm@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 79A72C033A for ; Tue, 2 Sep 2014 09:05:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A3EF320160 for ; Tue, 2 Sep 2014 09:05:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C75AD2014A for ; Tue, 2 Sep 2014 09:05:20 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XOjyb-0005U6-Pe; Tue, 02 Sep 2014 09:02:09 +0000 Received: from cluster-g.mailcontrol.com ([208.87.233.190]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XOjyO-0005Fa-Qf for linux-arm-kernel@lists.infradead.org; Tue, 02 Sep 2014 09:02:00 +0000 Received: from shaapppus01.asia.root.pri ([210.13.83.99]) by rly17g.srv.mailcontrol.com (MailControl) with ESMTP id s8291MTL000630 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Tue, 2 Sep 2014 10:01:24 +0100 Received: from SHAASIEXC01.ASIA.ROOT.PRI ([10.125.12.102]) by shaapppus01.asia.root.pri (PGP Universal service); Tue, 02 Sep 2014 17:01:24 +0800 X-PGP-Universal: processed; by shaapppus01.asia.root.pri on Tue, 02 Sep 2014 17:01:24 +0800 Received: from barry-laptop.ROOT.PRI (10.125.5.73) by asimail.csr.com (10.125.12.88) with Microsoft SMTP Server (TLS) id 14.3.174.1; Tue, 2 Sep 2014 17:01:21 +0800 From: Barry Song To: , Subject: [PATCH 1/8] spi: sirf: correct spi gpio and hardware chipselect behaviour Date: Tue, 2 Sep 2014 17:01:01 +0800 Message-ID: <1409648468-5436-2-git-send-email-Barry.Song@csr.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1409648468-5436-1-git-send-email-Barry.Song@csr.com> References: <1409648468-5436-1-git-send-email-Barry.Song@csr.com> MIME-Version: 1.0 X-Originating-IP: [10.125.5.73] X-CFilter-Loop: Reflected X-Scanned-By: MailControl 33066.168 (www.mailcontrol.com) on 10.71.0.127 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140902_020156_872683_C6336ACC X-CRM114-Status: GOOD ( 21.86 ) X-Spam-Score: -0.7 (/) Cc: Qipan Li , workgroup.linux@csr.com, linux-arm-kernel@lists.infradead.org, Barry Song X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-3.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, 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: Qipan Li the old codes check the cs-gpios, if the gpio number is 0 like: <&gpio, 0, 0>, the driver will use the only hardware chipselect. this is wrong because of_spi_register_master() can read property cs-gpios from device node and set the spi master's cs number and gpio cs automatically based on whether the cs-gpios is valid. this patch fixes the beviour of CSR spi driver and move to a core level supported way. Signed-off-by: Qipan Li Signed-off-by: Barry Song --- drivers/spi/spi-sirf.c | 86 +++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 95ac276..44ec3bb 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -170,8 +170,7 @@ struct sirfsoc_spi { * command model */ bool tx_by_cmd; - - int chipselect[0]; + bool hw_cs; }; static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi) @@ -484,7 +483,7 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) { struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master); - if (sspi->chipselect[spi->chip_select] == 0) { + if (sspi->hw_cs) { u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL); switch (value) { case BITBANG_CS_ACTIVE: @@ -502,14 +501,13 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) } writel(regval, sspi->base + SIRFSOC_SPI_CTRL); } else { - int gpio = sspi->chipselect[spi->chip_select]; switch (value) { case BITBANG_CS_ACTIVE: - gpio_direction_output(gpio, + gpio_direction_output(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); break; case BITBANG_CS_INACTIVE: - gpio_direction_output(gpio, + gpio_direction_output(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); break; } @@ -603,8 +601,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) sspi->tx_by_cmd = false; } /* - * set spi controller in RISC chipselect mode, we are controlling CS by - * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE. + * it should never set to hardware cs mode because in hardware cs mode, + * cs signal can't controlled by driver. */ regval |= SIRFSOC_SPI_CS_IO_MODE; writel(regval, sspi->base + SIRFSOC_SPI_CTRL); @@ -627,9 +625,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) static int spi_sirfsoc_setup(struct spi_device *spi) { + struct sirfsoc_spi *sspi; + if (!spi->max_speed_hz) return -EINVAL; + sspi = spi_master_get_devdata(spi->master); + + if (spi->cs_gpio == -ENOENT) + sspi->hw_cs = true; + else + sspi->hw_cs = false; return spi_sirfsoc_setup_transfer(spi, NULL); } @@ -638,19 +644,10 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) struct sirfsoc_spi *sspi; struct spi_master *master; struct resource *mem_res; - int num_cs, cs_gpio, irq; - int i; - int ret; - - ret = of_property_read_u32(pdev->dev.of_node, - "sirf,spi-num-chipselects", &num_cs); - if (ret < 0) { - dev_err(&pdev->dev, "Unable to get chip select number\n"); - goto err_cs; - } + int irq; + int i, ret; - master = spi_alloc_master(&pdev->dev, - sizeof(*sspi) + sizeof(int) * num_cs); + master = spi_alloc_master(&pdev->dev, sizeof(*sspi)); if (!master) { dev_err(&pdev->dev, "Unable to allocate SPI master\n"); return -ENOMEM; @@ -658,32 +655,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sspi = spi_master_get_devdata(master); - master->num_chipselect = num_cs; - - for (i = 0; i < master->num_chipselect; i++) { - cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i); - if (cs_gpio < 0) { - dev_err(&pdev->dev, "can't get cs gpio from DT\n"); - ret = -ENODEV; - goto free_master; - } - - sspi->chipselect[i] = cs_gpio; - if (cs_gpio == 0) - continue; /* use cs from spi controller */ - - ret = gpio_request(cs_gpio, DRIVER_NAME); - if (ret) { - while (i > 0) { - i--; - if (sspi->chipselect[i] > 0) - gpio_free(sspi->chipselect[i]); - } - dev_err(&pdev->dev, "fail to request cs gpios\n"); - goto free_master; - } - } - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); if (IS_ERR(sspi->base)) { @@ -753,7 +724,21 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ret = spi_bitbang_start(&sspi->bitbang); if (ret) goto free_dummypage; - + for (i = 0; master->cs_gpios && i < master->num_chipselect; i++) { + if (master->cs_gpios[i] == -ENOENT) + continue; + if (!gpio_is_valid(master->cs_gpios[i])) { + dev_err(&pdev->dev, "no valid gpio\n"); + ret = -EINVAL; + goto free_dummypage; + } + ret = devm_gpio_request(&pdev->dev, + master->cs_gpios[i], DRIVER_NAME); + if (ret) { + dev_err(&pdev->dev, "failed to request gpio\n"); + goto free_dummypage; + } + } dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num); return 0; @@ -768,7 +753,7 @@ free_rx_dma: dma_release_channel(sspi->rx_chan); free_master: spi_master_put(master); -err_cs: + return ret; } @@ -776,16 +761,11 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) { struct spi_master *master; struct sirfsoc_spi *sspi; - int i; master = platform_get_drvdata(pdev); sspi = spi_master_get_devdata(master); spi_bitbang_stop(&sspi->bitbang); - for (i = 0; i < master->num_chipselect; i++) { - if (sspi->chipselect[i] > 0) - gpio_free(sspi->chipselect[i]); - } kfree(sspi->dummypage); clk_disable_unprepare(sspi->clk); clk_put(sspi->clk);