[2/8] spi: sirf: request and free cs gpio in setup and cleanup callbacks
diff mbox

Message ID 1409648468-5436-3-git-send-email-Barry.Song@csr.com
State New, archived
Headers show

Commit Message

Barry Song Sept. 2, 2014, 9:01 a.m. UTC
From: Qipan Li <Qipan.Li@csr.com>

move spi controller's gpio request work out from probe() to spi device
register stage, so after spi device register spi controller can deactive
device's gpio chipselect. old code can't do it because gpio request has
not be done until device register is finised in spi_bitbang_start.
and add cleanup function to free CS gpio.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
---
 drivers/spi/spi-sirf.c | 58 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 38 insertions(+), 20 deletions(-)

Comments

Mark Brown Sept. 4, 2014, 7:19 p.m. UTC | #1
On Tue, Sep 02, 2014 at 05:01:02PM +0800, Barry Song wrote:
> From: Qipan Li <Qipan.Li@csr.com>
> 
> move spi controller's gpio request work out from probe() to spi device
> register stage, so after spi device register spi controller can deactive
> device's gpio chipselect. old code can't do it because gpio request has
> not be done until device register is finised in spi_bitbang_start.
> and add cleanup function to free CS gpio.

I'm not quite sure I understand the rationale here - as far as I can
tell this is making the GPIO request happen later not earlier so it's
not clear to me what the problem this is fixing in the existing code.
If the goal is to move the request around in the probe function why not
just move the existing code earlier in probe()?

This also won't interact well with deferred probe, though a better
solution here would be some kind of deferred device registration and
typically the link ordering will mean it won't be an issue when
everything is built in.
Qipan Li Sept. 5, 2014, 3:34 a.m. UTC | #2
2014-09-05 3:19 GMT+08:00 Mark Brown <broonie@kernel.org>:
> On Tue, Sep 02, 2014 at 05:01:02PM +0800, Barry Song wrote:
>> From: Qipan Li <Qipan.Li@csr.com>
>>
>> move spi controller's gpio request work out from probe() to spi device
>> register stage, so after spi device register spi controller can deactive
>> device's gpio chipselect. old code can't do it because gpio request has
>> not be done until device register is finised in spi_bitbang_start.
>> and add cleanup function to free CS gpio.
>
> I'm not quite sure I understand the rationale here - as far as I can
> tell this is making the GPIO request happen later not earlier so it's
> not clear to me what the problem this is fixing in the existing code.
> If the goal is to move the request around in the probe function why not
> just move the existing code earlier in probe()?
>
> This also won't interact well with deferred probe, though a better
> solution here would be some kind of deferred device registration and
> typically the link ordering will mean it won't be an issue when
> everything is built in.

As GPIO cs can be high or low validate and the used GPIO pin with
default value may high or low,
it is need do spi device's chipselect invalidation work in spi_setup,
the patch purpose for it.
master->cs_gpios only assigned after spi_bitbang_start and the
function call spi_setup,
if keep the existing code there will result gpio usage before gpio request.
just move gpio request code in spi_sirfsoc_setup before gpio use.
Mark Brown Sept. 6, 2014, 1:57 p.m. UTC | #3
On Fri, Sep 05, 2014 at 11:34:57AM +0800, swingboard wrote:
> 2014-09-05 3:19 GMT+08:00 Mark Brown <broonie@kernel.org>:

> > I'm not quite sure I understand the rationale here - as far as I can
> > tell this is making the GPIO request happen later not earlier so it's
> > not clear to me what the problem this is fixing in the existing code.
> > If the goal is to move the request around in the probe function why not
> > just move the existing code earlier in probe()?

> As GPIO cs can be high or low validate and the used GPIO pin with
> default value may high or low,
> it is need do spi device's chipselect invalidation work in spi_setup,
> the patch purpose for it.
> master->cs_gpios only assigned after spi_bitbang_start and the
> function call spi_setup,
> if keep the existing code there will result gpio usage before gpio request.
> just move gpio request code in spi_sirfsoc_setup before gpio use.

