From patchwork Mon Jan 11 16:01:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?TcOlbnMgUnVsbGfDpXJk?= X-Patchwork-Id: 8006471 Return-Path: X-Original-To: patchwork-linux-arm@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 6D2569F32E for ; Mon, 11 Jan 2016 16:04:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8249520122 for ; Mon, 11 Jan 2016 16:04:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 80474200ED for ; Mon, 11 Jan 2016 16:04:33 +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 1aIevi-0003xj-Ro; Mon, 11 Jan 2016 16:02:50 +0000 Received: from unicorn.mansr.com ([2001:8b0:ca0d:8d8e::2]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aIevc-0003s3-JP for linux-arm-kernel@lists.infradead.org; Mon, 11 Jan 2016 16:02:47 +0000 Received: by unicorn.mansr.com (Postfix, from userid 51770) id E77F015393; Mon, 11 Jan 2016 16:02:22 +0000 (GMT) From: Mans Rullgard To: linux-arm-kernel@lists.infradead.org, Cyrille Pitchen , "Yang, Wenyou" , Nicolas Ferre , Mark Brown , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] spi: atmel: improve internal vs gpio chip-select choice Date: Mon, 11 Jan 2016 16:01:42 +0000 Message-Id: <1452528102-26458-1-git-send-email-mans@mansr.com> X-Mailer: git-send-email 2.7.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160111_080245_072972_B71C40DD X-CRM114-Status: GOOD ( 13.59 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 The driver currently chooses between internal chip-select or gpio based on the existence of the cs-gpios DT property which fails on non-DT systems and also enforces the same choice for all devices. This patch makes the method per device instead of per controller and fixes the selection on non-DT systems. With these changes, the chip-select method for each device is chosen according to the following priority: 1. GPIO from device tree 2. GPIO from platform data 3. Internal chip-select Tested on AVR32 ATSTK1000. Signed-off-by: Mans Rullgard --- Changes: - allow internal CS only hardware v2 - retain seting of master->num_chipselect to 4 on hardware v2 if cs-gpios property is missing --- drivers/spi/spi-atmel.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 08cbb3e43c76..d4a806e24060 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -312,7 +312,6 @@ struct atmel_spi { bool use_dma; bool use_pdc; - bool use_cs_gpios; /* dmaengine data */ struct atmel_spi_dma dma; @@ -323,6 +322,7 @@ struct atmel_spi { struct atmel_spi_device { unsigned int npcs_pin; u32 csr; + bool use_cs_gpio; }; #define BUFFER_SIZE PAGE_SIZE @@ -387,7 +387,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) } mr = spi_readl(as, MR); - if (as->use_cs_gpios) + if (asd->use_cs_gpio) gpio_set_value(asd->npcs_pin, active); } else { u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; @@ -404,7 +404,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) mr = spi_readl(as, MR); mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); - if (as->use_cs_gpios && spi->chip_select != 0) + if (asd->use_cs_gpio && spi->chip_select != 0) gpio_set_value(asd->npcs_pin, active); spi_writel(as, MR, mr); } @@ -433,7 +433,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) asd->npcs_pin, active ? " (low)" : "", mr); - if (!as->use_cs_gpios) + if (!asd->use_cs_gpio) spi_writel(as, CR, SPI_BIT(LASTXFER)); else if (atmel_spi_is_v2(as) || spi->chip_select != 0) gpio_set_value(asd->npcs_pin, !active); @@ -1539,6 +1539,7 @@ static int atmel_spi_setup(struct spi_device *spi) unsigned int bits = spi->bits_per_word; unsigned int npcs_pin; int ret; + bool use_cs_gpio; as = spi_master_get_devdata(spi->master); @@ -1565,8 +1566,6 @@ static int atmel_spi_setup(struct spi_device *spi) csr |= SPI_BIT(CPOL); if (!(spi->mode & SPI_CPHA)) csr |= SPI_BIT(NCPHA); - if (!as->use_cs_gpios) - csr |= SPI_BIT(CSAAT); /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. * @@ -1577,13 +1576,22 @@ static int atmel_spi_setup(struct spi_device *spi) csr |= SPI_BF(DLYBS, 0); csr |= SPI_BF(DLYBCT, 0); - /* chipselect must have been muxed as GPIO (e.g. in board setup) */ npcs_pin = (unsigned long)spi->controller_data; - if (!as->use_cs_gpios) - npcs_pin = spi->chip_select; - else if (gpio_is_valid(spi->cs_gpio)) + if (gpio_is_valid(spi->cs_gpio)) { + /* GPIO from DT */ npcs_pin = spi->cs_gpio; + use_cs_gpio = true; + } else if (npcs_pin && gpio_is_valid(npcs_pin)) { + /* GPIO from platform data */ + use_cs_gpio = true; + } else if (atmel_spi_is_v2(as)) { + /* internal chip-select */ + npcs_pin = spi->chip_select; + use_cs_gpio = false; + } else { + return -EINVAL; + } asd = spi->controller_state; if (!asd) { @@ -1591,7 +1599,7 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; - if (as->use_cs_gpios) { + if (use_cs_gpio) { ret = gpio_request(npcs_pin, dev_name(&spi->dev)); if (ret) { kfree(asd); @@ -1603,6 +1611,7 @@ static int atmel_spi_setup(struct spi_device *spi) } asd->npcs_pin = npcs_pin; + asd->use_cs_gpio = use_cs_gpio; spi->controller_state = asd; } else { atmel_spi_lock(as); @@ -1612,6 +1621,8 @@ static int atmel_spi_setup(struct spi_device *spi) atmel_spi_unlock(as); } + if (!asd->use_cs_gpio) + csr |= SPI_BIT(CSAAT); asd->csr = csr; dev_dbg(&spi->dev, @@ -1807,12 +1818,9 @@ static int atmel_spi_probe(struct platform_device *pdev) atmel_get_caps(as); - as->use_cs_gpios = true; if (atmel_spi_is_v2(as) && - !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) { - as->use_cs_gpios = false; + !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) master->num_chipselect = 4; - } as->use_dma = false; as->use_pdc = false;