1ca632f55SGrant Likely /* 2ca632f55SGrant Likely * OMAP2 McSPI controller driver 3ca632f55SGrant Likely * 4ca632f55SGrant Likely * Copyright (C) 2005, 2006 Nokia Corporation 5ca632f55SGrant Likely * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and 6ca632f55SGrant Likely * Juha Yrj�l� <juha.yrjola@nokia.com> 7ca632f55SGrant Likely * 8ca632f55SGrant Likely * This program is free software; you can redistribute it and/or modify 9ca632f55SGrant Likely * it under the terms of the GNU General Public License as published by 10ca632f55SGrant Likely * the Free Software Foundation; either version 2 of the License, or 11ca632f55SGrant Likely * (at your option) any later version. 12ca632f55SGrant Likely * 13ca632f55SGrant Likely * This program is distributed in the hope that it will be useful, 14ca632f55SGrant Likely * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ca632f55SGrant Likely * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ca632f55SGrant Likely * GNU General Public License for more details. 17ca632f55SGrant Likely */ 18ca632f55SGrant Likely 19ca632f55SGrant Likely #include <linux/kernel.h> 20ca632f55SGrant Likely #include <linux/interrupt.h> 21ca632f55SGrant Likely #include <linux/module.h> 22ca632f55SGrant Likely #include <linux/device.h> 23ca632f55SGrant Likely #include <linux/delay.h> 24ca632f55SGrant Likely #include <linux/dma-mapping.h> 2553741ed8SRussell King #include <linux/dmaengine.h> 2653741ed8SRussell King #include <linux/omap-dma.h> 27ca632f55SGrant Likely #include <linux/platform_device.h> 28ca632f55SGrant Likely #include <linux/err.h> 29ca632f55SGrant Likely #include <linux/clk.h> 30ca632f55SGrant Likely #include <linux/io.h> 31ca632f55SGrant Likely #include <linux/slab.h> 32ca632f55SGrant Likely #include <linux/pm_runtime.h> 33d5a80031SBenoit Cousson #include <linux/of.h> 34d5a80031SBenoit Cousson #include <linux/of_device.h> 35d33f473dSIllia Smyrnov #include <linux/gcd.h> 36ca632f55SGrant Likely 37ca632f55SGrant Likely #include <linux/spi/spi.h> 38bc7f9bbcSMichael Welling #include <linux/gpio.h> 39ca632f55SGrant Likely 402203747cSArnd Bergmann #include <linux/platform_data/spi-omap2-mcspi.h> 41ca632f55SGrant Likely 42ca632f55SGrant Likely #define OMAP2_MCSPI_MAX_FREQ 48000000 43faee9b05SStefan Sørensen #define OMAP2_MCSPI_MAX_DIVIDER 4096 44d33f473dSIllia Smyrnov #define OMAP2_MCSPI_MAX_FIFODEPTH 64 45d33f473dSIllia Smyrnov #define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF 4627b5284cSShubhrajyoti D #define SPI_AUTOSUSPEND_TIMEOUT 2000 47ca632f55SGrant Likely 48ca632f55SGrant Likely #define OMAP2_MCSPI_REVISION 0x00 49ca632f55SGrant Likely #define OMAP2_MCSPI_SYSSTATUS 0x14 50ca632f55SGrant Likely #define OMAP2_MCSPI_IRQSTATUS 0x18 51ca632f55SGrant Likely #define OMAP2_MCSPI_IRQENABLE 0x1c 52ca632f55SGrant Likely #define OMAP2_MCSPI_WAKEUPENABLE 0x20 53ca632f55SGrant Likely #define OMAP2_MCSPI_SYST 0x24 54ca632f55SGrant Likely #define OMAP2_MCSPI_MODULCTRL 0x28 55d33f473dSIllia Smyrnov #define OMAP2_MCSPI_XFERLEVEL 0x7c 56ca632f55SGrant Likely 57ca632f55SGrant Likely /* per-channel banks, 0x14 bytes each, first is: */ 58ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF0 0x2c 59ca632f55SGrant Likely #define OMAP2_MCSPI_CHSTAT0 0x30 60ca632f55SGrant Likely #define OMAP2_MCSPI_CHCTRL0 0x34 61ca632f55SGrant Likely #define OMAP2_MCSPI_TX0 0x38 62ca632f55SGrant Likely #define OMAP2_MCSPI_RX0 0x3c 63ca632f55SGrant Likely 64ca632f55SGrant Likely /* per-register bitmasks: */ 65d33f473dSIllia Smyrnov #define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17) 66ca632f55SGrant Likely 67ca632f55SGrant Likely #define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) 68ca632f55SGrant Likely #define OMAP2_MCSPI_MODULCTRL_MS BIT(2) 69ca632f55SGrant Likely #define OMAP2_MCSPI_MODULCTRL_STEST BIT(3) 70ca632f55SGrant Likely 71ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_PHA BIT(0) 72ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_POL BIT(1) 73ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_CLKD_MASK (0x0f << 2) 74ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_EPOL BIT(6) 75ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_WL_MASK (0x1f << 7) 76ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY BIT(12) 77ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY BIT(13) 78ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_TRM_MASK (0x03 << 12) 79ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_DMAW BIT(14) 80ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_DMAR BIT(15) 81ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_DPE0 BIT(16) 82ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_DPE1 BIT(17) 83ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_IS BIT(18) 84ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_TURBO BIT(19) 85ca632f55SGrant Likely #define OMAP2_MCSPI_CHCONF_FORCE BIT(20) 86d33f473dSIllia Smyrnov #define OMAP2_MCSPI_CHCONF_FFET BIT(27) 87d33f473dSIllia Smyrnov #define OMAP2_MCSPI_CHCONF_FFER BIT(28) 88faee9b05SStefan Sørensen #define OMAP2_MCSPI_CHCONF_CLKG BIT(29) 89ca632f55SGrant Likely 90ca632f55SGrant Likely #define OMAP2_MCSPI_CHSTAT_RXS BIT(0) 91ca632f55SGrant Likely #define OMAP2_MCSPI_CHSTAT_TXS BIT(1) 92ca632f55SGrant Likely #define OMAP2_MCSPI_CHSTAT_EOT BIT(2) 93d33f473dSIllia Smyrnov #define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) 94ca632f55SGrant Likely 95ca632f55SGrant Likely #define OMAP2_MCSPI_CHCTRL_EN BIT(0) 96faee9b05SStefan Sørensen #define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8) 97ca632f55SGrant Likely 98ca632f55SGrant Likely #define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) 99ca632f55SGrant Likely 100ca632f55SGrant Likely /* We have 2 DMA channels per CS, one for RX and one for TX */ 101ca632f55SGrant Likely struct omap2_mcspi_dma { 10253741ed8SRussell King struct dma_chan *dma_tx; 10353741ed8SRussell King struct dma_chan *dma_rx; 104ca632f55SGrant Likely 105ca632f55SGrant Likely int dma_tx_sync_dev; 106ca632f55SGrant Likely int dma_rx_sync_dev; 107ca632f55SGrant Likely 108ca632f55SGrant Likely struct completion dma_tx_completion; 109ca632f55SGrant Likely struct completion dma_rx_completion; 11074f3aaadSMatt Porter 11174f3aaadSMatt Porter char dma_rx_ch_name[14]; 11274f3aaadSMatt Porter char dma_tx_ch_name[14]; 113ca632f55SGrant Likely }; 114ca632f55SGrant Likely 115ca632f55SGrant Likely /* use PIO for small transfers, avoiding DMA setup/teardown overhead and 116ca632f55SGrant Likely * cache operations; better heuristics consider wordsize and bitrate. 117ca632f55SGrant Likely */ 118ca632f55SGrant Likely #define DMA_MIN_BYTES 160 119ca632f55SGrant Likely 120ca632f55SGrant Likely 1211bd897f8SBenoit Cousson /* 1221bd897f8SBenoit Cousson * Used for context save and restore, structure members to be updated whenever 1231bd897f8SBenoit Cousson * corresponding registers are modified. 1241bd897f8SBenoit Cousson */ 1251bd897f8SBenoit Cousson struct omap2_mcspi_regs { 1261bd897f8SBenoit Cousson u32 modulctrl; 1271bd897f8SBenoit Cousson u32 wakeupenable; 1281bd897f8SBenoit Cousson struct list_head cs; 1291bd897f8SBenoit Cousson }; 1301bd897f8SBenoit Cousson 131ca632f55SGrant Likely struct omap2_mcspi { 132ca632f55SGrant Likely struct spi_master *master; 133ca632f55SGrant Likely /* Virtual base address of the controller */ 134ca632f55SGrant Likely void __iomem *base; 135ca632f55SGrant Likely unsigned long phys; 136ca632f55SGrant Likely /* SPI1 has 4 channels, while SPI2 has 2 */ 137ca632f55SGrant Likely struct omap2_mcspi_dma *dma_channels; 138ca632f55SGrant Likely struct device *dev; 1391bd897f8SBenoit Cousson struct omap2_mcspi_regs ctx; 140d33f473dSIllia Smyrnov int fifo_depth; 1410384e90bSDaniel Mack unsigned int pin_dir:1; 142ca632f55SGrant Likely }; 143ca632f55SGrant Likely 144ca632f55SGrant Likely struct omap2_mcspi_cs { 145ca632f55SGrant Likely void __iomem *base; 146ca632f55SGrant Likely unsigned long phys; 147ca632f55SGrant Likely int word_len; 14897ca0d6cSMark A. Greer u16 mode; 149ca632f55SGrant Likely struct list_head node; 150ca632f55SGrant Likely /* Context save and restore shadow register */ 151faee9b05SStefan Sørensen u32 chconf0, chctrl0; 152ca632f55SGrant Likely }; 153ca632f55SGrant Likely 154ca632f55SGrant Likely static inline void mcspi_write_reg(struct spi_master *master, 155ca632f55SGrant Likely int idx, u32 val) 156ca632f55SGrant Likely { 157ca632f55SGrant Likely struct omap2_mcspi *mcspi = spi_master_get_devdata(master); 158ca632f55SGrant Likely 15921b2ce5eSVictor Kamensky writel_relaxed(val, mcspi->base + idx); 160ca632f55SGrant Likely } 161ca632f55SGrant Likely 162ca632f55SGrant Likely static inline u32 mcspi_read_reg(struct spi_master *master, int idx) 163ca632f55SGrant Likely { 164ca632f55SGrant Likely struct omap2_mcspi *mcspi = spi_master_get_devdata(master); 165ca632f55SGrant Likely 16621b2ce5eSVictor Kamensky return readl_relaxed(mcspi->base + idx); 167ca632f55SGrant Likely } 168ca632f55SGrant Likely 169ca632f55SGrant Likely static inline void mcspi_write_cs_reg(const struct spi_device *spi, 170ca632f55SGrant Likely int idx, u32 val) 171ca632f55SGrant Likely { 172ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 173ca632f55SGrant Likely 17421b2ce5eSVictor Kamensky writel_relaxed(val, cs->base + idx); 175ca632f55SGrant Likely } 176ca632f55SGrant Likely 177ca632f55SGrant Likely static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx) 178ca632f55SGrant Likely { 179ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 180ca632f55SGrant Likely 18121b2ce5eSVictor Kamensky return readl_relaxed(cs->base + idx); 182ca632f55SGrant Likely } 183ca632f55SGrant Likely 184ca632f55SGrant Likely static inline u32 mcspi_cached_chconf0(const struct spi_device *spi) 185ca632f55SGrant Likely { 186ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 187ca632f55SGrant Likely 188ca632f55SGrant Likely return cs->chconf0; 189ca632f55SGrant Likely } 190ca632f55SGrant Likely 191ca632f55SGrant Likely static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val) 192ca632f55SGrant Likely { 193ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 194ca632f55SGrant Likely 195ca632f55SGrant Likely cs->chconf0 = val; 196ca632f55SGrant Likely mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val); 197ca632f55SGrant Likely mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); 198ca632f55SGrant Likely } 199ca632f55SGrant Likely 20056cd5c15SIllia Smyrnov static inline int mcspi_bytes_per_word(int word_len) 20156cd5c15SIllia Smyrnov { 20256cd5c15SIllia Smyrnov if (word_len <= 8) 20356cd5c15SIllia Smyrnov return 1; 20456cd5c15SIllia Smyrnov else if (word_len <= 16) 20556cd5c15SIllia Smyrnov return 2; 20656cd5c15SIllia Smyrnov else /* word_len <= 32 */ 20756cd5c15SIllia Smyrnov return 4; 20856cd5c15SIllia Smyrnov } 20956cd5c15SIllia Smyrnov 210ca632f55SGrant Likely static void omap2_mcspi_set_dma_req(const struct spi_device *spi, 211ca632f55SGrant Likely int is_read, int enable) 212ca632f55SGrant Likely { 213ca632f55SGrant Likely u32 l, rw; 214ca632f55SGrant Likely 215ca632f55SGrant Likely l = mcspi_cached_chconf0(spi); 216ca632f55SGrant Likely 217ca632f55SGrant Likely if (is_read) /* 1 is read, 0 write */ 218ca632f55SGrant Likely rw = OMAP2_MCSPI_CHCONF_DMAR; 219ca632f55SGrant Likely else 220ca632f55SGrant Likely rw = OMAP2_MCSPI_CHCONF_DMAW; 221ca632f55SGrant Likely 222af4e944dSShubhrajyoti D if (enable) 223af4e944dSShubhrajyoti D l |= rw; 224af4e944dSShubhrajyoti D else 225af4e944dSShubhrajyoti D l &= ~rw; 226af4e944dSShubhrajyoti D 227ca632f55SGrant Likely mcspi_write_chconf0(spi, l); 228ca632f55SGrant Likely } 229ca632f55SGrant Likely 230ca632f55SGrant Likely static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) 231ca632f55SGrant Likely { 232faee9b05SStefan Sørensen struct omap2_mcspi_cs *cs = spi->controller_state; 233ca632f55SGrant Likely u32 l; 234ca632f55SGrant Likely 235faee9b05SStefan Sørensen l = cs->chctrl0; 236faee9b05SStefan Sørensen if (enable) 237faee9b05SStefan Sørensen l |= OMAP2_MCSPI_CHCTRL_EN; 238faee9b05SStefan Sørensen else 239faee9b05SStefan Sørensen l &= ~OMAP2_MCSPI_CHCTRL_EN; 240faee9b05SStefan Sørensen cs->chctrl0 = l; 241faee9b05SStefan Sørensen mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0); 242ca632f55SGrant Likely /* Flash post-writes */ 243ca632f55SGrant Likely mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); 244ca632f55SGrant Likely } 245ca632f55SGrant Likely 246ddcad7e9SMichael Welling static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) 247ca632f55SGrant Likely { 248ca632f55SGrant Likely u32 l; 249ca632f55SGrant Likely 250*4373f8b6SMichael Welling /* The controller handles the inverted chip selects 251*4373f8b6SMichael Welling * using the OMAP2_MCSPI_CHCONF_EPOL bit so revert 252*4373f8b6SMichael Welling * the inversion from the core spi_set_cs function. 253*4373f8b6SMichael Welling */ 254*4373f8b6SMichael Welling if (spi->mode & SPI_CS_HIGH) 255*4373f8b6SMichael Welling enable = !enable; 256*4373f8b6SMichael Welling 257ddcad7e9SMichael Welling if (spi->controller_state) { 258ca632f55SGrant Likely l = mcspi_cached_chconf0(spi); 259ddcad7e9SMichael Welling 260ddcad7e9SMichael Welling if (enable) 261af4e944dSShubhrajyoti D l &= ~OMAP2_MCSPI_CHCONF_FORCE; 262ddcad7e9SMichael Welling else 263ddcad7e9SMichael Welling l |= OMAP2_MCSPI_CHCONF_FORCE; 264af4e944dSShubhrajyoti D 265ca632f55SGrant Likely mcspi_write_chconf0(spi, l); 266ca632f55SGrant Likely } 267ddcad7e9SMichael Welling } 268ca632f55SGrant Likely 269ca632f55SGrant Likely static void omap2_mcspi_set_master_mode(struct spi_master *master) 270ca632f55SGrant Likely { 2711bd897f8SBenoit Cousson struct omap2_mcspi *mcspi = spi_master_get_devdata(master); 2721bd897f8SBenoit Cousson struct omap2_mcspi_regs *ctx = &mcspi->ctx; 273ca632f55SGrant Likely u32 l; 274ca632f55SGrant Likely 2751bd897f8SBenoit Cousson /* 2761bd897f8SBenoit Cousson * Setup when switching from (reset default) slave mode 277ca632f55SGrant Likely * to single-channel master mode 278ca632f55SGrant Likely */ 279ca632f55SGrant Likely l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); 280af4e944dSShubhrajyoti D l &= ~(OMAP2_MCSPI_MODULCTRL_STEST | OMAP2_MCSPI_MODULCTRL_MS); 281af4e944dSShubhrajyoti D l |= OMAP2_MCSPI_MODULCTRL_SINGLE; 282ca632f55SGrant Likely mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); 283ca632f55SGrant Likely 2841bd897f8SBenoit Cousson ctx->modulctrl = l; 285ca632f55SGrant Likely } 286ca632f55SGrant Likely 287d33f473dSIllia Smyrnov static void omap2_mcspi_set_fifo(const struct spi_device *spi, 288d33f473dSIllia Smyrnov struct spi_transfer *t, int enable) 289d33f473dSIllia Smyrnov { 290d33f473dSIllia Smyrnov struct spi_master *master = spi->master; 291d33f473dSIllia Smyrnov struct omap2_mcspi_cs *cs = spi->controller_state; 292d33f473dSIllia Smyrnov struct omap2_mcspi *mcspi; 293d33f473dSIllia Smyrnov unsigned int wcnt; 2945db542edSIllia Smyrnov int max_fifo_depth, fifo_depth, bytes_per_word; 295d33f473dSIllia Smyrnov u32 chconf, xferlevel; 296d33f473dSIllia Smyrnov 297d33f473dSIllia Smyrnov mcspi = spi_master_get_devdata(master); 298d33f473dSIllia Smyrnov 299d33f473dSIllia Smyrnov chconf = mcspi_cached_chconf0(spi); 300d33f473dSIllia Smyrnov if (enable) { 301d33f473dSIllia Smyrnov bytes_per_word = mcspi_bytes_per_word(cs->word_len); 302d33f473dSIllia Smyrnov if (t->len % bytes_per_word != 0) 303d33f473dSIllia Smyrnov goto disable_fifo; 304d33f473dSIllia Smyrnov 3055db542edSIllia Smyrnov if (t->rx_buf != NULL && t->tx_buf != NULL) 3065db542edSIllia Smyrnov max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2; 3075db542edSIllia Smyrnov else 3085db542edSIllia Smyrnov max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH; 3095db542edSIllia Smyrnov 3105db542edSIllia Smyrnov fifo_depth = gcd(t->len, max_fifo_depth); 311d33f473dSIllia Smyrnov if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0) 312d33f473dSIllia Smyrnov goto disable_fifo; 313d33f473dSIllia Smyrnov 314d33f473dSIllia Smyrnov wcnt = t->len / bytes_per_word; 315d33f473dSIllia Smyrnov if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT) 316d33f473dSIllia Smyrnov goto disable_fifo; 317d33f473dSIllia Smyrnov 318d33f473dSIllia Smyrnov xferlevel = wcnt << 16; 319d33f473dSIllia Smyrnov if (t->rx_buf != NULL) { 320d33f473dSIllia Smyrnov chconf |= OMAP2_MCSPI_CHCONF_FFER; 321d33f473dSIllia Smyrnov xferlevel |= (fifo_depth - 1) << 8; 3225db542edSIllia Smyrnov } 3235db542edSIllia Smyrnov if (t->tx_buf != NULL) { 324d33f473dSIllia Smyrnov chconf |= OMAP2_MCSPI_CHCONF_FFET; 325d33f473dSIllia Smyrnov xferlevel |= fifo_depth - 1; 326d33f473dSIllia Smyrnov } 327d33f473dSIllia Smyrnov 328d33f473dSIllia Smyrnov mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel); 329d33f473dSIllia Smyrnov mcspi_write_chconf0(spi, chconf); 330d33f473dSIllia Smyrnov mcspi->fifo_depth = fifo_depth; 331d33f473dSIllia Smyrnov 332d33f473dSIllia Smyrnov return; 333d33f473dSIllia Smyrnov } 334d33f473dSIllia Smyrnov 335d33f473dSIllia Smyrnov disable_fifo: 336d33f473dSIllia Smyrnov if (t->rx_buf != NULL) 337d33f473dSIllia Smyrnov chconf &= ~OMAP2_MCSPI_CHCONF_FFER; 3383d0763c0SJorge A. Ventura 3393d0763c0SJorge A. Ventura if (t->tx_buf != NULL) 340d33f473dSIllia Smyrnov chconf &= ~OMAP2_MCSPI_CHCONF_FFET; 341d33f473dSIllia Smyrnov 342d33f473dSIllia Smyrnov mcspi_write_chconf0(spi, chconf); 343d33f473dSIllia Smyrnov mcspi->fifo_depth = 0; 344d33f473dSIllia Smyrnov } 345d33f473dSIllia Smyrnov 346ca632f55SGrant Likely static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) 347ca632f55SGrant Likely { 3481bd897f8SBenoit Cousson struct spi_master *spi_cntrl = mcspi->master; 3491bd897f8SBenoit Cousson struct omap2_mcspi_regs *ctx = &mcspi->ctx; 350ca632f55SGrant Likely struct omap2_mcspi_cs *cs; 351ca632f55SGrant Likely 352ca632f55SGrant Likely /* McSPI: context restore */ 3531bd897f8SBenoit Cousson mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); 3541bd897f8SBenoit Cousson mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); 355ca632f55SGrant Likely 3561bd897f8SBenoit Cousson list_for_each_entry(cs, &ctx->cs, node) 35721b2ce5eSVictor Kamensky writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); 358ca632f55SGrant Likely } 359ca632f55SGrant Likely 360ca632f55SGrant Likely static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) 361ca632f55SGrant Likely { 362ca632f55SGrant Likely unsigned long timeout; 363ca632f55SGrant Likely 364ca632f55SGrant Likely timeout = jiffies + msecs_to_jiffies(1000); 36521b2ce5eSVictor Kamensky while (!(readl_relaxed(reg) & bit)) { 366ff23fa3bSSebastian Andrzej Siewior if (time_after(jiffies, timeout)) { 36721b2ce5eSVictor Kamensky if (!(readl_relaxed(reg) & bit)) 368ff23fa3bSSebastian Andrzej Siewior return -ETIMEDOUT; 369ff23fa3bSSebastian Andrzej Siewior else 370ff23fa3bSSebastian Andrzej Siewior return 0; 371ff23fa3bSSebastian Andrzej Siewior } 372ca632f55SGrant Likely cpu_relax(); 373ca632f55SGrant Likely } 374ca632f55SGrant Likely return 0; 375ca632f55SGrant Likely } 376ca632f55SGrant Likely 37753741ed8SRussell King static void omap2_mcspi_rx_callback(void *data) 37853741ed8SRussell King { 37953741ed8SRussell King struct spi_device *spi = data; 38053741ed8SRussell King struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); 38153741ed8SRussell King struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 38253741ed8SRussell King 38353741ed8SRussell King /* We must disable the DMA RX request */ 38453741ed8SRussell King omap2_mcspi_set_dma_req(spi, 1, 0); 385830379e0SFelipe Balbi 386830379e0SFelipe Balbi complete(&mcspi_dma->dma_rx_completion); 38753741ed8SRussell King } 38853741ed8SRussell King 38953741ed8SRussell King static void omap2_mcspi_tx_callback(void *data) 39053741ed8SRussell King { 39153741ed8SRussell King struct spi_device *spi = data; 39253741ed8SRussell King struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); 39353741ed8SRussell King struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 39453741ed8SRussell King 39553741ed8SRussell King /* We must disable the DMA TX request */ 39653741ed8SRussell King omap2_mcspi_set_dma_req(spi, 0, 0); 397830379e0SFelipe Balbi 398830379e0SFelipe Balbi complete(&mcspi_dma->dma_tx_completion); 39953741ed8SRussell King } 40053741ed8SRussell King 401d7b4394eSShubhrajyoti D static void omap2_mcspi_tx_dma(struct spi_device *spi, 402d7b4394eSShubhrajyoti D struct spi_transfer *xfer, 403d7b4394eSShubhrajyoti D struct dma_slave_config cfg) 404ca632f55SGrant Likely { 405ca632f55SGrant Likely struct omap2_mcspi *mcspi; 406ca632f55SGrant Likely struct omap2_mcspi_dma *mcspi_dma; 4078c7494a5SRussell King unsigned int count; 408ca632f55SGrant Likely 409ca632f55SGrant Likely mcspi = spi_master_get_devdata(spi->master); 410ca632f55SGrant Likely mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 411d7b4394eSShubhrajyoti D count = xfer->len; 412ca632f55SGrant Likely 413d7b4394eSShubhrajyoti D if (mcspi_dma->dma_tx) { 41453741ed8SRussell King struct dma_async_tx_descriptor *tx; 41553741ed8SRussell King struct scatterlist sg; 41653741ed8SRussell King 41753741ed8SRussell King dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); 41853741ed8SRussell King 41953741ed8SRussell King sg_init_table(&sg, 1); 42053741ed8SRussell King sg_dma_address(&sg) = xfer->tx_dma; 42153741ed8SRussell King sg_dma_len(&sg) = xfer->len; 42253741ed8SRussell King 42353741ed8SRussell King tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, 42453741ed8SRussell King DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 42553741ed8SRussell King if (tx) { 42653741ed8SRussell King tx->callback = omap2_mcspi_tx_callback; 42753741ed8SRussell King tx->callback_param = spi; 42853741ed8SRussell King dmaengine_submit(tx); 42953741ed8SRussell King } else { 43053741ed8SRussell King /* FIXME: fall back to PIO? */ 43153741ed8SRussell King } 43253741ed8SRussell King } 43353741ed8SRussell King dma_async_issue_pending(mcspi_dma->dma_tx); 434ca632f55SGrant Likely omap2_mcspi_set_dma_req(spi, 0, 1); 435ca632f55SGrant Likely 436ca632f55SGrant Likely } 437ca632f55SGrant Likely 438d7b4394eSShubhrajyoti D static unsigned 439d7b4394eSShubhrajyoti D omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, 440d7b4394eSShubhrajyoti D struct dma_slave_config cfg, 441d7b4394eSShubhrajyoti D unsigned es) 442d7b4394eSShubhrajyoti D { 443d7b4394eSShubhrajyoti D struct omap2_mcspi *mcspi; 444d7b4394eSShubhrajyoti D struct omap2_mcspi_dma *mcspi_dma; 445d33f473dSIllia Smyrnov unsigned int count, dma_count; 446d7b4394eSShubhrajyoti D u32 l; 447d7b4394eSShubhrajyoti D int elements = 0; 448d7b4394eSShubhrajyoti D int word_len, element_count; 449d7b4394eSShubhrajyoti D struct omap2_mcspi_cs *cs = spi->controller_state; 450d7b4394eSShubhrajyoti D mcspi = spi_master_get_devdata(spi->master); 451d7b4394eSShubhrajyoti D mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 452d7b4394eSShubhrajyoti D count = xfer->len; 453d33f473dSIllia Smyrnov dma_count = xfer->len; 454d33f473dSIllia Smyrnov 455d33f473dSIllia Smyrnov if (mcspi->fifo_depth == 0) 456d33f473dSIllia Smyrnov dma_count -= es; 457d33f473dSIllia Smyrnov 458d7b4394eSShubhrajyoti D word_len = cs->word_len; 459d7b4394eSShubhrajyoti D l = mcspi_cached_chconf0(spi); 460d7b4394eSShubhrajyoti D 461d7b4394eSShubhrajyoti D if (word_len <= 8) 462d7b4394eSShubhrajyoti D element_count = count; 463d7b4394eSShubhrajyoti D else if (word_len <= 16) 464d7b4394eSShubhrajyoti D element_count = count >> 1; 465d7b4394eSShubhrajyoti D else /* word_len <= 32 */ 466d7b4394eSShubhrajyoti D element_count = count >> 2; 467d7b4394eSShubhrajyoti D 468d7b4394eSShubhrajyoti D if (mcspi_dma->dma_rx) { 469d7b4394eSShubhrajyoti D struct dma_async_tx_descriptor *tx; 470d7b4394eSShubhrajyoti D struct scatterlist sg; 471d7b4394eSShubhrajyoti D 472d7b4394eSShubhrajyoti D dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); 473d7b4394eSShubhrajyoti D 474d33f473dSIllia Smyrnov if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) 475d33f473dSIllia Smyrnov dma_count -= es; 476d7b4394eSShubhrajyoti D 477d7b4394eSShubhrajyoti D sg_init_table(&sg, 1); 478d7b4394eSShubhrajyoti D sg_dma_address(&sg) = xfer->rx_dma; 479d33f473dSIllia Smyrnov sg_dma_len(&sg) = dma_count; 480d7b4394eSShubhrajyoti D 481d7b4394eSShubhrajyoti D tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, 482d7b4394eSShubhrajyoti D DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | 483d7b4394eSShubhrajyoti D DMA_CTRL_ACK); 484d7b4394eSShubhrajyoti D if (tx) { 485d7b4394eSShubhrajyoti D tx->callback = omap2_mcspi_rx_callback; 486d7b4394eSShubhrajyoti D tx->callback_param = spi; 487d7b4394eSShubhrajyoti D dmaengine_submit(tx); 488d7b4394eSShubhrajyoti D } else { 489d7b4394eSShubhrajyoti D /* FIXME: fall back to PIO? */ 490d7b4394eSShubhrajyoti D } 491d7b4394eSShubhrajyoti D } 492d7b4394eSShubhrajyoti D 493d7b4394eSShubhrajyoti D dma_async_issue_pending(mcspi_dma->dma_rx); 494d7b4394eSShubhrajyoti D omap2_mcspi_set_dma_req(spi, 1, 1); 495d7b4394eSShubhrajyoti D 496ca632f55SGrant Likely wait_for_completion(&mcspi_dma->dma_rx_completion); 497a3ce9a80SShubhrajyoti D dma_unmap_single(mcspi->dev, xfer->rx_dma, count, 498a3ce9a80SShubhrajyoti D DMA_FROM_DEVICE); 499d33f473dSIllia Smyrnov 500d33f473dSIllia Smyrnov if (mcspi->fifo_depth > 0) 501d33f473dSIllia Smyrnov return count; 502d33f473dSIllia Smyrnov 503ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 504ca632f55SGrant Likely 50553741ed8SRussell King elements = element_count - 1; 50653741ed8SRussell King 507ca632f55SGrant Likely if (l & OMAP2_MCSPI_CHCONF_TURBO) { 50853741ed8SRussell King elements--; 509ca632f55SGrant Likely 510ca632f55SGrant Likely if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) 511ca632f55SGrant Likely & OMAP2_MCSPI_CHSTAT_RXS)) { 512ca632f55SGrant Likely u32 w; 513ca632f55SGrant Likely 514ca632f55SGrant Likely w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); 515ca632f55SGrant Likely if (word_len <= 8) 516ca632f55SGrant Likely ((u8 *)xfer->rx_buf)[elements++] = w; 517ca632f55SGrant Likely else if (word_len <= 16) 518ca632f55SGrant Likely ((u16 *)xfer->rx_buf)[elements++] = w; 519ca632f55SGrant Likely else /* word_len <= 32 */ 520ca632f55SGrant Likely ((u32 *)xfer->rx_buf)[elements++] = w; 521ca632f55SGrant Likely } else { 52256cd5c15SIllia Smyrnov int bytes_per_word = mcspi_bytes_per_word(word_len); 523a1829d2bSJarkko Nikula dev_err(&spi->dev, "DMA RX penultimate word empty\n"); 52456cd5c15SIllia Smyrnov count -= (bytes_per_word << 1); 525ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 1); 526ca632f55SGrant Likely return count; 527ca632f55SGrant Likely } 528ca632f55SGrant Likely } 529ca632f55SGrant Likely if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) 530ca632f55SGrant Likely & OMAP2_MCSPI_CHSTAT_RXS)) { 531ca632f55SGrant Likely u32 w; 532ca632f55SGrant Likely 533ca632f55SGrant Likely w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); 534ca632f55SGrant Likely if (word_len <= 8) 535ca632f55SGrant Likely ((u8 *)xfer->rx_buf)[elements] = w; 536ca632f55SGrant Likely else if (word_len <= 16) 537ca632f55SGrant Likely ((u16 *)xfer->rx_buf)[elements] = w; 538ca632f55SGrant Likely else /* word_len <= 32 */ 539ca632f55SGrant Likely ((u32 *)xfer->rx_buf)[elements] = w; 540ca632f55SGrant Likely } else { 541a1829d2bSJarkko Nikula dev_err(&spi->dev, "DMA RX last word empty\n"); 54256cd5c15SIllia Smyrnov count -= mcspi_bytes_per_word(word_len); 543ca632f55SGrant Likely } 544ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 1); 545d7b4394eSShubhrajyoti D return count; 546ca632f55SGrant Likely } 547d7b4394eSShubhrajyoti D 548d7b4394eSShubhrajyoti D static unsigned 549d7b4394eSShubhrajyoti D omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) 550d7b4394eSShubhrajyoti D { 551d7b4394eSShubhrajyoti D struct omap2_mcspi *mcspi; 552d7b4394eSShubhrajyoti D struct omap2_mcspi_cs *cs = spi->controller_state; 553d7b4394eSShubhrajyoti D struct omap2_mcspi_dma *mcspi_dma; 554d7b4394eSShubhrajyoti D unsigned int count; 555d7b4394eSShubhrajyoti D u32 l; 556d7b4394eSShubhrajyoti D u8 *rx; 557d7b4394eSShubhrajyoti D const u8 *tx; 558d7b4394eSShubhrajyoti D struct dma_slave_config cfg; 559d7b4394eSShubhrajyoti D enum dma_slave_buswidth width; 560d7b4394eSShubhrajyoti D unsigned es; 561d33f473dSIllia Smyrnov u32 burst; 562e47a682aSShubhrajyoti D void __iomem *chstat_reg; 563d33f473dSIllia Smyrnov void __iomem *irqstat_reg; 564d33f473dSIllia Smyrnov int wait_res; 565d7b4394eSShubhrajyoti D 566d7b4394eSShubhrajyoti D mcspi = spi_master_get_devdata(spi->master); 567d7b4394eSShubhrajyoti D mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 568d7b4394eSShubhrajyoti D l = mcspi_cached_chconf0(spi); 569d7b4394eSShubhrajyoti D 570d7b4394eSShubhrajyoti D 571d7b4394eSShubhrajyoti D if (cs->word_len <= 8) { 572d7b4394eSShubhrajyoti D width = DMA_SLAVE_BUSWIDTH_1_BYTE; 573d7b4394eSShubhrajyoti D es = 1; 574d7b4394eSShubhrajyoti D } else if (cs->word_len <= 16) { 575d7b4394eSShubhrajyoti D width = DMA_SLAVE_BUSWIDTH_2_BYTES; 576d7b4394eSShubhrajyoti D es = 2; 577d7b4394eSShubhrajyoti D } else { 578d7b4394eSShubhrajyoti D width = DMA_SLAVE_BUSWIDTH_4_BYTES; 579d7b4394eSShubhrajyoti D es = 4; 580d7b4394eSShubhrajyoti D } 581d7b4394eSShubhrajyoti D 582d33f473dSIllia Smyrnov count = xfer->len; 583d33f473dSIllia Smyrnov burst = 1; 584d33f473dSIllia Smyrnov 585d33f473dSIllia Smyrnov if (mcspi->fifo_depth > 0) { 586d33f473dSIllia Smyrnov if (count > mcspi->fifo_depth) 587d33f473dSIllia Smyrnov burst = mcspi->fifo_depth / es; 588d33f473dSIllia Smyrnov else 589d33f473dSIllia Smyrnov burst = count / es; 590d33f473dSIllia Smyrnov } 591d33f473dSIllia Smyrnov 592d7b4394eSShubhrajyoti D memset(&cfg, 0, sizeof(cfg)); 593d7b4394eSShubhrajyoti D cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; 594d7b4394eSShubhrajyoti D cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; 595d7b4394eSShubhrajyoti D cfg.src_addr_width = width; 596d7b4394eSShubhrajyoti D cfg.dst_addr_width = width; 597d33f473dSIllia Smyrnov cfg.src_maxburst = burst; 598d33f473dSIllia Smyrnov cfg.dst_maxburst = burst; 599d7b4394eSShubhrajyoti D 600d7b4394eSShubhrajyoti D rx = xfer->rx_buf; 601d7b4394eSShubhrajyoti D tx = xfer->tx_buf; 602d7b4394eSShubhrajyoti D 603d7b4394eSShubhrajyoti D if (tx != NULL) 604d7b4394eSShubhrajyoti D omap2_mcspi_tx_dma(spi, xfer, cfg); 605d7b4394eSShubhrajyoti D 606d7b4394eSShubhrajyoti D if (rx != NULL) 607e47a682aSShubhrajyoti D count = omap2_mcspi_rx_dma(spi, xfer, cfg, es); 608d7b4394eSShubhrajyoti D 609e47a682aSShubhrajyoti D if (tx != NULL) { 610e47a682aSShubhrajyoti D wait_for_completion(&mcspi_dma->dma_tx_completion); 611e47a682aSShubhrajyoti D dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len, 612e47a682aSShubhrajyoti D DMA_TO_DEVICE); 613e47a682aSShubhrajyoti D 614d33f473dSIllia Smyrnov if (mcspi->fifo_depth > 0) { 615d33f473dSIllia Smyrnov irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS; 616d33f473dSIllia Smyrnov 617d33f473dSIllia Smyrnov if (mcspi_wait_for_reg_bit(irqstat_reg, 618d33f473dSIllia Smyrnov OMAP2_MCSPI_IRQSTATUS_EOW) < 0) 619d33f473dSIllia Smyrnov dev_err(&spi->dev, "EOW timed out\n"); 620d33f473dSIllia Smyrnov 621d33f473dSIllia Smyrnov mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS, 622d33f473dSIllia Smyrnov OMAP2_MCSPI_IRQSTATUS_EOW); 623d33f473dSIllia Smyrnov } 624d33f473dSIllia Smyrnov 625e47a682aSShubhrajyoti D /* for TX_ONLY mode, be sure all words have shifted out */ 626e47a682aSShubhrajyoti D if (rx == NULL) { 627d33f473dSIllia Smyrnov chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; 628d33f473dSIllia Smyrnov if (mcspi->fifo_depth > 0) { 629d33f473dSIllia Smyrnov wait_res = mcspi_wait_for_reg_bit(chstat_reg, 630d33f473dSIllia Smyrnov OMAP2_MCSPI_CHSTAT_TXFFE); 631d33f473dSIllia Smyrnov if (wait_res < 0) 632d33f473dSIllia Smyrnov dev_err(&spi->dev, "TXFFE timed out\n"); 633d33f473dSIllia Smyrnov } else { 634d33f473dSIllia Smyrnov wait_res = mcspi_wait_for_reg_bit(chstat_reg, 635d33f473dSIllia Smyrnov OMAP2_MCSPI_CHSTAT_TXS); 636d33f473dSIllia Smyrnov if (wait_res < 0) 637e47a682aSShubhrajyoti D dev_err(&spi->dev, "TXS timed out\n"); 638d33f473dSIllia Smyrnov } 639d33f473dSIllia Smyrnov if (wait_res >= 0 && 640d33f473dSIllia Smyrnov (mcspi_wait_for_reg_bit(chstat_reg, 641d33f473dSIllia Smyrnov OMAP2_MCSPI_CHSTAT_EOT) < 0)) 642e47a682aSShubhrajyoti D dev_err(&spi->dev, "EOT timed out\n"); 643e47a682aSShubhrajyoti D } 644e47a682aSShubhrajyoti D } 645ca632f55SGrant Likely return count; 646ca632f55SGrant Likely } 647ca632f55SGrant Likely 648ca632f55SGrant Likely static unsigned 649ca632f55SGrant Likely omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) 650ca632f55SGrant Likely { 651ca632f55SGrant Likely struct omap2_mcspi *mcspi; 652ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 653ca632f55SGrant Likely unsigned int count, c; 654ca632f55SGrant Likely u32 l; 655ca632f55SGrant Likely void __iomem *base = cs->base; 656ca632f55SGrant Likely void __iomem *tx_reg; 657ca632f55SGrant Likely void __iomem *rx_reg; 658ca632f55SGrant Likely void __iomem *chstat_reg; 659ca632f55SGrant Likely int word_len; 660ca632f55SGrant Likely 661ca632f55SGrant Likely mcspi = spi_master_get_devdata(spi->master); 662ca632f55SGrant Likely count = xfer->len; 663ca632f55SGrant Likely c = count; 664ca632f55SGrant Likely word_len = cs->word_len; 665ca632f55SGrant Likely 666ca632f55SGrant Likely l = mcspi_cached_chconf0(spi); 667ca632f55SGrant Likely 668ca632f55SGrant Likely /* We store the pre-calculated register addresses on stack to speed 669ca632f55SGrant Likely * up the transfer loop. */ 670ca632f55SGrant Likely tx_reg = base + OMAP2_MCSPI_TX0; 671ca632f55SGrant Likely rx_reg = base + OMAP2_MCSPI_RX0; 672ca632f55SGrant Likely chstat_reg = base + OMAP2_MCSPI_CHSTAT0; 673ca632f55SGrant Likely 674ca632f55SGrant Likely if (c < (word_len>>3)) 675ca632f55SGrant Likely return 0; 676ca632f55SGrant Likely 677ca632f55SGrant Likely if (word_len <= 8) { 678ca632f55SGrant Likely u8 *rx; 679ca632f55SGrant Likely const u8 *tx; 680ca632f55SGrant Likely 681ca632f55SGrant Likely rx = xfer->rx_buf; 682ca632f55SGrant Likely tx = xfer->tx_buf; 683ca632f55SGrant Likely 684ca632f55SGrant Likely do { 685ca632f55SGrant Likely c -= 1; 686ca632f55SGrant Likely if (tx != NULL) { 687ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 688ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_TXS) < 0) { 689ca632f55SGrant Likely dev_err(&spi->dev, "TXS timed out\n"); 690ca632f55SGrant Likely goto out; 691ca632f55SGrant Likely } 692ca632f55SGrant Likely dev_vdbg(&spi->dev, "write-%d %02x\n", 693ca632f55SGrant Likely word_len, *tx); 69421b2ce5eSVictor Kamensky writel_relaxed(*tx++, tx_reg); 695ca632f55SGrant Likely } 696ca632f55SGrant Likely if (rx != NULL) { 697ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 698ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_RXS) < 0) { 699ca632f55SGrant Likely dev_err(&spi->dev, "RXS timed out\n"); 700ca632f55SGrant Likely goto out; 701ca632f55SGrant Likely } 702ca632f55SGrant Likely 703ca632f55SGrant Likely if (c == 1 && tx == NULL && 704ca632f55SGrant Likely (l & OMAP2_MCSPI_CHCONF_TURBO)) { 705ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 70621b2ce5eSVictor Kamensky *rx++ = readl_relaxed(rx_reg); 707ca632f55SGrant Likely dev_vdbg(&spi->dev, "read-%d %02x\n", 708ca632f55SGrant Likely word_len, *(rx - 1)); 709ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 710ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_RXS) < 0) { 711ca632f55SGrant Likely dev_err(&spi->dev, 712ca632f55SGrant Likely "RXS timed out\n"); 713ca632f55SGrant Likely goto out; 714ca632f55SGrant Likely } 715ca632f55SGrant Likely c = 0; 716ca632f55SGrant Likely } else if (c == 0 && tx == NULL) { 717ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 718ca632f55SGrant Likely } 719ca632f55SGrant Likely 72021b2ce5eSVictor Kamensky *rx++ = readl_relaxed(rx_reg); 721ca632f55SGrant Likely dev_vdbg(&spi->dev, "read-%d %02x\n", 722ca632f55SGrant Likely word_len, *(rx - 1)); 723ca632f55SGrant Likely } 724ca632f55SGrant Likely } while (c); 725ca632f55SGrant Likely } else if (word_len <= 16) { 726ca632f55SGrant Likely u16 *rx; 727ca632f55SGrant Likely const u16 *tx; 728ca632f55SGrant Likely 729ca632f55SGrant Likely rx = xfer->rx_buf; 730ca632f55SGrant Likely tx = xfer->tx_buf; 731ca632f55SGrant Likely do { 732ca632f55SGrant Likely c -= 2; 733ca632f55SGrant Likely if (tx != NULL) { 734ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 735ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_TXS) < 0) { 736ca632f55SGrant Likely dev_err(&spi->dev, "TXS timed out\n"); 737ca632f55SGrant Likely goto out; 738ca632f55SGrant Likely } 739ca632f55SGrant Likely dev_vdbg(&spi->dev, "write-%d %04x\n", 740ca632f55SGrant Likely word_len, *tx); 74121b2ce5eSVictor Kamensky writel_relaxed(*tx++, tx_reg); 742ca632f55SGrant Likely } 743ca632f55SGrant Likely if (rx != NULL) { 744ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 745ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_RXS) < 0) { 746ca632f55SGrant Likely dev_err(&spi->dev, "RXS timed out\n"); 747ca632f55SGrant Likely goto out; 748ca632f55SGrant Likely } 749ca632f55SGrant Likely 750ca632f55SGrant Likely if (c == 2 && tx == NULL && 751ca632f55SGrant Likely (l & OMAP2_MCSPI_CHCONF_TURBO)) { 752ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 75321b2ce5eSVictor Kamensky *rx++ = readl_relaxed(rx_reg); 754ca632f55SGrant Likely dev_vdbg(&spi->dev, "read-%d %04x\n", 755ca632f55SGrant Likely word_len, *(rx - 1)); 756ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 757ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_RXS) < 0) { 758ca632f55SGrant Likely dev_err(&spi->dev, 759ca632f55SGrant Likely "RXS timed out\n"); 760ca632f55SGrant Likely goto out; 761ca632f55SGrant Likely } 762ca632f55SGrant Likely c = 0; 763ca632f55SGrant Likely } else if (c == 0 && tx == NULL) { 764ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 765ca632f55SGrant Likely } 766ca632f55SGrant Likely 76721b2ce5eSVictor Kamensky *rx++ = readl_relaxed(rx_reg); 768ca632f55SGrant Likely dev_vdbg(&spi->dev, "read-%d %04x\n", 769ca632f55SGrant Likely word_len, *(rx - 1)); 770ca632f55SGrant Likely } 771ca632f55SGrant Likely } while (c >= 2); 772ca632f55SGrant Likely } else if (word_len <= 32) { 773ca632f55SGrant Likely u32 *rx; 774ca632f55SGrant Likely const u32 *tx; 775ca632f55SGrant Likely 776ca632f55SGrant Likely rx = xfer->rx_buf; 777ca632f55SGrant Likely tx = xfer->tx_buf; 778ca632f55SGrant Likely do { 779ca632f55SGrant Likely c -= 4; 780ca632f55SGrant Likely if (tx != NULL) { 781ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 782ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_TXS) < 0) { 783ca632f55SGrant Likely dev_err(&spi->dev, "TXS timed out\n"); 784ca632f55SGrant Likely goto out; 785ca632f55SGrant Likely } 786ca632f55SGrant Likely dev_vdbg(&spi->dev, "write-%d %08x\n", 787ca632f55SGrant Likely word_len, *tx); 78821b2ce5eSVictor Kamensky writel_relaxed(*tx++, tx_reg); 789ca632f55SGrant Likely } 790ca632f55SGrant Likely if (rx != NULL) { 791ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 792ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_RXS) < 0) { 793ca632f55SGrant Likely dev_err(&spi->dev, "RXS timed out\n"); 794ca632f55SGrant Likely goto out; 795ca632f55SGrant Likely } 796ca632f55SGrant Likely 797ca632f55SGrant Likely if (c == 4 && tx == NULL && 798ca632f55SGrant Likely (l & OMAP2_MCSPI_CHCONF_TURBO)) { 799ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 80021b2ce5eSVictor Kamensky *rx++ = readl_relaxed(rx_reg); 801ca632f55SGrant Likely dev_vdbg(&spi->dev, "read-%d %08x\n", 802ca632f55SGrant Likely word_len, *(rx - 1)); 803ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 804ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_RXS) < 0) { 805ca632f55SGrant Likely dev_err(&spi->dev, 806ca632f55SGrant Likely "RXS timed out\n"); 807ca632f55SGrant Likely goto out; 808ca632f55SGrant Likely } 809ca632f55SGrant Likely c = 0; 810ca632f55SGrant Likely } else if (c == 0 && tx == NULL) { 811ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 812ca632f55SGrant Likely } 813ca632f55SGrant Likely 81421b2ce5eSVictor Kamensky *rx++ = readl_relaxed(rx_reg); 815ca632f55SGrant Likely dev_vdbg(&spi->dev, "read-%d %08x\n", 816ca632f55SGrant Likely word_len, *(rx - 1)); 817ca632f55SGrant Likely } 818ca632f55SGrant Likely } while (c >= 4); 819ca632f55SGrant Likely } 820ca632f55SGrant Likely 821ca632f55SGrant Likely /* for TX_ONLY mode, be sure all words have shifted out */ 822ca632f55SGrant Likely if (xfer->rx_buf == NULL) { 823ca632f55SGrant Likely if (mcspi_wait_for_reg_bit(chstat_reg, 824ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_TXS) < 0) { 825ca632f55SGrant Likely dev_err(&spi->dev, "TXS timed out\n"); 826ca632f55SGrant Likely } else if (mcspi_wait_for_reg_bit(chstat_reg, 827ca632f55SGrant Likely OMAP2_MCSPI_CHSTAT_EOT) < 0) 828ca632f55SGrant Likely dev_err(&spi->dev, "EOT timed out\n"); 829ca632f55SGrant Likely 830ca632f55SGrant Likely /* disable chan to purge rx datas received in TX_ONLY transfer, 831ca632f55SGrant Likely * otherwise these rx datas will affect the direct following 832ca632f55SGrant Likely * RX_ONLY transfer. 833ca632f55SGrant Likely */ 834ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 835ca632f55SGrant Likely } 836ca632f55SGrant Likely out: 837ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 1); 838ca632f55SGrant Likely return count - c; 839ca632f55SGrant Likely } 840ca632f55SGrant Likely 841ca632f55SGrant Likely static u32 omap2_mcspi_calc_divisor(u32 speed_hz) 842ca632f55SGrant Likely { 843ca632f55SGrant Likely u32 div; 844ca632f55SGrant Likely 845ca632f55SGrant Likely for (div = 0; div < 15; div++) 846ca632f55SGrant Likely if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div)) 847ca632f55SGrant Likely return div; 848ca632f55SGrant Likely 849ca632f55SGrant Likely return 15; 850ca632f55SGrant Likely } 851ca632f55SGrant Likely 852ca632f55SGrant Likely /* called only when no transfer is active to this device */ 853ca632f55SGrant Likely static int omap2_mcspi_setup_transfer(struct spi_device *spi, 854ca632f55SGrant Likely struct spi_transfer *t) 855ca632f55SGrant Likely { 856ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 857ca632f55SGrant Likely struct omap2_mcspi *mcspi; 858ca632f55SGrant Likely struct spi_master *spi_cntrl; 859faee9b05SStefan Sørensen u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0; 860ca632f55SGrant Likely u8 word_len = spi->bits_per_word; 861ca632f55SGrant Likely u32 speed_hz = spi->max_speed_hz; 862ca632f55SGrant Likely 863ca632f55SGrant Likely mcspi = spi_master_get_devdata(spi->master); 864ca632f55SGrant Likely spi_cntrl = mcspi->master; 865ca632f55SGrant Likely 866ca632f55SGrant Likely if (t != NULL && t->bits_per_word) 867ca632f55SGrant Likely word_len = t->bits_per_word; 868ca632f55SGrant Likely 869ca632f55SGrant Likely cs->word_len = word_len; 870ca632f55SGrant Likely 871ca632f55SGrant Likely if (t && t->speed_hz) 872ca632f55SGrant Likely speed_hz = t->speed_hz; 873ca632f55SGrant Likely 874ca632f55SGrant Likely speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); 875faee9b05SStefan Sørensen if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) { 876faee9b05SStefan Sørensen clkd = omap2_mcspi_calc_divisor(speed_hz); 877faee9b05SStefan Sørensen speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd; 878faee9b05SStefan Sørensen clkg = 0; 879faee9b05SStefan Sørensen } else { 880faee9b05SStefan Sørensen div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz; 881faee9b05SStefan Sørensen speed_hz = OMAP2_MCSPI_MAX_FREQ / div; 882faee9b05SStefan Sørensen clkd = (div - 1) & 0xf; 883faee9b05SStefan Sørensen extclk = (div - 1) >> 4; 884faee9b05SStefan Sørensen clkg = OMAP2_MCSPI_CHCONF_CLKG; 885faee9b05SStefan Sørensen } 886ca632f55SGrant Likely 887ca632f55SGrant Likely l = mcspi_cached_chconf0(spi); 888ca632f55SGrant Likely 889ca632f55SGrant Likely /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS 890ca632f55SGrant Likely * REVISIT: this controller could support SPI_3WIRE mode. 891ca632f55SGrant Likely */ 8922cd45179SDaniel Mack if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) { 8930384e90bSDaniel Mack l &= ~OMAP2_MCSPI_CHCONF_IS; 8940384e90bSDaniel Mack l &= ~OMAP2_MCSPI_CHCONF_DPE1; 895ca632f55SGrant Likely l |= OMAP2_MCSPI_CHCONF_DPE0; 8960384e90bSDaniel Mack } else { 8970384e90bSDaniel Mack l |= OMAP2_MCSPI_CHCONF_IS; 8980384e90bSDaniel Mack l |= OMAP2_MCSPI_CHCONF_DPE1; 8990384e90bSDaniel Mack l &= ~OMAP2_MCSPI_CHCONF_DPE0; 9000384e90bSDaniel Mack } 901ca632f55SGrant Likely 902ca632f55SGrant Likely /* wordlength */ 903ca632f55SGrant Likely l &= ~OMAP2_MCSPI_CHCONF_WL_MASK; 904ca632f55SGrant Likely l |= (word_len - 1) << 7; 905ca632f55SGrant Likely 906ca632f55SGrant Likely /* set chipselect polarity; manage with FORCE */ 907ca632f55SGrant Likely if (!(spi->mode & SPI_CS_HIGH)) 908ca632f55SGrant Likely l |= OMAP2_MCSPI_CHCONF_EPOL; /* active-low; normal */ 909ca632f55SGrant Likely else 910ca632f55SGrant Likely l &= ~OMAP2_MCSPI_CHCONF_EPOL; 911ca632f55SGrant Likely 912ca632f55SGrant Likely /* set clock divisor */ 913ca632f55SGrant Likely l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK; 914faee9b05SStefan Sørensen l |= clkd << 2; 915faee9b05SStefan Sørensen 916faee9b05SStefan Sørensen /* set clock granularity */ 917faee9b05SStefan Sørensen l &= ~OMAP2_MCSPI_CHCONF_CLKG; 918faee9b05SStefan Sørensen l |= clkg; 919faee9b05SStefan Sørensen if (clkg) { 920faee9b05SStefan Sørensen cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK; 921faee9b05SStefan Sørensen cs->chctrl0 |= extclk << 8; 922faee9b05SStefan Sørensen mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0); 923faee9b05SStefan Sørensen } 924ca632f55SGrant Likely 925ca632f55SGrant Likely /* set SPI mode 0..3 */ 926ca632f55SGrant Likely if (spi->mode & SPI_CPOL) 927ca632f55SGrant Likely l |= OMAP2_MCSPI_CHCONF_POL; 928ca632f55SGrant Likely else 929ca632f55SGrant Likely l &= ~OMAP2_MCSPI_CHCONF_POL; 930ca632f55SGrant Likely if (spi->mode & SPI_CPHA) 931ca632f55SGrant Likely l |= OMAP2_MCSPI_CHCONF_PHA; 932ca632f55SGrant Likely else 933ca632f55SGrant Likely l &= ~OMAP2_MCSPI_CHCONF_PHA; 934ca632f55SGrant Likely 935ca632f55SGrant Likely mcspi_write_chconf0(spi, l); 936ca632f55SGrant Likely 93797ca0d6cSMark A. Greer cs->mode = spi->mode; 93897ca0d6cSMark A. Greer 939ca632f55SGrant Likely dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", 940faee9b05SStefan Sørensen speed_hz, 941ca632f55SGrant Likely (spi->mode & SPI_CPHA) ? "trailing" : "leading", 942ca632f55SGrant Likely (spi->mode & SPI_CPOL) ? "inverted" : "normal"); 943ca632f55SGrant Likely 944ca632f55SGrant Likely return 0; 945ca632f55SGrant Likely } 946ca632f55SGrant Likely 947ddc5cdf1STony Lindgren /* 948ddc5cdf1STony Lindgren * Note that we currently allow DMA only if we get a channel 949ddc5cdf1STony Lindgren * for both rx and tx. Otherwise we'll do PIO for both rx and tx. 950ddc5cdf1STony Lindgren */ 951ca632f55SGrant Likely static int omap2_mcspi_request_dma(struct spi_device *spi) 952ca632f55SGrant Likely { 953ca632f55SGrant Likely struct spi_master *master = spi->master; 954ca632f55SGrant Likely struct omap2_mcspi *mcspi; 955ca632f55SGrant Likely struct omap2_mcspi_dma *mcspi_dma; 95653741ed8SRussell King dma_cap_mask_t mask; 95753741ed8SRussell King unsigned sig; 958ca632f55SGrant Likely 959ca632f55SGrant Likely mcspi = spi_master_get_devdata(master); 960ca632f55SGrant Likely mcspi_dma = mcspi->dma_channels + spi->chip_select; 961ca632f55SGrant Likely 962ca632f55SGrant Likely init_completion(&mcspi_dma->dma_rx_completion); 963ca632f55SGrant Likely init_completion(&mcspi_dma->dma_tx_completion); 964ca632f55SGrant Likely 96553741ed8SRussell King dma_cap_zero(mask); 96653741ed8SRussell King dma_cap_set(DMA_SLAVE, mask); 96753741ed8SRussell King sig = mcspi_dma->dma_rx_sync_dev; 96874f3aaadSMatt Porter 96974f3aaadSMatt Porter mcspi_dma->dma_rx = 97074f3aaadSMatt Porter dma_request_slave_channel_compat(mask, omap_dma_filter_fn, 97174f3aaadSMatt Porter &sig, &master->dev, 97274f3aaadSMatt Porter mcspi_dma->dma_rx_ch_name); 973ddc5cdf1STony Lindgren if (!mcspi_dma->dma_rx) 974ddc5cdf1STony Lindgren goto no_dma; 975ca632f55SGrant Likely 97653741ed8SRussell King sig = mcspi_dma->dma_tx_sync_dev; 97774f3aaadSMatt Porter mcspi_dma->dma_tx = 97874f3aaadSMatt Porter dma_request_slave_channel_compat(mask, omap_dma_filter_fn, 97974f3aaadSMatt Porter &sig, &master->dev, 98074f3aaadSMatt Porter mcspi_dma->dma_tx_ch_name); 98174f3aaadSMatt Porter 98253741ed8SRussell King if (!mcspi_dma->dma_tx) { 98353741ed8SRussell King dma_release_channel(mcspi_dma->dma_rx); 98453741ed8SRussell King mcspi_dma->dma_rx = NULL; 985ddc5cdf1STony Lindgren goto no_dma; 98653741ed8SRussell King } 987ca632f55SGrant Likely 988ca632f55SGrant Likely return 0; 989ddc5cdf1STony Lindgren 990ddc5cdf1STony Lindgren no_dma: 991ddc5cdf1STony Lindgren dev_warn(&spi->dev, "not using DMA for McSPI\n"); 992ddc5cdf1STony Lindgren return -EAGAIN; 993ca632f55SGrant Likely } 994ca632f55SGrant Likely 995ca632f55SGrant Likely static int omap2_mcspi_setup(struct spi_device *spi) 996ca632f55SGrant Likely { 997ca632f55SGrant Likely int ret; 9981bd897f8SBenoit Cousson struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); 9991bd897f8SBenoit Cousson struct omap2_mcspi_regs *ctx = &mcspi->ctx; 1000ca632f55SGrant Likely struct omap2_mcspi_dma *mcspi_dma; 1001ca632f55SGrant Likely struct omap2_mcspi_cs *cs = spi->controller_state; 1002ca632f55SGrant Likely 1003ca632f55SGrant Likely mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 1004ca632f55SGrant Likely 1005ca632f55SGrant Likely if (!cs) { 100610aa5a35SRussell King cs = kzalloc(sizeof *cs, GFP_KERNEL); 1007ca632f55SGrant Likely if (!cs) 1008ca632f55SGrant Likely return -ENOMEM; 1009ca632f55SGrant Likely cs->base = mcspi->base + spi->chip_select * 0x14; 1010ca632f55SGrant Likely cs->phys = mcspi->phys + spi->chip_select * 0x14; 101197ca0d6cSMark A. Greer cs->mode = 0; 1012ca632f55SGrant Likely cs->chconf0 = 0; 1013faee9b05SStefan Sørensen cs->chctrl0 = 0; 1014ca632f55SGrant Likely spi->controller_state = cs; 1015ca632f55SGrant Likely /* Link this to context save list */ 10161bd897f8SBenoit Cousson list_add_tail(&cs->node, &ctx->cs); 1017ca632f55SGrant Likely } 1018ca632f55SGrant Likely 10198c7494a5SRussell King if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { 1020ca632f55SGrant Likely ret = omap2_mcspi_request_dma(spi); 1021ddc5cdf1STony Lindgren if (ret < 0 && ret != -EAGAIN) 1022ca632f55SGrant Likely return ret; 1023ca632f55SGrant Likely } 1024ca632f55SGrant Likely 1025bc7f9bbcSMichael Welling if (gpio_is_valid(spi->cs_gpio)) { 1026bc7f9bbcSMichael Welling if (gpio_request(spi->cs_gpio, dev_name(&spi->dev)) == 0) 1027bc7f9bbcSMichael Welling gpio_direction_output(spi->cs_gpio, 1028bc7f9bbcSMichael Welling !(spi->mode & SPI_CS_HIGH)); 1029bc7f9bbcSMichael Welling } 1030bc7f9bbcSMichael Welling 1031034d3dc9SShubhrajyoti D ret = pm_runtime_get_sync(mcspi->dev); 1032ca632f55SGrant Likely if (ret < 0) 1033ca632f55SGrant Likely return ret; 1034ca632f55SGrant Likely 1035ca632f55SGrant Likely ret = omap2_mcspi_setup_transfer(spi, NULL); 1036034d3dc9SShubhrajyoti D pm_runtime_mark_last_busy(mcspi->dev); 1037034d3dc9SShubhrajyoti D pm_runtime_put_autosuspend(mcspi->dev); 1038ca632f55SGrant Likely 1039ca632f55SGrant Likely return ret; 1040ca632f55SGrant Likely } 1041ca632f55SGrant Likely 1042ca632f55SGrant Likely static void omap2_mcspi_cleanup(struct spi_device *spi) 1043ca632f55SGrant Likely { 1044ca632f55SGrant Likely struct omap2_mcspi *mcspi; 1045ca632f55SGrant Likely struct omap2_mcspi_dma *mcspi_dma; 1046ca632f55SGrant Likely struct omap2_mcspi_cs *cs; 1047ca632f55SGrant Likely 1048ca632f55SGrant Likely mcspi = spi_master_get_devdata(spi->master); 1049ca632f55SGrant Likely 1050ca632f55SGrant Likely if (spi->controller_state) { 1051ca632f55SGrant Likely /* Unlink controller state from context save list */ 1052ca632f55SGrant Likely cs = spi->controller_state; 1053ca632f55SGrant Likely list_del(&cs->node); 1054ca632f55SGrant Likely 105510aa5a35SRussell King kfree(cs); 1056ca632f55SGrant Likely } 1057ca632f55SGrant Likely 1058ca632f55SGrant Likely if (spi->chip_select < spi->master->num_chipselect) { 1059ca632f55SGrant Likely mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 1060ca632f55SGrant Likely 106153741ed8SRussell King if (mcspi_dma->dma_rx) { 106253741ed8SRussell King dma_release_channel(mcspi_dma->dma_rx); 106353741ed8SRussell King mcspi_dma->dma_rx = NULL; 1064ca632f55SGrant Likely } 106553741ed8SRussell King if (mcspi_dma->dma_tx) { 106653741ed8SRussell King dma_release_channel(mcspi_dma->dma_tx); 106753741ed8SRussell King mcspi_dma->dma_tx = NULL; 1068ca632f55SGrant Likely } 1069ca632f55SGrant Likely } 1070bc7f9bbcSMichael Welling 1071bc7f9bbcSMichael Welling if (gpio_is_valid(spi->cs_gpio)) 1072bc7f9bbcSMichael Welling gpio_free(spi->cs_gpio); 1073ca632f55SGrant Likely } 1074ca632f55SGrant Likely 1075b28cb941SMichael Welling static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, 1076b28cb941SMichael Welling struct spi_device *spi, struct spi_transfer *t) 1077ca632f55SGrant Likely { 1078ca632f55SGrant Likely 1079ca632f55SGrant Likely /* We only enable one channel at a time -- the one whose message is 10805fda88f5SShubhrajyoti D * -- although this controller would gladly 1081ca632f55SGrant Likely * arbitrate among multiple channels. This corresponds to "single 1082ca632f55SGrant Likely * channel" master mode. As a side effect, we need to manage the 1083ca632f55SGrant Likely * chipselect with the FORCE bit ... CS != channel enable. 1084ca632f55SGrant Likely */ 10855fda88f5SShubhrajyoti D 10865cbc7ca9SMatthias Brugger struct spi_master *master; 1087ddc5cdf1STony Lindgren struct omap2_mcspi_dma *mcspi_dma; 1088ca632f55SGrant Likely struct omap2_mcspi_cs *cs; 1089ca632f55SGrant Likely struct omap2_mcspi_device_config *cd; 1090ca632f55SGrant Likely int par_override = 0; 1091ca632f55SGrant Likely int status = 0; 1092ca632f55SGrant Likely u32 chconf; 1093ca632f55SGrant Likely 10945cbc7ca9SMatthias Brugger master = spi->master; 1095ddc5cdf1STony Lindgren mcspi_dma = mcspi->dma_channels + spi->chip_select; 1096ca632f55SGrant Likely cs = spi->controller_state; 1097ca632f55SGrant Likely cd = spi->controller_data; 1098ca632f55SGrant Likely 109997ca0d6cSMark A. Greer /* 110097ca0d6cSMark A. Greer * The slave driver could have changed spi->mode in which case 110197ca0d6cSMark A. Greer * it will be different from cs->mode (the current hardware setup). 110297ca0d6cSMark A. Greer * If so, set par_override (even though its not a parity issue) so 110397ca0d6cSMark A. Greer * omap2_mcspi_setup_transfer will be called to configure the hardware 110497ca0d6cSMark A. Greer * with the correct mode on the first iteration of the loop below. 110597ca0d6cSMark A. Greer */ 110697ca0d6cSMark A. Greer if (spi->mode != cs->mode) 110797ca0d6cSMark A. Greer par_override = 1; 110897ca0d6cSMark A. Greer 1109d33f473dSIllia Smyrnov omap2_mcspi_set_enable(spi, 0); 1110b28cb941SMichael Welling 11112bd16e3eSStefan Sørensen if (par_override || 11122bd16e3eSStefan Sørensen (t->speed_hz != spi->max_speed_hz) || 11132bd16e3eSStefan Sørensen (t->bits_per_word != spi->bits_per_word)) { 1114ca632f55SGrant Likely par_override = 1; 1115ca632f55SGrant Likely status = omap2_mcspi_setup_transfer(spi, t); 1116ca632f55SGrant Likely if (status < 0) 1117b28cb941SMichael Welling goto out; 11182bd16e3eSStefan Sørensen if (t->speed_hz == spi->max_speed_hz && 11192bd16e3eSStefan Sørensen t->bits_per_word == spi->bits_per_word) 1120ca632f55SGrant Likely par_override = 0; 1121ca632f55SGrant Likely } 11225cbc7ca9SMatthias Brugger if (cd && cd->cs_per_word) { 11235cbc7ca9SMatthias Brugger chconf = mcspi->ctx.modulctrl; 11245cbc7ca9SMatthias Brugger chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE; 11255cbc7ca9SMatthias Brugger mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf); 11265cbc7ca9SMatthias Brugger mcspi->ctx.modulctrl = 11275cbc7ca9SMatthias Brugger mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL); 11285cbc7ca9SMatthias Brugger } 11295cbc7ca9SMatthias Brugger 1130ca632f55SGrant Likely chconf = mcspi_cached_chconf0(spi); 1131ca632f55SGrant Likely chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; 1132ca632f55SGrant Likely chconf &= ~OMAP2_MCSPI_CHCONF_TURBO; 1133ca632f55SGrant Likely 1134ca632f55SGrant Likely if (t->tx_buf == NULL) 1135ca632f55SGrant Likely chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY; 1136ca632f55SGrant Likely else if (t->rx_buf == NULL) 1137ca632f55SGrant Likely chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY; 1138ca632f55SGrant Likely 1139ca632f55SGrant Likely if (cd && cd->turbo_mode && t->tx_buf == NULL) { 1140ca632f55SGrant Likely /* Turbo mode is for more than one word */ 1141ca632f55SGrant Likely if (t->len > ((cs->word_len + 7) >> 3)) 1142ca632f55SGrant Likely chconf |= OMAP2_MCSPI_CHCONF_TURBO; 1143ca632f55SGrant Likely } 1144ca632f55SGrant Likely 1145ca632f55SGrant Likely mcspi_write_chconf0(spi, chconf); 1146ca632f55SGrant Likely 1147ca632f55SGrant Likely if (t->len) { 1148ca632f55SGrant Likely unsigned count; 1149ca632f55SGrant Likely 1150d33f473dSIllia Smyrnov if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && 1151b28cb941SMichael Welling (t->len >= DMA_MIN_BYTES)) 1152d33f473dSIllia Smyrnov omap2_mcspi_set_fifo(spi, t, 1); 1153d33f473dSIllia Smyrnov 1154d33f473dSIllia Smyrnov omap2_mcspi_set_enable(spi, 1); 1155d33f473dSIllia Smyrnov 1156ca632f55SGrant Likely /* RX_ONLY mode needs dummy data in TX reg */ 1157ca632f55SGrant Likely if (t->tx_buf == NULL) 115821b2ce5eSVictor Kamensky writel_relaxed(0, cs->base 1159ca632f55SGrant Likely + OMAP2_MCSPI_TX0); 1160ca632f55SGrant Likely 1161ddc5cdf1STony Lindgren if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && 1162b28cb941SMichael Welling (t->len >= DMA_MIN_BYTES)) 1163ca632f55SGrant Likely count = omap2_mcspi_txrx_dma(spi, t); 1164ca632f55SGrant Likely else 1165ca632f55SGrant Likely count = omap2_mcspi_txrx_pio(spi, t); 1166ca632f55SGrant Likely 1167ca632f55SGrant Likely if (count != t->len) { 1168ca632f55SGrant Likely status = -EIO; 1169b28cb941SMichael Welling goto out; 1170ca632f55SGrant Likely } 1171ca632f55SGrant Likely } 1172ca632f55SGrant Likely 1173d33f473dSIllia Smyrnov omap2_mcspi_set_enable(spi, 0); 1174d33f473dSIllia Smyrnov 1175d33f473dSIllia Smyrnov if (mcspi->fifo_depth > 0) 1176d33f473dSIllia Smyrnov omap2_mcspi_set_fifo(spi, t, 0); 1177b28cb941SMichael Welling 1178b28cb941SMichael Welling out: 1179ca632f55SGrant Likely /* Restore defaults if they were overriden */ 1180ca632f55SGrant Likely if (par_override) { 1181ca632f55SGrant Likely par_override = 0; 1182ca632f55SGrant Likely status = omap2_mcspi_setup_transfer(spi, NULL); 1183ca632f55SGrant Likely } 1184ca632f55SGrant Likely 11855cbc7ca9SMatthias Brugger if (cd && cd->cs_per_word) { 11865cbc7ca9SMatthias Brugger chconf = mcspi->ctx.modulctrl; 11875cbc7ca9SMatthias Brugger chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE; 11885cbc7ca9SMatthias Brugger mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf); 11895cbc7ca9SMatthias Brugger mcspi->ctx.modulctrl = 11905cbc7ca9SMatthias Brugger mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL); 11915cbc7ca9SMatthias Brugger } 11925cbc7ca9SMatthias Brugger 1193ca632f55SGrant Likely omap2_mcspi_set_enable(spi, 0); 1194ca632f55SGrant Likely 1195d33f473dSIllia Smyrnov if (mcspi->fifo_depth > 0 && t) 1196d33f473dSIllia Smyrnov omap2_mcspi_set_fifo(spi, t, 0); 1197ca632f55SGrant Likely 1198b28cb941SMichael Welling return status; 1199ca632f55SGrant Likely } 1200ca632f55SGrant Likely 1201b28cb941SMichael Welling static int omap2_mcspi_transfer_one(struct spi_master *master, 1202b28cb941SMichael Welling struct spi_device *spi, struct spi_transfer *t) 1203ca632f55SGrant Likely { 1204ca632f55SGrant Likely struct omap2_mcspi *mcspi; 1205ddc5cdf1STony Lindgren struct omap2_mcspi_dma *mcspi_dma; 1206ca632f55SGrant Likely const void *tx_buf = t->tx_buf; 1207ca632f55SGrant Likely void *rx_buf = t->rx_buf; 1208ca632f55SGrant Likely unsigned len = t->len; 1209ca632f55SGrant Likely 1210b28cb941SMichael Welling mcspi = spi_master_get_devdata(master); 1211b28cb941SMichael Welling mcspi_dma = mcspi->dma_channels + spi->chip_select; 1212b28cb941SMichael Welling 1213aca0924bSAxel Lin if ((len && !(rx_buf || tx_buf))) { 12145fda88f5SShubhrajyoti D dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", 1215ca632f55SGrant Likely t->speed_hz, 1216ca632f55SGrant Likely len, 1217ca632f55SGrant Likely tx_buf ? "tx" : "", 1218ca632f55SGrant Likely rx_buf ? "rx" : "", 1219ca632f55SGrant Likely t->bits_per_word); 1220b28cb941SMichael Welling return -EINVAL; 1221ca632f55SGrant Likely } 1222ca632f55SGrant Likely 1223b28cb941SMichael Welling if (len < DMA_MIN_BYTES) 1224b28cb941SMichael Welling goto skip_dma_map; 1225ca632f55SGrant Likely 1226ddc5cdf1STony Lindgren if (mcspi_dma->dma_tx && tx_buf != NULL) { 12275fda88f5SShubhrajyoti D t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf, 1228ca632f55SGrant Likely len, DMA_TO_DEVICE); 12295fda88f5SShubhrajyoti D if (dma_mapping_error(mcspi->dev, t->tx_dma)) { 12305fda88f5SShubhrajyoti D dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", 1231ca632f55SGrant Likely 'T', len); 1232b28cb941SMichael Welling return -EINVAL; 1233ca632f55SGrant Likely } 1234ca632f55SGrant Likely } 1235ddc5cdf1STony Lindgren if (mcspi_dma->dma_rx && rx_buf != NULL) { 12365fda88f5SShubhrajyoti D t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len, 1237ca632f55SGrant Likely DMA_FROM_DEVICE); 12385fda88f5SShubhrajyoti D if (dma_mapping_error(mcspi->dev, t->rx_dma)) { 12395fda88f5SShubhrajyoti D dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", 1240ca632f55SGrant Likely 'R', len); 1241ca632f55SGrant Likely if (tx_buf != NULL) 12425fda88f5SShubhrajyoti D dma_unmap_single(mcspi->dev, t->tx_dma, 1243ca632f55SGrant Likely len, DMA_TO_DEVICE); 1244b28cb941SMichael Welling return -EINVAL; 1245ca632f55SGrant Likely } 1246ca632f55SGrant Likely } 1247ca632f55SGrant Likely 1248b28cb941SMichael Welling skip_dma_map: 1249b28cb941SMichael Welling return omap2_mcspi_work_one(mcspi, spi, t); 1250ca632f55SGrant Likely } 1251ca632f55SGrant Likely 1252fd4a319bSGrant Likely static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) 1253ca632f55SGrant Likely { 1254ca632f55SGrant Likely struct spi_master *master = mcspi->master; 12551bd897f8SBenoit Cousson struct omap2_mcspi_regs *ctx = &mcspi->ctx; 1256ca632f55SGrant Likely int ret = 0; 1257ca632f55SGrant Likely 1258034d3dc9SShubhrajyoti D ret = pm_runtime_get_sync(mcspi->dev); 1259ca632f55SGrant Likely if (ret < 0) 1260ca632f55SGrant Likely return ret; 1261ca632f55SGrant Likely 126239f8052dSShubhrajyoti D mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, 126339f8052dSShubhrajyoti D OMAP2_MCSPI_WAKEUPENABLE_WKEN); 126439f8052dSShubhrajyoti D ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; 1265ca632f55SGrant Likely 1266ca632f55SGrant Likely omap2_mcspi_set_master_mode(master); 1267034d3dc9SShubhrajyoti D pm_runtime_mark_last_busy(mcspi->dev); 1268034d3dc9SShubhrajyoti D pm_runtime_put_autosuspend(mcspi->dev); 1269ca632f55SGrant Likely return 0; 1270ca632f55SGrant Likely } 1271ca632f55SGrant Likely 1272ca632f55SGrant Likely static int omap_mcspi_runtime_resume(struct device *dev) 1273ca632f55SGrant Likely { 1274ca632f55SGrant Likely struct omap2_mcspi *mcspi; 1275ca632f55SGrant Likely struct spi_master *master; 1276ca632f55SGrant Likely 1277ca632f55SGrant Likely master = dev_get_drvdata(dev); 1278ca632f55SGrant Likely mcspi = spi_master_get_devdata(master); 1279ca632f55SGrant Likely omap2_mcspi_restore_ctx(mcspi); 1280ca632f55SGrant Likely 1281ca632f55SGrant Likely return 0; 1282ca632f55SGrant Likely } 1283ca632f55SGrant Likely 1284d5a80031SBenoit Cousson static struct omap2_mcspi_platform_config omap2_pdata = { 1285d5a80031SBenoit Cousson .regs_offset = 0, 1286d5a80031SBenoit Cousson }; 1287d5a80031SBenoit Cousson 1288d5a80031SBenoit Cousson static struct omap2_mcspi_platform_config omap4_pdata = { 1289d5a80031SBenoit Cousson .regs_offset = OMAP4_MCSPI_REG_OFFSET, 1290d5a80031SBenoit Cousson }; 1291d5a80031SBenoit Cousson 1292d5a80031SBenoit Cousson static const struct of_device_id omap_mcspi_of_match[] = { 1293d5a80031SBenoit Cousson { 1294d5a80031SBenoit Cousson .compatible = "ti,omap2-mcspi", 1295d5a80031SBenoit Cousson .data = &omap2_pdata, 1296d5a80031SBenoit Cousson }, 1297d5a80031SBenoit Cousson { 1298d5a80031SBenoit Cousson .compatible = "ti,omap4-mcspi", 1299d5a80031SBenoit Cousson .data = &omap4_pdata, 1300d5a80031SBenoit Cousson }, 1301d5a80031SBenoit Cousson { }, 1302d5a80031SBenoit Cousson }; 1303d5a80031SBenoit Cousson MODULE_DEVICE_TABLE(of, omap_mcspi_of_match); 1304ca632f55SGrant Likely 1305fd4a319bSGrant Likely static int omap2_mcspi_probe(struct platform_device *pdev) 1306ca632f55SGrant Likely { 1307ca632f55SGrant Likely struct spi_master *master; 130883a01e72SUwe Kleine-König const struct omap2_mcspi_platform_config *pdata; 1309ca632f55SGrant Likely struct omap2_mcspi *mcspi; 1310ca632f55SGrant Likely struct resource *r; 1311ca632f55SGrant Likely int status = 0, i; 1312d5a80031SBenoit Cousson u32 regs_offset = 0; 1313d5a80031SBenoit Cousson static int bus_num = 1; 1314d5a80031SBenoit Cousson struct device_node *node = pdev->dev.of_node; 1315d5a80031SBenoit Cousson const struct of_device_id *match; 1316ca632f55SGrant Likely 1317ca632f55SGrant Likely master = spi_alloc_master(&pdev->dev, sizeof *mcspi); 1318ca632f55SGrant Likely if (master == NULL) { 1319ca632f55SGrant Likely dev_dbg(&pdev->dev, "master allocation failed\n"); 1320ca632f55SGrant Likely return -ENOMEM; 1321ca632f55SGrant Likely } 1322ca632f55SGrant Likely 1323ca632f55SGrant Likely /* the spi->mode bits understood by this driver: */ 1324ca632f55SGrant Likely master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 132524778be2SStephen Warren master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); 1326ca632f55SGrant Likely master->setup = omap2_mcspi_setup; 1327f0278a1aSMark Brown master->auto_runtime_pm = true; 1328b28cb941SMichael Welling master->transfer_one = omap2_mcspi_transfer_one; 1329ddcad7e9SMichael Welling master->set_cs = omap2_mcspi_set_cs; 1330ca632f55SGrant Likely master->cleanup = omap2_mcspi_cleanup; 1331d5a80031SBenoit Cousson master->dev.of_node = node; 1332aca0924bSAxel Lin master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ; 1333aca0924bSAxel Lin master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15; 1334d5a80031SBenoit Cousson 133524b5a82cSJingoo Han platform_set_drvdata(pdev, master); 13360384e90bSDaniel Mack 13370384e90bSDaniel Mack mcspi = spi_master_get_devdata(master); 13380384e90bSDaniel Mack mcspi->master = master; 13390384e90bSDaniel Mack 1340d5a80031SBenoit Cousson match = of_match_device(omap_mcspi_of_match, &pdev->dev); 1341d5a80031SBenoit Cousson if (match) { 1342d5a80031SBenoit Cousson u32 num_cs = 1; /* default number of chipselect */ 1343d5a80031SBenoit Cousson pdata = match->data; 1344d5a80031SBenoit Cousson 1345d5a80031SBenoit Cousson of_property_read_u32(node, "ti,spi-num-cs", &num_cs); 1346d5a80031SBenoit Cousson master->num_chipselect = num_cs; 1347d5a80031SBenoit Cousson master->bus_num = bus_num++; 13482cd45179SDaniel Mack if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL)) 13492cd45179SDaniel Mack mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN; 1350d5a80031SBenoit Cousson } else { 13518074cf06SJingoo Han pdata = dev_get_platdata(&pdev->dev); 1352ca632f55SGrant Likely master->num_chipselect = pdata->num_cs; 1353d5a80031SBenoit Cousson if (pdev->id != -1) 1354d5a80031SBenoit Cousson master->bus_num = pdev->id; 13550384e90bSDaniel Mack mcspi->pin_dir = pdata->pin_dir; 1356d5a80031SBenoit Cousson } 1357d5a80031SBenoit Cousson regs_offset = pdata->regs_offset; 1358ca632f55SGrant Likely 1359ca632f55SGrant Likely r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1360ca632f55SGrant Likely if (r == NULL) { 1361ca632f55SGrant Likely status = -ENODEV; 136239f1b565SShubhrajyoti D goto free_master; 1363ca632f55SGrant Likely } 13641458d160SShubhrajyoti D 1365d5a80031SBenoit Cousson r->start += regs_offset; 1366d5a80031SBenoit Cousson r->end += regs_offset; 13671458d160SShubhrajyoti D mcspi->phys = r->start; 1368ca632f55SGrant Likely 1369b0ee5605SThierry Reding mcspi->base = devm_ioremap_resource(&pdev->dev, r); 1370b0ee5605SThierry Reding if (IS_ERR(mcspi->base)) { 1371b0ee5605SThierry Reding status = PTR_ERR(mcspi->base); 13721a77b127SShubhrajyoti D goto free_master; 1373ca632f55SGrant Likely } 1374ca632f55SGrant Likely 1375ca632f55SGrant Likely mcspi->dev = &pdev->dev; 1376ca632f55SGrant Likely 13771bd897f8SBenoit Cousson INIT_LIST_HEAD(&mcspi->ctx.cs); 1378ca632f55SGrant Likely 1379a6f936dbSAxel Lin mcspi->dma_channels = devm_kcalloc(&pdev->dev, master->num_chipselect, 1380ca632f55SGrant Likely sizeof(struct omap2_mcspi_dma), 1381ca632f55SGrant Likely GFP_KERNEL); 1382a6f936dbSAxel Lin if (mcspi->dma_channels == NULL) { 1383a6f936dbSAxel Lin status = -ENOMEM; 13841a77b127SShubhrajyoti D goto free_master; 1385a6f936dbSAxel Lin } 1386ca632f55SGrant Likely 1387ca632f55SGrant Likely for (i = 0; i < master->num_chipselect; i++) { 138874f3aaadSMatt Porter char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name; 138974f3aaadSMatt Porter char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name; 1390ca632f55SGrant Likely struct resource *dma_res; 1391ca632f55SGrant Likely 139274f3aaadSMatt Porter sprintf(dma_rx_ch_name, "rx%d", i); 139374f3aaadSMatt Porter if (!pdev->dev.of_node) { 139474f3aaadSMatt Porter dma_res = 139574f3aaadSMatt Porter platform_get_resource_byname(pdev, 139674f3aaadSMatt Porter IORESOURCE_DMA, 139774f3aaadSMatt Porter dma_rx_ch_name); 1398ca632f55SGrant Likely if (!dma_res) { 139974f3aaadSMatt Porter dev_dbg(&pdev->dev, 140074f3aaadSMatt Porter "cannot get DMA RX channel\n"); 1401ca632f55SGrant Likely status = -ENODEV; 1402ca632f55SGrant Likely break; 1403ca632f55SGrant Likely } 1404ca632f55SGrant Likely 140574f3aaadSMatt Porter mcspi->dma_channels[i].dma_rx_sync_dev = 140674f3aaadSMatt Porter dma_res->start; 140774f3aaadSMatt Porter } 140874f3aaadSMatt Porter sprintf(dma_tx_ch_name, "tx%d", i); 140974f3aaadSMatt Porter if (!pdev->dev.of_node) { 141074f3aaadSMatt Porter dma_res = 141174f3aaadSMatt Porter platform_get_resource_byname(pdev, 141274f3aaadSMatt Porter IORESOURCE_DMA, 141374f3aaadSMatt Porter dma_tx_ch_name); 1414ca632f55SGrant Likely if (!dma_res) { 141574f3aaadSMatt Porter dev_dbg(&pdev->dev, 141674f3aaadSMatt Porter "cannot get DMA TX channel\n"); 1417ca632f55SGrant Likely status = -ENODEV; 1418ca632f55SGrant Likely break; 1419ca632f55SGrant Likely } 1420ca632f55SGrant Likely 142174f3aaadSMatt Porter mcspi->dma_channels[i].dma_tx_sync_dev = 142274f3aaadSMatt Porter dma_res->start; 142374f3aaadSMatt Porter } 1424ca632f55SGrant Likely } 1425ca632f55SGrant Likely 142639f1b565SShubhrajyoti D if (status < 0) 1427a6f936dbSAxel Lin goto free_master; 142839f1b565SShubhrajyoti D 142927b5284cSShubhrajyoti D pm_runtime_use_autosuspend(&pdev->dev); 143027b5284cSShubhrajyoti D pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); 1431ca632f55SGrant Likely pm_runtime_enable(&pdev->dev); 1432ca632f55SGrant Likely 1433142e07beSWei Yongjun status = omap2_mcspi_master_setup(mcspi); 1434142e07beSWei Yongjun if (status < 0) 143539f1b565SShubhrajyoti D goto disable_pm; 1436ca632f55SGrant Likely 1437b95e02b7SJingoo Han status = devm_spi_register_master(&pdev->dev, master); 1438ca632f55SGrant Likely if (status < 0) 143937a2d84aSShubhrajyoti D goto disable_pm; 1440ca632f55SGrant Likely 1441ca632f55SGrant Likely return status; 1442ca632f55SGrant Likely 144339f1b565SShubhrajyoti D disable_pm: 1444751c925cSShubhrajyoti D pm_runtime_disable(&pdev->dev); 144539f1b565SShubhrajyoti D free_master: 144637a2d84aSShubhrajyoti D spi_master_put(master); 1447ca632f55SGrant Likely return status; 1448ca632f55SGrant Likely } 1449ca632f55SGrant Likely 1450fd4a319bSGrant Likely static int omap2_mcspi_remove(struct platform_device *pdev) 1451ca632f55SGrant Likely { 1452a6f936dbSAxel Lin struct spi_master *master = platform_get_drvdata(pdev); 1453a6f936dbSAxel Lin struct omap2_mcspi *mcspi = spi_master_get_devdata(master); 1454ca632f55SGrant Likely 1455a93a2029SShubhrajyoti D pm_runtime_put_sync(mcspi->dev); 1456751c925cSShubhrajyoti D pm_runtime_disable(&pdev->dev); 1457ca632f55SGrant Likely 1458ca632f55SGrant Likely return 0; 1459ca632f55SGrant Likely } 1460ca632f55SGrant Likely 1461ca632f55SGrant Likely /* work with hotplug and coldplug */ 1462ca632f55SGrant Likely MODULE_ALIAS("platform:omap2_mcspi"); 1463ca632f55SGrant Likely 1464ca632f55SGrant Likely #ifdef CONFIG_SUSPEND 1465ca632f55SGrant Likely /* 1466ca632f55SGrant Likely * When SPI wake up from off-mode, CS is in activate state. If it was in 1467ca632f55SGrant Likely * unactive state when driver was suspend, then force it to unactive state at 1468ca632f55SGrant Likely * wake up. 1469ca632f55SGrant Likely */ 1470ca632f55SGrant Likely static int omap2_mcspi_resume(struct device *dev) 1471ca632f55SGrant Likely { 1472ca632f55SGrant Likely struct spi_master *master = dev_get_drvdata(dev); 1473ca632f55SGrant Likely struct omap2_mcspi *mcspi = spi_master_get_devdata(master); 14741bd897f8SBenoit Cousson struct omap2_mcspi_regs *ctx = &mcspi->ctx; 1475ca632f55SGrant Likely struct omap2_mcspi_cs *cs; 1476ca632f55SGrant Likely 1477034d3dc9SShubhrajyoti D pm_runtime_get_sync(mcspi->dev); 14781bd897f8SBenoit Cousson list_for_each_entry(cs, &ctx->cs, node) { 1479ca632f55SGrant Likely if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { 1480ca632f55SGrant Likely /* 1481ca632f55SGrant Likely * We need to toggle CS state for OMAP take this 1482ca632f55SGrant Likely * change in account. 1483ca632f55SGrant Likely */ 1484af4e944dSShubhrajyoti D cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; 148521b2ce5eSVictor Kamensky writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); 1486af4e944dSShubhrajyoti D cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE; 148721b2ce5eSVictor Kamensky writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); 1488ca632f55SGrant Likely } 1489ca632f55SGrant Likely } 1490034d3dc9SShubhrajyoti D pm_runtime_mark_last_busy(mcspi->dev); 1491034d3dc9SShubhrajyoti D pm_runtime_put_autosuspend(mcspi->dev); 1492ca632f55SGrant Likely return 0; 1493ca632f55SGrant Likely } 1494ca632f55SGrant Likely #else 1495ca632f55SGrant Likely #define omap2_mcspi_resume NULL 1496ca632f55SGrant Likely #endif 1497ca632f55SGrant Likely 1498ca632f55SGrant Likely static const struct dev_pm_ops omap2_mcspi_pm_ops = { 1499ca632f55SGrant Likely .resume = omap2_mcspi_resume, 1500ca632f55SGrant Likely .runtime_resume = omap_mcspi_runtime_resume, 1501ca632f55SGrant Likely }; 1502ca632f55SGrant Likely 1503ca632f55SGrant Likely static struct platform_driver omap2_mcspi_driver = { 1504ca632f55SGrant Likely .driver = { 1505ca632f55SGrant Likely .name = "omap2_mcspi", 1506d5a80031SBenoit Cousson .pm = &omap2_mcspi_pm_ops, 1507d5a80031SBenoit Cousson .of_match_table = omap_mcspi_of_match, 1508ca632f55SGrant Likely }, 15097d6b6d83SFelipe Balbi .probe = omap2_mcspi_probe, 1510fd4a319bSGrant Likely .remove = omap2_mcspi_remove, 1511ca632f55SGrant Likely }; 1512ca632f55SGrant Likely 15139fdca9dfSFelipe Balbi module_platform_driver(omap2_mcspi_driver); 1514ca632f55SGrant Likely MODULE_LICENSE("GPL"); 1515