I'm still having a hard time understanding why pulling the code earlier
in probe isn't a better fix here.
Barry Song Sept. 7, 2014, 12:50 a.m. UTC | #4
On 14-9-6 ??9:57, "Mark Brown" <broonie@kernel.org> wrote:

>On Fri, Sep 05, 2014 at 11:34:57AM +0800, swingboard wrote:
>> 2014-09-05 3:19 GMT+08:00 Mark Brown <broonie@kernel.org>:
>
>> > I'm not quite sure I understand the rationale here - as far as I can
>> > tell this is making the GPIO request happen later not earlier so it's
>> > not clear to me what the problem this is fixing in the existing code.
>> > If the goal is to move the request around in the probe function why
>>not
>> > just move the existing code earlier in probe()?
>
>> As GPIO cs can be high or low validate and the used GPIO pin with
>> default value may high or low,
>> it is need do spi device's chipselect invalidation work in spi_setup,
>> the patch purpose for it.
>> master->cs_gpios only assigned after spi_bitbang_start and the
>> function call spi_setup,
>> if keep the existing code there will result gpio usage before gpio
>>request.
>> just move gpio request code in spi_sirfsoc_setup before gpio use.
>
>I'm still having a hard time understanding why pulling the code earlier
>in probe isn't a better fix here.

Gpio is unknown before spi_bitbang_start(). Everything is done in the big
routine spi_bitbang_start(). It includes:
Get cs_gpios, extend spi devices, and setup cs to de-active.

-barry


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Barry Song April 28, 2015, 3:36 a.m. UTC | #5
>>
>>> > I'm not quite sure I understand the rationale here - as far as I can
>>> > tell this is making the GPIO request happen later not earlier so it's
>>> > not clear to me what the problem this is fixing in the existing code.
>>> > If the goal is to move the request around in the probe function why
>>>not
>>> > just move the existing code earlier in probe()?
>>
>>> As GPIO cs can be high or low validate and the used GPIO pin with
>>> default value may high or low,
>>> it is need do spi device's chipselect invalidation work in spi_setup,
>>> the patch purpose for it.
>>> master->cs_gpios only assigned after spi_bitbang_start and the
>>> function call spi_setup,
>>> if keep the existing code there will result gpio usage before gpio
>>>request.
>>> just move gpio request code in spi_sirfsoc_setup before gpio use.
>>
>>I'm still having a hard time understanding why pulling the code earlier
>>in probe isn't a better fix here.
>
> Gpio is unknown before spi_bitbang_start(). Everything is done in the big
> routine spi_bitbang_start(). It includes:
> Get cs_gpios, extend spi devices, and setup cs to de-active.

Mark, i'd like to re-call this patch. "pulling the code earlier in
probe" is impossible based on current SPI core codes. because before
spi master is registerred,
cs_gpios is NULL. but once it is registered, cs_gpios are assigned in
spi_register_master:

