Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

Linux/drivers/spi/spi-orion.c

  1 /*
  2  * Marvell Orion SPI controller driver
  3  *
  4  * Author: Shadi Ammouri <shadi@marvell.com>
  5  * Copyright (C) 2007-2008 Marvell Ltd.
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
 10  */
 11 
 12 #include <linux/interrupt.h>
 13 #include <linux/delay.h>
 14 #include <linux/platform_device.h>
 15 #include <linux/err.h>
 16 #include <linux/io.h>
 17 #include <linux/spi/spi.h>
 18 #include <linux/module.h>
 19 #include <linux/pm_runtime.h>
 20 #include <linux/of.h>
 21 #include <linux/clk.h>
 22 #include <linux/sizes.h>
 23 #include <asm/unaligned.h>
 24 
 25 #define DRIVER_NAME                     "orion_spi"
 26 
 27 /* Runtime PM autosuspend timeout: PM is fairly light on this driver */
 28 #define SPI_AUTOSUSPEND_TIMEOUT         200
 29 
 30 #define ORION_NUM_CHIPSELECTS           1 /* only one slave is supported*/
 31 #define ORION_SPI_WAIT_RDY_MAX_LOOP     2000 /* in usec */
 32 
 33 #define ORION_SPI_IF_CTRL_REG           0x00
 34 #define ORION_SPI_IF_CONFIG_REG         0x04
 35 #define ORION_SPI_DATA_OUT_REG          0x08
 36 #define ORION_SPI_DATA_IN_REG           0x0c
 37 #define ORION_SPI_INT_CAUSE_REG         0x10
 38 
 39 #define ORION_SPI_MODE_CPOL             (1 << 11)
 40 #define ORION_SPI_MODE_CPHA             (1 << 12)
 41 #define ORION_SPI_IF_8_16_BIT_MODE      (1 << 5)
 42 #define ORION_SPI_CLK_PRESCALE_MASK     0x1F
 43 #define ORION_SPI_MODE_MASK             (ORION_SPI_MODE_CPOL | \
 44                                          ORION_SPI_MODE_CPHA)
 45 
 46 struct orion_spi {
 47         struct spi_master       *master;
 48         void __iomem            *base;
 49         struct clk              *clk;
 50 };
 51 
 52 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
 53 {
 54         return orion_spi->base + reg;
 55 }
 56 
 57 static inline void
 58 orion_spi_setbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
 59 {
 60         void __iomem *reg_addr = spi_reg(orion_spi, reg);
 61         u32 val;
 62 
 63         val = readl(reg_addr);
 64         val |= mask;
 65         writel(val, reg_addr);
 66 }
 67 
 68 static inline void
 69 orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
 70 {
 71         void __iomem *reg_addr = spi_reg(orion_spi, reg);
 72         u32 val;
 73 
 74         val = readl(reg_addr);
 75         val &= ~mask;
 76         writel(val, reg_addr);
 77 }
 78 
 79 static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
 80 {
 81         u32 tclk_hz;
 82         u32 rate;
 83         u32 prescale;
 84         u32 reg;
 85         struct orion_spi *orion_spi;
 86 
 87         orion_spi = spi_master_get_devdata(spi->master);
 88 
 89         tclk_hz = clk_get_rate(orion_spi->clk);
 90 
 91         /*
 92          * the supported rates are: 4,6,8...30
 93          * round up as we look for equal or less speed
 94          */
 95         rate = DIV_ROUND_UP(tclk_hz, speed);
 96         rate = roundup(rate, 2);
 97 
 98         /* check if requested speed is too small */
 99         if (rate > 30)
100                 return -EINVAL;
101 
102         if (rate < 4)
103                 rate = 4;
104 
105         /* Convert the rate to SPI clock divisor value. */
106         prescale = 0x10 + rate/2;
107 
108         reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
109         reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale);
110         writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
111 
112         return 0;
113 }
114 
115 static void
116 orion_spi_mode_set(struct spi_device *spi)
117 {
118         u32 reg;
119         struct orion_spi *orion_spi;
120 
121         orion_spi = spi_master_get_devdata(spi->master);
122 
123         reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
124         reg &= ~ORION_SPI_MODE_MASK;
125         if (spi->mode & SPI_CPOL)
126                 reg |= ORION_SPI_MODE_CPOL;
127         if (spi->mode & SPI_CPHA)
128                 reg |= ORION_SPI_MODE_CPHA;
129         writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
130 }
131 
132 /*
133  * called only when no transfer is active on the bus
134  */
135 static int
136 orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
137 {
138         struct orion_spi *orion_spi;
139         unsigned int speed = spi->max_speed_hz;
140         unsigned int bits_per_word = spi->bits_per_word;
141         int     rc;
142 
143         orion_spi = spi_master_get_devdata(spi->master);
144 
145         if ((t != NULL) && t->speed_hz)
146                 speed = t->speed_hz;
147 
148         if ((t != NULL) && t->bits_per_word)
149                 bits_per_word = t->bits_per_word;
150 
151         orion_spi_mode_set(spi);
152 
153         rc = orion_spi_baudrate_set(spi, speed);
154         if (rc)
155                 return rc;
156 
157         if (bits_per_word == 16)
158                 orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
159                                   ORION_SPI_IF_8_16_BIT_MODE);
160         else
161                 orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
162                                   ORION_SPI_IF_8_16_BIT_MODE);
163 
164         return 0;
165 }
166 
167 static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
168 {
169         if (enable)
170                 orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
171         else
172                 orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
173 }
174 
175 static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
176 {
177         int i;
178 
179         for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) {
180                 if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)))
181                         return 1;
182                 else
183                         udelay(1);
184         }
185 
186         return -1;
187 }
188 
189 static inline int
190 orion_spi_write_read_8bit(struct spi_device *spi,
191                           const u8 **tx_buf, u8 **rx_buf)
192 {
193         void __iomem *tx_reg, *rx_reg, *int_reg;
194         struct orion_spi *orion_spi;
195 
196         orion_spi = spi_master_get_devdata(spi->master);
197         tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
198         rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
199         int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
200 
201         /* clear the interrupt cause register */
202         writel(0x0, int_reg);
203 
204         if (tx_buf && *tx_buf)
205                 writel(*(*tx_buf)++, tx_reg);
206         else
207                 writel(0, tx_reg);
208 
209         if (orion_spi_wait_till_ready(orion_spi) < 0) {
210                 dev_err(&spi->dev, "TXS timed out\n");
211                 return -1;
212         }
213 
214         if (rx_buf && *rx_buf)
215                 *(*rx_buf)++ = readl(rx_reg);
216 
217         return 1;
218 }
219 
220 static inline int
221 orion_spi_write_read_16bit(struct spi_device *spi,
222                            const u16 **tx_buf, u16 **rx_buf)
223 {
224         void __iomem *tx_reg, *rx_reg, *int_reg;
225         struct orion_spi *orion_spi;
226 
227         orion_spi = spi_master_get_devdata(spi->master);
228         tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
229         rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
230         int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
231 
232         /* clear the interrupt cause register */
233         writel(0x0, int_reg);
234 
235         if (tx_buf && *tx_buf)
236                 writel(__cpu_to_le16(get_unaligned((*tx_buf)++)), tx_reg);
237         else
238                 writel(0, tx_reg);
239 
240         if (orion_spi_wait_till_ready(orion_spi) < 0) {
241                 dev_err(&spi->dev, "TXS timed out\n");
242                 return -1;
243         }
244 
245         if (rx_buf && *rx_buf)
246                 put_unaligned(__le16_to_cpu(readl(rx_reg)), (*rx_buf)++);
247 
248         return 1;
249 }
250 
251 static unsigned int
252 orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
253 {
254         unsigned int count;
255         int word_len;
256 
257         word_len = spi->bits_per_word;
258         count = xfer->len;
259 
260         if (word_len == 8) {
261                 const u8 *tx = xfer->tx_buf;
262                 u8 *rx = xfer->rx_buf;
263 
264                 do {
265                         if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0)
266                                 goto out;
267                         count--;
268                 } while (count);
269         } else if (word_len == 16) {
270                 const u16 *tx = xfer->tx_buf;
271                 u16 *rx = xfer->rx_buf;
272 
273                 do {
274                         if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0)
275                                 goto out;
276                         count -= 2;
277                 } while (count);
278         }
279 
280 out:
281         return xfer->len - count;
282 }
283 
284 static int orion_spi_transfer_one_message(struct spi_master *master,
285                                            struct spi_message *m)
286 {
287         struct orion_spi *orion_spi = spi_master_get_devdata(master);
288         struct spi_device *spi = m->spi;
289         struct spi_transfer *t = NULL;
290         int par_override = 0;
291         int status = 0;
292         int cs_active = 0;
293 
294         /* Load defaults */
295         status = orion_spi_setup_transfer(spi, NULL);
296 
297         if (status < 0)
298                 goto msg_done;
299 
300         list_for_each_entry(t, &m->transfers, transfer_list) {
301                 if (par_override || t->speed_hz || t->bits_per_word) {
302                         par_override = 1;
303                         status = orion_spi_setup_transfer(spi, t);
304                         if (status < 0)
305                                 break;
306                         if (!t->speed_hz && !t->bits_per_word)
307                                 par_override = 0;
308                 }
309 
310                 if (!cs_active) {
311                         orion_spi_set_cs(orion_spi, 1);
312                         cs_active = 1;
313                 }
314 
315                 if (t->len)
316                         m->actual_length += orion_spi_write_read(spi, t);
317 
318                 if (t->delay_usecs)
319                         udelay(t->delay_usecs);
320 
321                 if (t->cs_change) {
322                         orion_spi_set_cs(orion_spi, 0);
323                         cs_active = 0;
324                 }
325         }
326 
327 msg_done:
328         if (cs_active)
329                 orion_spi_set_cs(orion_spi, 0);
330 
331         m->status = status;
332         spi_finalize_current_message(master);
333 
334         return 0;
335 }
336 
337 static int orion_spi_reset(struct orion_spi *orion_spi)
338 {
339         /* Verify that the CS is deasserted */
340         orion_spi_set_cs(orion_spi, 0);
341 
342         return 0;
343 }
344 
345 static int orion_spi_probe(struct platform_device *pdev)
346 {
347         struct spi_master *master;
348         struct orion_spi *spi;
349         struct resource *r;
350         unsigned long tclk_hz;
351         int status = 0;
352 
353         master = spi_alloc_master(&pdev->dev, sizeof(*spi));
354         if (master == NULL) {
355                 dev_dbg(&pdev->dev, "master allocation failed\n");
356                 return -ENOMEM;
357         }
358 
359         if (pdev->id != -1)
360                 master->bus_num = pdev->id;
361         if (pdev->dev.of_node) {
362                 u32 cell_index;
363                 if (!of_property_read_u32(pdev->dev.of_node, "cell-index",
364                                           &cell_index))
365                         master->bus_num = cell_index;
366         }
367 
368         /* we support only mode 0, and no options */
369         master->mode_bits = SPI_CPHA | SPI_CPOL;
370 
371         master->transfer_one_message = orion_spi_transfer_one_message;
372         master->num_chipselect = ORION_NUM_CHIPSELECTS;
373         master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
374         master->auto_runtime_pm = true;
375 
376         platform_set_drvdata(pdev, master);
377 
378         spi = spi_master_get_devdata(master);
379         spi->master = master;
380 
381         spi->clk = devm_clk_get(&pdev->dev, NULL);
382         if (IS_ERR(spi->clk)) {
383                 status = PTR_ERR(spi->clk);
384                 goto out;
385         }
386 
387         status = clk_prepare_enable(spi->clk);
388         if (status)
389                 goto out;
390 
391         tclk_hz = clk_get_rate(spi->clk);
392         master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4);
393         master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30);
394 
395         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
396         spi->base = devm_ioremap_resource(&pdev->dev, r);
397         if (IS_ERR(spi->base)) {
398                 status = PTR_ERR(spi->base);
399                 goto out_rel_clk;
400         }
401 
402         pm_runtime_set_active(&pdev->dev);
403         pm_runtime_use_autosuspend(&pdev->dev);
404         pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
405         pm_runtime_enable(&pdev->dev);
406 
407         status = orion_spi_reset(spi);
408         if (status < 0)
409                 goto out_rel_pm;
410 
411         pm_runtime_mark_last_busy(&pdev->dev);
412         pm_runtime_put_autosuspend(&pdev->dev);
413 
414         master->dev.of_node = pdev->dev.of_node;
415         status = spi_register_master(master);
416         if (status < 0)
417                 goto out_rel_pm;
418 
419         return status;
420 
421 out_rel_pm:
422         pm_runtime_disable(&pdev->dev);
423 out_rel_clk:
424         clk_disable_unprepare(spi->clk);
425 out:
426         spi_master_put(master);
427         return status;
428 }
429 
430 
431 static int orion_spi_remove(struct platform_device *pdev)
432 {
433         struct spi_master *master = platform_get_drvdata(pdev);
434         struct orion_spi *spi = spi_master_get_devdata(master);
435 
436         pm_runtime_get_sync(&pdev->dev);
437         clk_disable_unprepare(spi->clk);
438 
439         spi_unregister_master(master);
440         pm_runtime_disable(&pdev->dev);
441 
442         return 0;
443 }
444 
445 MODULE_ALIAS("platform:" DRIVER_NAME);
446 
447 #ifdef CONFIG_PM_RUNTIME
448 static int orion_spi_runtime_suspend(struct device *dev)
449 {
450         struct spi_master *master = dev_get_drvdata(dev);
451         struct orion_spi *spi = spi_master_get_devdata(master);
452 
453         clk_disable_unprepare(spi->clk);
454         return 0;
455 }
456 
457 static int orion_spi_runtime_resume(struct device *dev)
458 {
459         struct spi_master *master = dev_get_drvdata(dev);
460         struct orion_spi *spi = spi_master_get_devdata(master);
461 
462         return clk_prepare_enable(spi->clk);
463 }
464 #endif
465 
466 static const struct dev_pm_ops orion_spi_pm_ops = {
467         SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend,
468                            orion_spi_runtime_resume,
469                            NULL)
470 };
471 
472 static const struct of_device_id orion_spi_of_match_table[] = {
473         { .compatible = "marvell,orion-spi", },
474         {}
475 };
476 MODULE_DEVICE_TABLE(of, orion_spi_of_match_table);
477 
478 static struct platform_driver orion_spi_driver = {
479         .driver = {
480                 .name   = DRIVER_NAME,
481                 .owner  = THIS_MODULE,
482                 .pm     = &orion_spi_pm_ops,
483                 .of_match_table = of_match_ptr(orion_spi_of_match_table),
484         },
485         .probe          = orion_spi_probe,
486         .remove         = orion_spi_remove,
487 };
488 
489 module_platform_driver(orion_spi_driver);
490 
491 MODULE_DESCRIPTION("Orion SPI driver");
492 MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
493 MODULE_LICENSE("GPL");
494 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us