diff options
author | Martin Sperl <kernel@martin.sperl.org> | 2015-03-26 06:08:36 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-26 21:28:44 -0400 |
commit | e34ff011c70e5f4ef219141711142d5111ae6ebb (patch) | |
tree | c245a490e7007e28b12ec5eabde7ea4ef3d3fc78 | |
parent | 1be38e041f8eaa935f370aa0f34dd7a2fe39b1d8 (diff) |
spi: bcm2835: move to the transfer_one driver model
This also allows for GPIO-CS to get used removing the limitation of
2/3 SPI devises on the SPI bus.
Fixes: spi-cs-high with native CS with multiple devices on the spi-bus
resetting the chip selects to "normal" polarity after a finished
transfer.
No other functionality/improvements added.
Tested with the following 4 devices on the spi-bus:
* mcp2515 with native CS
* mcp2515 with gpio CS
* fb_st7735r with native CS
(plus spi-cs-high via transistor inverting polarity)
* enc28j60 with gpio-CS
Tested-by: Martin Sperl <kernel@martin.sperl.org>
Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/spi/spi-bcm2835.c | 212 |
1 files changed, 124 insertions, 88 deletions
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 3f93718aad3f..0dbe544e8be4 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2012 Chris Boot | 4 | * Copyright (C) 2012 Chris Boot |
5 | * Copyright (C) 2013 Stephen Warren | 5 | * Copyright (C) 2013 Stephen Warren |
6 | * Copyright (C) 2015 Martin Sperl | ||
6 | * | 7 | * |
7 | * This driver is inspired by: | 8 | * This driver is inspired by: |
8 | * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> | 9 | * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> |
@@ -29,6 +30,7 @@ | |||
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/of.h> | 31 | #include <linux/of.h> |
31 | #include <linux/of_irq.h> | 32 | #include <linux/of_irq.h> |
33 | #include <linux/of_gpio.h> | ||
32 | #include <linux/of_device.h> | 34 | #include <linux/of_device.h> |
33 | #include <linux/spi/spi.h> | 35 | #include <linux/spi/spi.h> |
34 | 36 | ||
@@ -76,10 +78,10 @@ struct bcm2835_spi { | |||
76 | void __iomem *regs; | 78 | void __iomem *regs; |
77 | struct clk *clk; | 79 | struct clk *clk; |
78 | int irq; | 80 | int irq; |
79 | struct completion done; | ||
80 | const u8 *tx_buf; | 81 | const u8 *tx_buf; |
81 | u8 *rx_buf; | 82 | u8 *rx_buf; |
82 | int len; | 83 | int tx_len; |
84 | int rx_len; | ||
83 | }; | 85 | }; |
84 | 86 | ||
85 | static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg) | 87 | static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg) |
@@ -96,10 +98,12 @@ static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) | |||
96 | { | 98 | { |
97 | u8 byte; | 99 | u8 byte; |
98 | 100 | ||
99 | while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { | 101 | while ((bs->rx_len) && |
102 | (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) { | ||
100 | byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); | 103 | byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); |
101 | if (bs->rx_buf) | 104 | if (bs->rx_buf) |
102 | *bs->rx_buf++ = byte; | 105 | *bs->rx_buf++ = byte; |
106 | bs->rx_len--; | ||
103 | } | 107 | } |
104 | } | 108 | } |
105 | 109 | ||
@@ -107,47 +111,60 @@ static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) | |||
107 | { | 111 | { |
108 | u8 byte; | 112 | u8 byte; |
109 | 113 | ||
110 | while ((bs->len) && | 114 | while ((bs->tx_len) && |
111 | (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { | 115 | (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { |
112 | byte = bs->tx_buf ? *bs->tx_buf++ : 0; | 116 | byte = bs->tx_buf ? *bs->tx_buf++ : 0; |
113 | bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); | 117 | bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); |
114 | bs->len--; | 118 | bs->tx_len--; |
115 | } | 119 | } |
116 | } | 120 | } |
117 | 121 | ||
122 | static void bcm2835_spi_reset_hw(struct spi_master *master) | ||
123 | { | ||
124 | struct bcm2835_spi *bs = spi_master_get_devdata(master); | ||
125 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); | ||
126 | |||
127 | /* Disable SPI interrupts and transfer */ | ||
128 | cs &= ~(BCM2835_SPI_CS_INTR | | ||
129 | BCM2835_SPI_CS_INTD | | ||
130 | BCM2835_SPI_CS_TA); | ||
131 | /* and reset RX/TX FIFOS */ | ||
132 | cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; | ||
133 | |||
134 | /* and reset the SPI_HW */ | ||
135 | bcm2835_wr(bs, BCM2835_SPI_CS, cs); | ||
136 | } | ||
137 | |||
118 | static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) | 138 | static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) |
119 | { | 139 | { |
120 | struct spi_master *master = dev_id; | 140 | struct spi_master *master = dev_id; |
121 | struct bcm2835_spi *bs = spi_master_get_devdata(master); | 141 | struct bcm2835_spi *bs = spi_master_get_devdata(master); |
122 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); | ||
123 | 142 | ||
124 | /* Read as many bytes as possible from FIFO */ | 143 | /* Read as many bytes as possible from FIFO */ |
125 | bcm2835_rd_fifo(bs); | 144 | bcm2835_rd_fifo(bs); |
126 | 145 | /* Write as many bytes as possible to FIFO */ | |
127 | if (bs->len) { /* there is more data to transmit */ | 146 | bcm2835_wr_fifo(bs); |
128 | bcm2835_wr_fifo(bs); | 147 | |
129 | } else { /* Transfer complete */ | 148 | /* based on flags decide if we can finish the transfer */ |
130 | /* Disable SPI interrupts */ | 149 | if (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE) { |
131 | cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); | 150 | /* Transfer complete - reset SPI HW */ |
132 | bcm2835_wr(bs, BCM2835_SPI_CS, cs); | 151 | bcm2835_spi_reset_hw(master); |
133 | 152 | /* wake up the framework */ | |
134 | /* | 153 | complete(&master->xfer_completion); |
135 | * Wake up bcm2835_spi_transfer_one(), which will call | ||
136 | * bcm2835_spi_finish_transfer(), to drain the RX FIFO. | ||
137 | */ | ||
138 | complete(&bs->done); | ||
139 | } | 154 | } |
140 | 155 | ||
141 | return IRQ_HANDLED; | 156 | return IRQ_HANDLED; |
142 | } | 157 | } |
143 | 158 | ||
144 | static int bcm2835_spi_start_transfer(struct spi_device *spi, | 159 | static int bcm2835_spi_transfer_one(struct spi_master *master, |
145 | struct spi_transfer *tfr) | 160 | struct spi_device *spi, |
161 | struct spi_transfer *tfr) | ||
146 | { | 162 | { |
147 | struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); | 163 | struct bcm2835_spi *bs = spi_master_get_devdata(master); |
148 | unsigned long spi_hz, clk_hz, cdiv; | 164 | unsigned long spi_hz, clk_hz, cdiv; |
149 | u32 cs = BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; | 165 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); |
150 | 166 | ||
167 | /* set clock */ | ||
151 | spi_hz = tfr->speed_hz; | 168 | spi_hz = tfr->speed_hz; |
152 | clk_hz = clk_get_rate(bs->clk); | 169 | clk_hz = clk_get_rate(bs->clk); |
153 | 170 | ||
@@ -163,100 +180,118 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, | |||
163 | } else { | 180 | } else { |
164 | cdiv = 0; /* 0 is the slowest we can go */ | 181 | cdiv = 0; /* 0 is the slowest we can go */ |
165 | } | 182 | } |
183 | bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); | ||
166 | 184 | ||
185 | /* handle all the modes */ | ||
167 | if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) | 186 | if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) |
168 | cs |= BCM2835_SPI_CS_REN; | 187 | cs |= BCM2835_SPI_CS_REN; |
169 | |||
170 | if (spi->mode & SPI_CPOL) | 188 | if (spi->mode & SPI_CPOL) |
171 | cs |= BCM2835_SPI_CS_CPOL; | 189 | cs |= BCM2835_SPI_CS_CPOL; |
172 | if (spi->mode & SPI_CPHA) | 190 | if (spi->mode & SPI_CPHA) |
173 | cs |= BCM2835_SPI_CS_CPHA; | 191 | cs |= BCM2835_SPI_CS_CPHA; |
174 | 192 | ||
175 | if (!(spi->mode & SPI_NO_CS)) { | 193 | /* for gpio_cs set dummy CS so that no HW-CS get changed |
176 | if (spi->mode & SPI_CS_HIGH) { | 194 | * we can not run this in bcm2835_spi_set_cs, as it does |
177 | cs |= BCM2835_SPI_CS_CSPOL; | 195 | * not get called for cs_gpio cases, so we need to do it here |
178 | cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; | 196 | */ |
179 | } | 197 | if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS)) |
180 | 198 | cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; | |
181 | cs |= spi->chip_select; | ||
182 | } | ||
183 | 199 | ||
184 | reinit_completion(&bs->done); | 200 | /* set transmit buffers and length */ |
185 | bs->tx_buf = tfr->tx_buf; | 201 | bs->tx_buf = tfr->tx_buf; |
186 | bs->rx_buf = tfr->rx_buf; | 202 | bs->rx_buf = tfr->rx_buf; |
187 | bs->len = tfr->len; | 203 | bs->tx_len = tfr->len; |
204 | bs->rx_len = tfr->len; | ||
188 | 205 | ||
189 | bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); | ||
190 | /* | 206 | /* |
191 | * Enable the HW block. This will immediately trigger a DONE (TX | 207 | * Enable the HW block. This will immediately trigger a DONE (TX |
192 | * empty) interrupt, upon which we will fill the TX FIFO with the | 208 | * empty) interrupt, upon which we will fill the TX FIFO with the |
193 | * first TX bytes. Pre-filling the TX FIFO here to avoid the | 209 | * first TX bytes. Pre-filling the TX FIFO here to avoid the |
194 | * interrupt doesn't work:-( | 210 | * interrupt doesn't work:-( |
195 | */ | 211 | */ |
212 | cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; | ||
196 | bcm2835_wr(bs, BCM2835_SPI_CS, cs); | 213 | bcm2835_wr(bs, BCM2835_SPI_CS, cs); |
197 | 214 | ||
198 | return 0; | 215 | /* signal that we need to wait for completion */ |
216 | return 1; | ||
199 | } | 217 | } |
200 | 218 | ||
201 | static int bcm2835_spi_finish_transfer(struct spi_device *spi, | 219 | static void bcm2835_spi_handle_err(struct spi_master *master, |
202 | struct spi_transfer *tfr, | 220 | struct spi_message *msg) |
203 | bool cs_change) | ||
204 | { | 221 | { |
205 | struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); | 222 | bcm2835_spi_reset_hw(master); |
206 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); | ||
207 | |||
208 | if (tfr->delay_usecs) | ||
209 | udelay(tfr->delay_usecs); | ||
210 | |||
211 | if (cs_change) | ||
212 | /* Clear TA flag */ | ||
213 | bcm2835_wr(bs, BCM2835_SPI_CS, cs & ~BCM2835_SPI_CS_TA); | ||
214 | |||
215 | return 0; | ||
216 | } | 223 | } |
217 | 224 | ||
218 | static int bcm2835_spi_transfer_one(struct spi_master *master, | 225 | static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) |
219 | struct spi_message *mesg) | ||
220 | { | 226 | { |
227 | /* | ||
228 | * we can assume that we are "native" as per spi_set_cs | ||
229 | * calling us ONLY when cs_gpio is not set | ||
230 | * we can also assume that we are CS < 3 as per bcm2835_spi_setup | ||
231 | * we would not get called because of error handling there. | ||
232 | * the level passed is the electrical level not enabled/disabled | ||
233 | * so it has to get translated back to enable/disable | ||
234 | * see spi_set_cs in spi.c for the implementation | ||
235 | */ | ||
236 | |||
237 | struct spi_master *master = spi->master; | ||
221 | struct bcm2835_spi *bs = spi_master_get_devdata(master); | 238 | struct bcm2835_spi *bs = spi_master_get_devdata(master); |
222 | struct spi_transfer *tfr; | 239 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); |
223 | struct spi_device *spi = mesg->spi; | 240 | bool enable; |
224 | int err = 0; | ||
225 | unsigned int timeout; | ||
226 | bool cs_change; | ||
227 | |||
228 | list_for_each_entry(tfr, &mesg->transfers, transfer_list) { | ||
229 | err = bcm2835_spi_start_transfer(spi, tfr); | ||
230 | if (err) | ||
231 | goto out; | ||
232 | |||
233 | timeout = wait_for_completion_timeout( | ||
234 | &bs->done, | ||
235 | msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) | ||
236 | ); | ||
237 | if (!timeout) { | ||
238 | err = -ETIMEDOUT; | ||
239 | goto out; | ||
240 | } | ||
241 | 241 | ||
242 | cs_change = tfr->cs_change || | 242 | /* calculate the enable flag from the passed gpio_level */ |
243 | list_is_last(&tfr->transfer_list, &mesg->transfers); | 243 | enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level; |
244 | 244 | ||
245 | err = bcm2835_spi_finish_transfer(spi, tfr, cs_change); | 245 | /* set flags for "reverse" polarity in the registers */ |
246 | if (err) | 246 | if (spi->mode & SPI_CS_HIGH) { |
247 | goto out; | 247 | /* set the correct CS-bits */ |
248 | cs |= BCM2835_SPI_CS_CSPOL; | ||
249 | cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; | ||
250 | } else { | ||
251 | /* clean the CS-bits */ | ||
252 | cs &= ~BCM2835_SPI_CS_CSPOL; | ||
253 | cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select); | ||
254 | } | ||
248 | 255 | ||
249 | mesg->actual_length += (tfr->len - bs->len); | 256 | /* select the correct chip_select depending on disabled/enabled */ |
257 | if (enable) { | ||
258 | /* set cs correctly */ | ||
259 | if (spi->mode & SPI_NO_CS) { | ||
260 | /* use the "undefined" chip-select */ | ||
261 | cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; | ||
262 | } else { | ||
263 | /* set the chip select */ | ||
264 | cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01); | ||
265 | cs |= spi->chip_select; | ||
266 | } | ||
267 | } else { | ||
268 | /* disable CSPOL which puts HW-CS into deselected state */ | ||
269 | cs &= ~BCM2835_SPI_CS_CSPOL; | ||
270 | /* use the "undefined" chip-select as precaution */ | ||
271 | cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; | ||
250 | } | 272 | } |
251 | 273 | ||
252 | out: | 274 | /* finally set the calculated flags in SPI_CS */ |
253 | /* Clear FIFOs, and disable the HW block */ | 275 | bcm2835_wr(bs, BCM2835_SPI_CS, cs); |
254 | bcm2835_wr(bs, BCM2835_SPI_CS, | 276 | } |
255 | BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); | ||
256 | mesg->status = err; | ||
257 | spi_finalize_current_message(master); | ||
258 | 277 | ||
259 | return 0; | 278 | static int bcm2835_spi_setup(struct spi_device *spi) |
279 | { | ||
280 | /* | ||
281 | * sanity checking the native-chipselects | ||
282 | */ | ||
283 | if (spi->mode & SPI_NO_CS) | ||
284 | return 0; | ||
285 | if (gpio_is_valid(spi->cs_gpio)) | ||
286 | return 0; | ||
287 | if (spi->chip_select < 3) | ||
288 | return 0; | ||
289 | |||
290 | /* error in the case of native CS requested with CS-id > 2 */ | ||
291 | dev_err(&spi->dev, | ||
292 | "setup: only three native chip-selects are supported\n" | ||
293 | ); | ||
294 | return -EINVAL; | ||
260 | } | 295 | } |
261 | 296 | ||
262 | static int bcm2835_spi_probe(struct platform_device *pdev) | 297 | static int bcm2835_spi_probe(struct platform_device *pdev) |
@@ -277,13 +312,14 @@ static int bcm2835_spi_probe(struct platform_device *pdev) | |||
277 | master->mode_bits = BCM2835_SPI_MODE_BITS; | 312 | master->mode_bits = BCM2835_SPI_MODE_BITS; |
278 | master->bits_per_word_mask = SPI_BPW_MASK(8); | 313 | master->bits_per_word_mask = SPI_BPW_MASK(8); |
279 | master->num_chipselect = 3; | 314 | master->num_chipselect = 3; |
280 | master->transfer_one_message = bcm2835_spi_transfer_one; | 315 | master->setup = bcm2835_spi_setup; |
316 | master->set_cs = bcm2835_spi_set_cs; | ||
317 | master->transfer_one = bcm2835_spi_transfer_one; | ||
318 | master->handle_err = bcm2835_spi_handle_err; | ||
281 | master->dev.of_node = pdev->dev.of_node; | 319 | master->dev.of_node = pdev->dev.of_node; |
282 | 320 | ||
283 | bs = spi_master_get_devdata(master); | 321 | bs = spi_master_get_devdata(master); |
284 | 322 | ||
285 | init_completion(&bs->done); | ||
286 | |||
287 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 323 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
288 | bs->regs = devm_ioremap_resource(&pdev->dev, res); | 324 | bs->regs = devm_ioremap_resource(&pdev->dev, res); |
289 | if (IS_ERR(bs->regs)) { | 325 | if (IS_ERR(bs->regs)) { |
@@ -314,7 +350,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) | |||
314 | goto out_clk_disable; | 350 | goto out_clk_disable; |
315 | } | 351 | } |
316 | 352 | ||
317 | /* initialise the hardware */ | 353 | /* initialise the hardware with the default polarities */ |
318 | bcm2835_wr(bs, BCM2835_SPI_CS, | 354 | bcm2835_wr(bs, BCM2835_SPI_CS, |
319 | BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); | 355 | BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); |
320 | 356 | ||