omap3_spi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
  3. *
  4. * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
  5. * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
  6. *
  7. * Copyright (C) 2007 Atmel Corporation
  8. *
  9. * Parts taken from linux/drivers/spi/omap2_mcspi.c
  10. * Copyright (C) 2005, 2006 Nokia Corporation
  11. *
  12. * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
  13. *
  14. * SPDX-License-Identifier: GPL-2.0+
  15. */
  16. #include <common.h>
  17. #include <spi.h>
  18. #include <malloc.h>
  19. #include <asm/io.h>
  20. #include "omap3_spi.h"
  21. #define WORD_LEN 8
  22. #define SPI_WAIT_TIMEOUT 3000000;
  23. static void spi_reset(struct omap3_spi_slave *ds)
  24. {
  25. unsigned int tmp;
  26. writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig);
  27. do {
  28. tmp = readl(&ds->regs->sysstatus);
  29. } while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
  30. writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
  31. OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
  32. OMAP3_MCSPI_SYSCONFIG_SMARTIDLE,
  33. &ds->regs->sysconfig);
  34. writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
  35. }
  36. static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val)
  37. {
  38. writel(val, &ds->regs->channel[ds->slave.cs].chconf);
  39. /* Flash post writes to make immediate effect */
  40. readl(&ds->regs->channel[ds->slave.cs].chconf);
  41. }
  42. static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable)
  43. {
  44. writel(enable, &ds->regs->channel[ds->slave.cs].chctrl);
  45. /* Flash post writes to make immediate effect */
  46. readl(&ds->regs->channel[ds->slave.cs].chctrl);
  47. }
  48. void spi_init()
  49. {
  50. /* do nothing */
  51. }
  52. struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  53. unsigned int max_hz, unsigned int mode)
  54. {
  55. struct omap3_spi_slave *ds;
  56. struct mcspi *regs;
  57. /*
  58. * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
  59. * with different number of chip selects (CS, channels):
  60. * McSPI1 has 4 CS (bus 0, cs 0 - 3)
  61. * McSPI2 has 2 CS (bus 1, cs 0 - 1)
  62. * McSPI3 has 2 CS (bus 2, cs 0 - 1)
  63. * McSPI4 has 1 CS (bus 3, cs 0)
  64. */
  65. switch (bus) {
  66. case 0:
  67. regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
  68. break;
  69. #ifdef OMAP3_MCSPI2_BASE
  70. case 1:
  71. regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
  72. break;
  73. #endif
  74. #ifdef OMAP3_MCSPI3_BASE
  75. case 2:
  76. regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
  77. break;
  78. #endif
  79. #ifdef OMAP3_MCSPI4_BASE
  80. case 3:
  81. regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
  82. break;
  83. #endif
  84. default:
  85. printf("SPI error: unsupported bus %i. \
  86. Supported busses 0 - 3\n", bus);
  87. return NULL;
  88. }
  89. if (((bus == 0) && (cs > 3)) ||
  90. ((bus == 1) && (cs > 1)) ||
  91. ((bus == 2) && (cs > 1)) ||
  92. ((bus == 3) && (cs > 0))) {
  93. printf("SPI error: unsupported chip select %i \
  94. on bus %i\n", cs, bus);
  95. return NULL;
  96. }
  97. if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
  98. printf("SPI error: unsupported frequency %i Hz. \
  99. Max frequency is 48 Mhz\n", max_hz);
  100. return NULL;
  101. }
  102. if (mode > SPI_MODE_3) {
  103. printf("SPI error: unsupported SPI mode %i\n", mode);
  104. return NULL;
  105. }
  106. ds = spi_alloc_slave(struct omap3_spi_slave, bus, cs);
  107. if (!ds) {
  108. printf("SPI error: malloc of SPI structure failed\n");
  109. return NULL;
  110. }
  111. ds->regs = regs;
  112. ds->freq = max_hz;
  113. ds->mode = mode;
  114. return &ds->slave;
  115. }
  116. void spi_free_slave(struct spi_slave *slave)
  117. {
  118. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  119. free(ds);
  120. }
  121. int spi_claim_bus(struct spi_slave *slave)
  122. {
  123. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  124. unsigned int conf, div = 0;
  125. /* McSPI global module configuration */
  126. /*
  127. * setup when switching from (reset default) slave mode
  128. * to single-channel master mode
  129. */
  130. spi_reset(ds);
  131. conf = readl(&ds->regs->modulctrl);
  132. conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
  133. conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
  134. writel(conf, &ds->regs->modulctrl);
  135. /* McSPI individual channel configuration */
  136. /* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
  137. if (ds->freq) {
  138. while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
  139. > ds->freq)
  140. div++;
  141. } else
  142. div = 0xC;
  143. conf = readl(&ds->regs->channel[ds->slave.cs].chconf);
  144. /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
  145. * REVISIT: this controller could support SPI_3WIRE mode.
  146. */
  147. #ifdef CONFIG_OMAP3_SPI_D0_D1_SWAPPED
  148. /*
  149. * Some boards have D0 wired as MOSI / D1 as MISO instead of
  150. * The normal D0 as MISO / D1 as MOSI.
  151. */
  152. conf &= ~OMAP3_MCSPI_CHCONF_DPE0;
  153. conf |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1;
  154. #else
  155. conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
  156. conf |= OMAP3_MCSPI_CHCONF_DPE0;
  157. #endif
  158. /* wordlength */
  159. conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
  160. conf |= (WORD_LEN - 1) << 7;
  161. /* set chipselect polarity; manage with FORCE */
  162. if (!(ds->mode & SPI_CS_HIGH))
  163. conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
  164. else
  165. conf &= ~OMAP3_MCSPI_CHCONF_EPOL;
  166. /* set clock divisor */
  167. conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
  168. conf |= div << 2;
  169. /* set SPI mode 0..3 */
  170. if (ds->mode & SPI_CPOL)
  171. conf |= OMAP3_MCSPI_CHCONF_POL;
  172. else
  173. conf &= ~OMAP3_MCSPI_CHCONF_POL;
  174. if (ds->mode & SPI_CPHA)
  175. conf |= OMAP3_MCSPI_CHCONF_PHA;
  176. else
  177. conf &= ~OMAP3_MCSPI_CHCONF_PHA;
  178. /* Transmit & receive mode */
  179. conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
  180. omap3_spi_write_chconf(ds,conf);
  181. return 0;
  182. }
  183. void spi_release_bus(struct spi_slave *slave)
  184. {
  185. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  186. /* Reset the SPI hardware */
  187. spi_reset(ds);
  188. }
  189. int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp,
  190. unsigned long flags)
  191. {
  192. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  193. int i;
  194. int timeout = SPI_WAIT_TIMEOUT;
  195. int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
  196. /* Enable the channel */
  197. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
  198. chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
  199. chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
  200. chconf |= OMAP3_MCSPI_CHCONF_FORCE;
  201. omap3_spi_write_chconf(ds,chconf);
  202. for (i = 0; i < len; i++) {
  203. /* wait till TX register is empty (TXS == 1) */
  204. while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
  205. OMAP3_MCSPI_CHSTAT_TXS)) {
  206. if (--timeout <= 0) {
  207. printf("SPI TXS timed out, status=0x%08x\n",
  208. readl(&ds->regs->channel[ds->slave.cs].chstat));
  209. return -1;
  210. }
  211. }
  212. /* Write the data */
  213. writel(txp[i], &ds->regs->channel[ds->slave.cs].tx);
  214. }
  215. /* wait to finish of transfer */
  216. while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
  217. OMAP3_MCSPI_CHSTAT_EOT));
  218. /* Disable the channel otherwise the next immediate RX will get affected */
  219. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
  220. if (flags & SPI_XFER_END) {
  221. chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
  222. omap3_spi_write_chconf(ds,chconf);
  223. }
  224. return 0;
  225. }
  226. int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp,
  227. unsigned long flags)
  228. {
  229. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  230. int i;
  231. int timeout = SPI_WAIT_TIMEOUT;
  232. int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
  233. /* Enable the channel */
  234. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
  235. chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
  236. chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
  237. chconf |= OMAP3_MCSPI_CHCONF_FORCE;
  238. omap3_spi_write_chconf(ds,chconf);
  239. writel(0, &ds->regs->channel[ds->slave.cs].tx);
  240. for (i = 0; i < len; i++) {
  241. /* Wait till RX register contains data (RXS == 1) */
  242. while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
  243. OMAP3_MCSPI_CHSTAT_RXS)) {
  244. if (--timeout <= 0) {
  245. printf("SPI RXS timed out, status=0x%08x\n",
  246. readl(&ds->regs->channel[ds->slave.cs].chstat));
  247. return -1;
  248. }
  249. }
  250. /* Disable the channel to prevent furher receiving */
  251. if(i == (len - 1))
  252. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
  253. /* Read the data */
  254. rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
  255. }
  256. if (flags & SPI_XFER_END) {
  257. chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
  258. omap3_spi_write_chconf(ds,chconf);
  259. }
  260. return 0;
  261. }
  262. /*McSPI Transmit Receive Mode*/
  263. int omap3_spi_txrx(struct spi_slave *slave,
  264. unsigned int len, const u8 *txp, u8 *rxp, unsigned long flags)
  265. {
  266. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  267. int timeout = SPI_WAIT_TIMEOUT;
  268. int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
  269. int irqstatus = readl(&ds->regs->irqstatus);
  270. int i=0;
  271. /*Enable SPI channel*/
  272. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
  273. /*set TRANSMIT-RECEIVE Mode*/
  274. chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
  275. chconf |= OMAP3_MCSPI_CHCONF_FORCE;
  276. omap3_spi_write_chconf(ds,chconf);
  277. /*Shift in and out 1 byte at time*/
  278. for (i=0; i < len; i++){
  279. /* Write: wait for TX empty (TXS == 1)*/
  280. irqstatus |= (1<< (4*(ds->slave.bus)));
  281. while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
  282. OMAP3_MCSPI_CHSTAT_TXS)) {
  283. if (--timeout <= 0) {
  284. printf("SPI TXS timed out, status=0x%08x\n",
  285. readl(&ds->regs->channel[ds->slave.cs].chstat));
  286. return -1;
  287. }
  288. }
  289. /* Write the data */
  290. writel(txp[i], &ds->regs->channel[ds->slave.cs].tx);
  291. /*Read: wait for RX containing data (RXS == 1)*/
  292. while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
  293. OMAP3_MCSPI_CHSTAT_RXS)) {
  294. if (--timeout <= 0) {
  295. printf("SPI RXS timed out, status=0x%08x\n",
  296. readl(&ds->regs->channel[ds->slave.cs].chstat));
  297. return -1;
  298. }
  299. }
  300. /* Read the data */
  301. rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
  302. }
  303. /* Disable the channel */
  304. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
  305. /*if transfer must be terminated disable the channel*/
  306. if (flags & SPI_XFER_END) {
  307. chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
  308. omap3_spi_write_chconf(ds,chconf);
  309. }
  310. return 0;
  311. }
  312. int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  313. const void *dout, void *din, unsigned long flags)
  314. {
  315. struct omap3_spi_slave *ds = to_omap3_spi(slave);
  316. unsigned int len;
  317. const u8 *txp = dout;
  318. u8 *rxp = din;
  319. int ret = -1;
  320. if (bitlen % 8)
  321. return -1;
  322. len = bitlen / 8;
  323. if (bitlen == 0) { /* only change CS */
  324. int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
  325. if (flags & SPI_XFER_BEGIN) {
  326. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
  327. chconf |= OMAP3_MCSPI_CHCONF_FORCE;
  328. omap3_spi_write_chconf(ds,chconf);
  329. }
  330. if (flags & SPI_XFER_END) {
  331. chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
  332. omap3_spi_write_chconf(ds,chconf);
  333. omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
  334. }
  335. ret = 0;
  336. } else {
  337. if (dout != NULL && din != NULL)
  338. ret = omap3_spi_txrx(slave, len, txp, rxp, flags);
  339. else if (dout != NULL)
  340. ret = omap3_spi_write(slave, len, txp, flags);
  341. else if (din != NULL)
  342. ret = omap3_spi_read(slave, len, rxp, flags);
  343. }
  344. return ret;
  345. }
  346. int spi_cs_is_valid(unsigned int bus, unsigned int cs)
  347. {
  348. return 1;
  349. }
  350. void spi_cs_activate(struct spi_slave *slave)
  351. {
  352. }
  353. void spi_cs_deactivate(struct spi_slave *slave)
  354. {
  355. }