aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/omap2_mcspi.c
diff options
context:
space:
mode:
authorHemanth V <hemanthv@ti.com>2009-09-22 19:46:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:44 -0400
commita41ae1ad907655b2efbb9b1a97736ab1451e1649 (patch)
tree2b74a410c9108bee0ff1db47ffe9a30a15bce1be /drivers/spi/omap2_mcspi.c
parent0644c48672a3146c01bf7314d440edecf8742d62 (diff)
spi: McSPI off-mode support
Add context save/restore feature to McSPI driver. Signed-off-by: Hemanth V <hemanthv@ti.com> Reviewed-by: Aaro Koskinen <Aaro.Koskinen@nokia.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/spi/omap2_mcspi.c')
-rw-r--r--drivers/spi/omap2_mcspi.c134
1 files changed, 100 insertions, 34 deletions
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index ae785cc627b6..e96ad2709565 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -41,6 +41,9 @@
41 41
42#define OMAP2_MCSPI_MAX_FREQ 48000000 42#define OMAP2_MCSPI_MAX_FREQ 48000000
43 43
44/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
45#define OMAP2_MCSPI_MAX_CTRL 4
46
44#define OMAP2_MCSPI_REVISION 0x00 47#define OMAP2_MCSPI_REVISION 0x00
45#define OMAP2_MCSPI_SYSCONFIG 0x10 48#define OMAP2_MCSPI_SYSCONFIG 0x10
46#define OMAP2_MCSPI_SYSSTATUS 0x14 49#define OMAP2_MCSPI_SYSSTATUS 0x14
@@ -131,8 +134,21 @@ struct omap2_mcspi_cs {
131 void __iomem *base; 134 void __iomem *base;
132 unsigned long phys; 135 unsigned long phys;
133 int word_len; 136 int word_len;
137 /* Context save and restore shadow register */
138 u32 chconf0;
139};
140
141/* used for context save and restore, structure members to be updated whenever
142 * corresponding registers are modified.
143 */
144struct omap2_mcspi_regs {
145 u32 sysconfig;
146 u32 modulctrl;
147 u32 wakeupenable;
134}; 148};
135 149
150static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
151
136static struct workqueue_struct *omap2_mcspi_wq; 152static struct workqueue_struct *omap2_mcspi_wq;
137 153
138#define MOD_REG_BIT(val, mask, set) do { \ 154#define MOD_REG_BIT(val, mask, set) do { \
@@ -172,12 +188,27 @@ static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
172 return __raw_readl(cs->base + idx); 188 return __raw_readl(cs->base + idx);
173} 189}
174 190
191static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
192{
193 struct omap2_mcspi_cs *cs = spi->controller_state;
194
195 return cs->chconf0;
196}
197
198static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
199{
200 struct omap2_mcspi_cs *cs = spi->controller_state;
201
202 cs->chconf0 = val;
203 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
204}
205
175static void omap2_mcspi_set_dma_req(const struct spi_device *spi, 206static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
176 int is_read, int enable) 207 int is_read, int enable)
177{ 208{
178 u32 l, rw; 209 u32 l, rw;
179 210
180 l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); 211 l = mcspi_cached_chconf0(spi);
181 212
182 if (is_read) /* 1 is read, 0 write */ 213 if (is_read) /* 1 is read, 0 write */
183 rw = OMAP2_MCSPI_CHCONF_DMAR; 214 rw = OMAP2_MCSPI_CHCONF_DMAR;
@@ -185,7 +216,7 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
185 rw = OMAP2_MCSPI_CHCONF_DMAW; 216 rw = OMAP2_MCSPI_CHCONF_DMAW;
186 217
187 MOD_REG_BIT(l, rw, enable); 218 MOD_REG_BIT(l, rw, enable);
188 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); 219 mcspi_write_chconf0(spi, l);
189} 220}
190 221
191static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) 222static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
@@ -200,9 +231,9 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
200{ 231{
201 u32 l; 232 u32 l;
202 233
203 l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); 234 l = mcspi_cached_chconf0(spi);
204 MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); 235 MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
205 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); 236 mcspi_write_chconf0(spi, l);
206} 237}
207 238
208static void omap2_mcspi_set_master_mode(struct spi_master *master) 239static void omap2_mcspi_set_master_mode(struct spi_master *master)
@@ -217,6 +248,41 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
217 MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); 248 MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
218 MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); 249 MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
219 mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); 250 mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
251
252 omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
253}
254
255static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
256{
257 struct spi_master *spi_cntrl;
258 spi_cntrl = mcspi->master;
259
260 /* McSPI: context restore */
261 mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
262 omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
263
264 mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG,
265 omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig);
266
267 mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
268 omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
269}
270static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
271{
272 clk_disable(mcspi->ick);
273 clk_disable(mcspi->fck);
274}
275
276static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
277{
278 if (clk_enable(mcspi->ick))
279 return -ENODEV;
280 if (clk_enable(mcspi->fck))
281 return -ENODEV;
282
283 omap2_mcspi_restore_ctx(mcspi);
284
285 return 0;
220} 286}
221 287
222static unsigned 288static unsigned
@@ -357,7 +423,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
357 c = count; 423 c = count;
358 word_len = cs->word_len; 424 word_len = cs->word_len;
359 425
360 l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); 426 l = mcspi_cached_chconf0(spi);
361 l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; 427 l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
362 428
363 /* We store the pre-calculated register addresses on stack to speed 429 /* We store the pre-calculated register addresses on stack to speed
@@ -397,8 +463,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
397 * more word i/o: switch to rx+tx 463 * more word i/o: switch to rx+tx
398 */ 464 */
399 if (c == 0 && tx == NULL) 465 if (c == 0 && tx == NULL)
400 mcspi_write_cs_reg(spi, 466 mcspi_write_chconf0(spi, l);
401 OMAP2_MCSPI_CHCONF0, l);
402 *rx++ = __raw_readl(rx_reg); 467 *rx++ = __raw_readl(rx_reg);
403#ifdef VERBOSE 468#ifdef VERBOSE
404 dev_dbg(&spi->dev, "read-%d %02x\n", 469 dev_dbg(&spi->dev, "read-%d %02x\n",
@@ -436,8 +501,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
436 * more word i/o: switch to rx+tx 501 * more word i/o: switch to rx+tx
437 */ 502 */
438 if (c == 0 && tx == NULL) 503 if (c == 0 && tx == NULL)
439 mcspi_write_cs_reg(spi, 504 mcspi_write_chconf0(spi, l);
440 OMAP2_MCSPI_CHCONF0, l);
441 *rx++ = __raw_readl(rx_reg); 505 *rx++ = __raw_readl(rx_reg);
442#ifdef VERBOSE 506#ifdef VERBOSE
443 dev_dbg(&spi->dev, "read-%d %04x\n", 507 dev_dbg(&spi->dev, "read-%d %04x\n",
@@ -475,8 +539,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
475 * more word i/o: switch to rx+tx 539 * more word i/o: switch to rx+tx
476 */ 540 */
477 if (c == 0 && tx == NULL) 541 if (c == 0 && tx == NULL)
478 mcspi_write_cs_reg(spi, 542 mcspi_write_chconf0(spi, l);
479 OMAP2_MCSPI_CHCONF0, l);
480 *rx++ = __raw_readl(rx_reg); 543 *rx++ = __raw_readl(rx_reg);
481#ifdef VERBOSE 544#ifdef VERBOSE
482 dev_dbg(&spi->dev, "read-%d %04x\n", 545 dev_dbg(&spi->dev, "read-%d %04x\n",
@@ -505,10 +568,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
505{ 568{
506 struct omap2_mcspi_cs *cs = spi->controller_state; 569 struct omap2_mcspi_cs *cs = spi->controller_state;
507 struct omap2_mcspi *mcspi; 570 struct omap2_mcspi *mcspi;
571 struct spi_master *spi_cntrl;
508 u32 l = 0, div = 0; 572 u32 l = 0, div = 0;
509 u8 word_len = spi->bits_per_word; 573 u8 word_len = spi->bits_per_word;
510 574
511 mcspi = spi_master_get_devdata(spi->master); 575 mcspi = spi_master_get_devdata(spi->master);
576 spi_cntrl = mcspi->master;
512 577
513 if (t != NULL && t->bits_per_word) 578 if (t != NULL && t->bits_per_word)
514 word_len = t->bits_per_word; 579 word_len = t->bits_per_word;
@@ -522,7 +587,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
522 } else 587 } else
523 div = 15; 588 div = 15;
524 589
525 l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); 590 l = mcspi_cached_chconf0(spi);
526 591
527 /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS 592 /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
528 * REVISIT: this controller could support SPI_3WIRE mode. 593 * REVISIT: this controller could support SPI_3WIRE mode.
@@ -554,7 +619,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
554 else 619 else
555 l &= ~OMAP2_MCSPI_CHCONF_PHA; 620 l &= ~OMAP2_MCSPI_CHCONF_PHA;
556 621
557 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); 622 mcspi_write_chconf0(spi, l);
558 623
559 dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", 624 dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
560 OMAP2_MCSPI_MAX_FREQ / (1 << div), 625 OMAP2_MCSPI_MAX_FREQ / (1 << div),
@@ -647,6 +712,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
647 return -ENOMEM; 712 return -ENOMEM;
648 cs->base = mcspi->base + spi->chip_select * 0x14; 713 cs->base = mcspi->base + spi->chip_select * 0x14;
649 cs->phys = mcspi->phys + spi->chip_select * 0x14; 714 cs->phys = mcspi->phys + spi->chip_select * 0x14;
715 cs->chconf0 = 0;
650 spi->controller_state = cs; 716 spi->controller_state = cs;
651 } 717 }
652 718
@@ -657,11 +723,11 @@ static int omap2_mcspi_setup(struct spi_device *spi)
657 return ret; 723 return ret;
658 } 724 }
659 725
660 clk_enable(mcspi->ick); 726 if (omap2_mcspi_enable_clocks(mcspi))
661 clk_enable(mcspi->fck); 727 return -ENODEV;
728
662 ret = omap2_mcspi_setup_transfer(spi, NULL); 729 ret = omap2_mcspi_setup_transfer(spi, NULL);
663 clk_disable(mcspi->fck); 730 omap2_mcspi_disable_clocks(mcspi);
664 clk_disable(mcspi->ick);
665 731
666 return ret; 732 return ret;
667} 733}
@@ -693,8 +759,8 @@ static void omap2_mcspi_work(struct work_struct *work)
693 mcspi = container_of(work, struct omap2_mcspi, work); 759 mcspi = container_of(work, struct omap2_mcspi, work);
694 spin_lock_irq(&mcspi->lock); 760 spin_lock_irq(&mcspi->lock);
695 761
696 clk_enable(mcspi->ick); 762 if (omap2_mcspi_enable_clocks(mcspi))
697 clk_enable(mcspi->fck); 763 goto out;
698 764
699 /* We only enable one channel at a time -- the one whose message is 765 /* We only enable one channel at a time -- the one whose message is
700 * at the head of the queue -- although this controller would gladly 766 * at the head of the queue -- although this controller would gladly
@@ -741,13 +807,13 @@ static void omap2_mcspi_work(struct work_struct *work)
741 cs_active = 1; 807 cs_active = 1;
742 } 808 }
743 809
744 chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); 810 chconf = mcspi_cached_chconf0(spi);
745 chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; 811 chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
746 if (t->tx_buf == NULL) 812 if (t->tx_buf == NULL)
747 chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY; 813 chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
748 else if (t->rx_buf == NULL) 814 else if (t->rx_buf == NULL)
749 chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY; 815 chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
750 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf); 816 mcspi_write_chconf0(spi, chconf);
751 817
752 if (t->len) { 818 if (t->len) {
753 unsigned count; 819 unsigned count;
@@ -796,9 +862,9 @@ static void omap2_mcspi_work(struct work_struct *work)
796 spin_lock_irq(&mcspi->lock); 862 spin_lock_irq(&mcspi->lock);
797 } 863 }
798 864
799 clk_disable(mcspi->fck); 865 omap2_mcspi_disable_clocks(mcspi);
800 clk_disable(mcspi->ick);
801 866
867out:
802 spin_unlock_irq(&mcspi->lock); 868 spin_unlock_irq(&mcspi->lock);
803} 869}
804 870
@@ -885,8 +951,8 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
885 struct spi_master *master = mcspi->master; 951 struct spi_master *master = mcspi->master;
886 u32 tmp; 952 u32 tmp;
887 953
888 clk_enable(mcspi->ick); 954 if (omap2_mcspi_enable_clocks(mcspi))
889 clk_enable(mcspi->fck); 955 return -1;
890 956
891 mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, 957 mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
892 OMAP2_MCSPI_SYSCONFIG_SOFTRESET); 958 OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
@@ -894,18 +960,18 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
894 tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS); 960 tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
895 } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE)); 961 } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
896 962
897 mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, 963 tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
898 OMAP2_MCSPI_SYSCONFIG_AUTOIDLE | 964 OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
899 OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP | 965 OMAP2_MCSPI_SYSCONFIG_SMARTIDLE;
900 OMAP2_MCSPI_SYSCONFIG_SMARTIDLE); 966 mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp);
967 omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp;
901 968
902 mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, 969 tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
903 OMAP2_MCSPI_WAKEUPENABLE_WKEN); 970 mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
971 omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp;
904 972
905 omap2_mcspi_set_master_mode(master); 973 omap2_mcspi_set_master_mode(master);
906 974 omap2_mcspi_disable_clocks(mcspi);
907 clk_disable(mcspi->fck);
908 clk_disable(mcspi->ick);
909 return 0; 975 return 0;
910} 976}
911 977