1446 static int of_spi_register_master(struct spi_master *master)
1447 {
1448         int nb, i, *cs;
1449         struct device_node *np = master->dev.of_node;
1450
1451         if (!np)
1452                 return 0;
1453
1454         nb = of_gpio_named_count(np, "cs-gpios");
1455         master->num_chipselect = max_t(int, nb, master->num_chipselect);
1456
1457         /* Return error only for an incorrectly formed cs-gpios property */
1458         if (nb == 0 || nb == -ENOENT)
1459                 return 0;
1460         else if (nb < 0)
1461                 return nb;
1462
1463         cs = devm_kzalloc(&master->dev,
1464                           sizeof(int) * master->num_chipselect,
1465                           GFP_KERNEL);
1466         master->cs_gpios = cs;
1467
1468         if (!master->cs_gpios)
1469                 return -ENOMEM;
1470
1471         for (i = 0; i < master->num_chipselect; i++)
1472                 cs[i] = -ENOENT;
1473
1474         for (i = 0; i < nb; i++)
1475                 cs[i] = of_get_named_gpio(np, "cs-gpios", i);


we can get cs_gpios earlier in probe(), but this will definitely
reduplicated with SPI core.

and in the setup() stage, we need the CS to be de-active, so we need
the cs_gpio. that means we have to move gpio_request codes earlier,
but the current SPI core stop us from get ting gpio earlier than
spi_bitbang_start() being called. it looks the setup() itself is the
best place to get the cs.

drivers/spi/spi-clps711x.c is doing cs_gpios earlier in probe(), but
it is a non-OF driver, which will not have of_spi_register_master() to
set cs_gpios.


-barry
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown April 30, 2015, 10:16 a.m. UTC | #6
On Tue, Apr 28, 2015 at 11:36:51AM +0800, Barry Song wrote:

> Mark, i'd like to re-call this patch. "pulling the code earlier in
> probe" is impossible based on current SPI core codes. because before
> spi master is registerred,
> cs_gpios is NULL. but once it is registered, cs_gpios are assigned in
> spi_register_master:

I'm afraid I've forgotten what this patch is, sorry.  Can you resend
please?

Patch
diff mbox

diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index 44ec3bb..a21e423 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -626,7 +626,7 @@  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;
-
+	int ret = 0;
 	if (!spi->max_speed_hz)
 		return -EINVAL;
 
@@ -634,9 +634,41 @@  static int spi_sirfsoc_setup(struct spi_device *spi)
 
 	if (spi->cs_gpio == -ENOENT)
 		sspi->hw_cs = true;
-	else
+	else {
 		sspi->hw_cs = false;
-	return spi_sirfsoc_setup_transfer(spi, NULL);
+		if (!spi_get_ctldata(spi)) {
+			void *cs = kmalloc(sizeof(int), GFP_KERNEL);
+			if (!cs) {
+				ret = -ENOMEM;
+				goto exit;
+			}
+			ret = gpio_is_valid(spi->cs_gpio);
+			if (!ret) {
+				dev_err(&spi->dev, "no valid gpio\n");
+				ret = -ENOENT;
+				goto exit;
+			}
+			ret = gpio_request(spi->cs_gpio, DRIVER_NAME);
+			if (ret) {
+				dev_err(&spi->dev, "failed to request gpio\n");
+				goto exit;
+			}
+			spi_set_ctldata(spi, cs);
+		}
+	}
+	writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | SIRFSOC_SPI_CS_IO_MODE,
+			sspi->base + SIRFSOC_SPI_CTRL);
+	spi_sirfsoc_chipselect(spi, BITBANG_CS_INACTIVE);
+exit:
+	return ret;
+}
+
+static void spi_sirfsoc_cleanup(struct spi_device *spi)
+{
+	if (spi_get_ctldata(spi)) {
+		gpio_free(spi->cs_gpio);
+		kfree(spi_get_ctldata(spi));
+	}
 }
 
 static int spi_sirfsoc_probe(struct platform_device *pdev)
@@ -645,7 +677,7 @@  static int spi_sirfsoc_probe(struct platform_device *pdev)
 	struct spi_master *master;
 	struct resource *mem_res;
 	int irq;
-	int i, ret;
+	int ret;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
 	if (!master) {
@@ -677,6 +709,7 @@  static int spi_sirfsoc_probe(struct platform_device *pdev)
 	sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer;
 	sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
 	sspi->bitbang.master->setup = spi_sirfsoc_setup;
+	sspi->bitbang.master->cleanup = spi_sirfsoc_cleanup;
 	master->bus_num = pdev->id;
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
 	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
@@ -723,22 +756,7 @@  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;
-		}
-	}
+		goto free_clk;
 	dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num);
 
 	return 0;