| 1 | From e63ceaa0c4f7be0498cd452981073d3ce8e7d1f5 Mon Sep 17 00:00:00 2001 |
| 2 | From: Gabor Juhos <juhosg@openwrt.org> |
| 3 | Date: Mon, 9 Jan 2012 15:00:46 +0100 |
| 4 | Subject: [PATCH 32/34] spi/ath79: avoid multiple initialization of the SPI controller |
| 5 | |
| 6 | Currently we are initializing the SPI controller in |
| 7 | the chip select line function, and that function is |
| 8 | called once for each SPI device on the bus. If a |
| 9 | board has multiple SPI devices, the controller will |
| 10 | be initialized multiple times. |
| 11 | |
| 12 | Introduce ath79_spi_{en,dis}able helper functions, |
| 13 | and call those from probe/response in order to avoid |
| 14 | the mutliple initialization of the controller. |
| 15 | |
| 16 | Signed-off-by: Gabor Juhos <juhosg@openwrt.org> |
| 17 | --- |
| 18 | drivers/spi/spi-ath79.c | 41 ++++++++++++++++++++++++----------------- |
| 19 | 1 files changed, 24 insertions(+), 17 deletions(-) |
| 20 | |
| 21 | --- a/drivers/spi/spi-ath79.c |
| 22 | +++ b/drivers/spi/spi-ath79.c |
| 23 | @@ -96,16 +96,8 @@ static void ath79_spi_chipselect(struct |
| 24 | |
| 25 | } |
| 26 | |
| 27 | -static int ath79_spi_setup_cs(struct spi_device *spi) |
| 28 | +static void ath79_spi_enable(struct ath79_spi *sp) |
| 29 | { |
| 30 | - struct ath79_spi *sp = ath79_spidev_to_sp(spi); |
| 31 | - struct ath79_spi_controller_data *cdata; |
| 32 | - int status; |
| 33 | - |
| 34 | - cdata = spi->controller_data; |
| 35 | - if (spi->chip_select && !cdata) |
| 36 | - return -EINVAL; |
| 37 | - |
| 38 | /* enable GPIO mode */ |
| 39 | ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); |
| 40 | |
| 41 | @@ -115,6 +107,24 @@ static int ath79_spi_setup_cs(struct spi |
| 42 | |
| 43 | /* TODO: setup speed? */ |
| 44 | ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); |
| 45 | +} |
| 46 | + |
| 47 | +static void ath79_spi_disable(struct ath79_spi *sp) |
| 48 | +{ |
| 49 | + /* restore CTRL register */ |
| 50 | + ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); |
| 51 | + /* disable GPIO mode */ |
| 52 | + ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); |
| 53 | +} |
| 54 | + |
| 55 | +static int ath79_spi_setup_cs(struct spi_device *spi) |
| 56 | +{ |
| 57 | + struct ath79_spi_controller_data *cdata; |
| 58 | + int status; |
| 59 | + |
| 60 | + cdata = spi->controller_data; |
| 61 | + if (spi->chip_select && !cdata) |
| 62 | + return -EINVAL; |
| 63 | |
| 64 | status = 0; |
| 65 | if (spi->chip_select) { |
| 66 | @@ -135,17 +145,10 @@ static int ath79_spi_setup_cs(struct spi |
| 67 | |
| 68 | static void ath79_spi_cleanup_cs(struct spi_device *spi) |
| 69 | { |
| 70 | - struct ath79_spi *sp = ath79_spidev_to_sp(spi); |
| 71 | - |
| 72 | if (spi->chip_select) { |
| 73 | struct ath79_spi_controller_data *cdata = spi->controller_data; |
| 74 | gpio_free(cdata->gpio); |
| 75 | } |
| 76 | - |
| 77 | - /* restore CTRL register */ |
| 78 | - ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); |
| 79 | - /* disable GPIO mode */ |
| 80 | - ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); |
| 81 | } |
| 82 | |
| 83 | static int ath79_spi_setup(struct spi_device *spi) |
| 84 | @@ -271,12 +274,15 @@ static __devinit int ath79_spi_probe(str |
| 85 | dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n", |
| 86 | sp->rrw_delay); |
| 87 | |
| 88 | + ath79_spi_enable(sp); |
| 89 | ret = spi_bitbang_start(&sp->bitbang); |
| 90 | if (ret) |
| 91 | - goto err_clk_disable; |
| 92 | + goto err_disable; |
| 93 | |
| 94 | return 0; |
| 95 | |
| 96 | +err_disable: |
| 97 | + ath79_spi_disable(sp); |
| 98 | err_clk_disable: |
| 99 | clk_disable(sp->clk); |
| 100 | err_clk_put: |
| 101 | @@ -295,6 +301,7 @@ static __devexit int ath79_spi_remove(st |
| 102 | struct ath79_spi *sp = platform_get_drvdata(pdev); |
| 103 | |
| 104 | spi_bitbang_stop(&sp->bitbang); |
| 105 | + ath79_spi_disable(sp); |
| 106 | clk_disable(sp->clk); |
| 107 | clk_put(sp->clk); |
| 108 | iounmap(sp->base); |
| 109 | |