Message ID | 1409648468-5436-3-git-send-email-Barry.Song@csr.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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.
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.
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.
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
>> >>> > 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
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?
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;