summaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/patches-3.3/204-spi-ath79-avoid-multiple-initialization-of-the-SPI-c.patch
blob: 084bd98bbeae6770b757ff5fde500dfd4ae73848 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
From e63ceaa0c4f7be0498cd452981073d3ce8e7d1f5 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 9 Jan 2012 15:00:46 +0100
Subject: [PATCH 32/34] spi/ath79: avoid multiple initialization of the SPI controller

Currently we are initializing the SPI controller in
the chip select line function, and that function is
called once for each SPI device on the bus. If a
board has multiple SPI devices, the controller will
be initialized multiple times.

Introduce ath79_spi_{en,dis}able helper functions,
and call those from probe/response in order to avoid
the mutliple initialization of the controller.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/spi/spi-ath79.c |   41 ++++++++++++++++++++++++-----------------
 1 files changed, 24 insertions(+), 17 deletions(-)

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -96,16 +96,8 @@ static void ath79_spi_chipselect(struct
 
 }
 
-static int ath79_spi_setup_cs(struct spi_device *spi)
+static void ath79_spi_enable(struct ath79_spi *sp)
 {
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-	struct ath79_spi_controller_data *cdata;
-	int status;
-
-	cdata = spi->controller_data;
-	if (spi->chip_select && !cdata)
-		return -EINVAL;
-
 	/* enable GPIO mode */
 	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
 
@@ -115,6 +107,24 @@ static int ath79_spi_setup_cs(struct spi
 
 	/* TODO: setup speed? */
 	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
+}
+
+static void ath79_spi_disable(struct ath79_spi *sp)
+{
+	/* restore CTRL register */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
+	/* disable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+}
+
+static int ath79_spi_setup_cs(struct spi_device *spi)
+{
+	struct ath79_spi_controller_data *cdata;
+	int status;
+
+	cdata = spi->controller_data;
+	if (spi->chip_select && !cdata)
+		return -EINVAL;
 
 	status = 0;
 	if (spi->chip_select) {
@@ -135,17 +145,10 @@ static int ath79_spi_setup_cs(struct spi
 
 static void ath79_spi_cleanup_cs(struct spi_device *spi)
 {
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-
 	if (spi->chip_select) {
 		struct ath79_spi_controller_data *cdata = spi->controller_data;
 		gpio_free(cdata->gpio);
 	}
-
-	/* restore CTRL register */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
-	/* disable GPIO mode */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
 }
 
 static int ath79_spi_setup(struct spi_device *spi)
@@ -271,12 +274,15 @@ static __devinit int ath79_spi_probe(str
 	dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
 		sp->rrw_delay);
 
+	ath79_spi_enable(sp);
 	ret = spi_bitbang_start(&sp->bitbang);
 	if (ret)
-		goto err_clk_disable;
+		goto err_disable;
 
 	return 0;
 
+err_disable:
+	ath79_spi_disable(sp);
 err_clk_disable:
 	clk_disable(sp->clk);
 err_clk_put:
@@ -295,6 +301,7 @@ static __devexit int ath79_spi_remove(st
 	struct ath79_spi *sp = platform_get_drvdata(pdev);
 
 	spi_bitbang_stop(&sp->bitbang);
+	ath79_spi_disable(sp);
 	clk_disable(sp->clk);
 	clk_put(sp->clk);
 	iounmap(sp->base);