spi-nuc900.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * Copyright (c) 2009 Nuvoton technology.
  3. * Wan ZongShun <mcuos.com@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. */
  10. #include <linux/module.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/workqueue.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/delay.h>
  15. #include <linux/errno.h>
  16. #include <linux/err.h>
  17. #include <linux/clk.h>
  18. #include <linux/device.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/gpio.h>
  21. #include <linux/io.h>
  22. #include <linux/slab.h>
  23. #include <linux/spi/spi.h>
  24. #include <linux/spi/spi_bitbang.h>
  25. #include <linux/platform_data/spi-nuc900.h>
  26. /* usi registers offset */
  27. #define USI_CNT 0x00
  28. #define USI_DIV 0x04
  29. #define USI_SSR 0x08
  30. #define USI_RX0 0x10
  31. #define USI_TX0 0x10
  32. /* usi register bit */
  33. #define ENINT (0x01 << 17)
  34. #define ENFLG (0x01 << 16)
  35. #define SLEEP (0x0f << 12)
  36. #define TXNUM (0x03 << 8)
  37. #define TXBITLEN (0x1f << 3)
  38. #define TXNEG (0x01 << 2)
  39. #define RXNEG (0x01 << 1)
  40. #define LSB (0x01 << 10)
  41. #define SELECTLEV (0x01 << 2)
  42. #define SELECTPOL (0x01 << 31)
  43. #define SELECTSLAVE 0x01
  44. #define GOBUSY 0x01
  45. struct nuc900_spi {
  46. struct spi_bitbang bitbang;
  47. struct completion done;
  48. void __iomem *regs;
  49. int irq;
  50. int len;
  51. int count;
  52. const unsigned char *tx;
  53. unsigned char *rx;
  54. struct clk *clk;
  55. struct spi_master *master;
  56. struct nuc900_spi_info *pdata;
  57. spinlock_t lock;
  58. };
  59. static inline struct nuc900_spi *to_hw(struct spi_device *sdev)
  60. {
  61. return spi_master_get_devdata(sdev->master);
  62. }
  63. static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr)
  64. {
  65. struct nuc900_spi *hw = to_hw(spi);
  66. unsigned int val;
  67. unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
  68. unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0;
  69. unsigned long flags;
  70. spin_lock_irqsave(&hw->lock, flags);
  71. val = __raw_readl(hw->regs + USI_SSR);
  72. if (!cs)
  73. val &= ~SELECTLEV;
  74. else
  75. val |= SELECTLEV;
  76. if (!ssr)
  77. val &= ~SELECTSLAVE;
  78. else
  79. val |= SELECTSLAVE;
  80. __raw_writel(val, hw->regs + USI_SSR);
  81. val = __raw_readl(hw->regs + USI_CNT);
  82. if (!cpol)
  83. val &= ~SELECTPOL;
  84. else
  85. val |= SELECTPOL;
  86. __raw_writel(val, hw->regs + USI_CNT);
  87. spin_unlock_irqrestore(&hw->lock, flags);
  88. }
  89. static void nuc900_spi_chipsel(struct spi_device *spi, int value)
  90. {
  91. switch (value) {
  92. case BITBANG_CS_INACTIVE:
  93. nuc900_slave_select(spi, 0);
  94. break;
  95. case BITBANG_CS_ACTIVE:
  96. nuc900_slave_select(spi, 1);
  97. break;
  98. }
  99. }
  100. static void nuc900_spi_setup_txnum(struct nuc900_spi *hw, unsigned int txnum)
  101. {
  102. unsigned int val;
  103. unsigned long flags;
  104. spin_lock_irqsave(&hw->lock, flags);
  105. val = __raw_readl(hw->regs + USI_CNT) & ~TXNUM;
  106. if (txnum)
  107. val |= txnum << 0x08;
  108. __raw_writel(val, hw->regs + USI_CNT);
  109. spin_unlock_irqrestore(&hw->lock, flags);
  110. }
  111. static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw,
  112. unsigned int txbitlen)
  113. {
  114. unsigned int val;
  115. unsigned long flags;
  116. spin_lock_irqsave(&hw->lock, flags);
  117. val = __raw_readl(hw->regs + USI_CNT) & ~TXBITLEN;
  118. val |= (txbitlen << 0x03);
  119. __raw_writel(val, hw->regs + USI_CNT);
  120. spin_unlock_irqrestore(&hw->lock, flags);
  121. }
  122. static void nuc900_spi_gobusy(struct nuc900_spi *hw)
  123. {
  124. unsigned int val;
  125. unsigned long flags;
  126. spin_lock_irqsave(&hw->lock, flags);
  127. val = __raw_readl(hw->regs + USI_CNT);
  128. val |= GOBUSY;
  129. __raw_writel(val, hw->regs + USI_CNT);
  130. spin_unlock_irqrestore(&hw->lock, flags);
  131. }
  132. static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
  133. {
  134. return hw->tx ? hw->tx[count] : 0;
  135. }
  136. static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
  137. {
  138. struct nuc900_spi *hw = to_hw(spi);
  139. hw->tx = t->tx_buf;
  140. hw->rx = t->rx_buf;
  141. hw->len = t->len;
  142. hw->count = 0;
  143. __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0);
  144. nuc900_spi_gobusy(hw);
  145. wait_for_completion(&hw->done);
  146. return hw->count;
  147. }
  148. static irqreturn_t nuc900_spi_irq(int irq, void *dev)
  149. {
  150. struct nuc900_spi *hw = dev;
  151. unsigned int status;
  152. unsigned int count = hw->count;
  153. status = __raw_readl(hw->regs + USI_CNT);
  154. __raw_writel(status, hw->regs + USI_CNT);
  155. if (status & ENFLG) {
  156. hw->count++;
  157. if (hw->rx)
  158. hw->rx[count] = __raw_readl(hw->regs + USI_RX0);
  159. count++;
  160. if (count < hw->len) {
  161. __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0);
  162. nuc900_spi_gobusy(hw);
  163. } else {
  164. complete(&hw->done);
  165. }
  166. return IRQ_HANDLED;
  167. }
  168. complete(&hw->done);
  169. return IRQ_HANDLED;
  170. }
  171. static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge)
  172. {
  173. unsigned int val;
  174. unsigned long flags;
  175. spin_lock_irqsave(&hw->lock, flags);
  176. val = __raw_readl(hw->regs + USI_CNT);
  177. if (edge)
  178. val |= TXNEG;
  179. else
  180. val &= ~TXNEG;
  181. __raw_writel(val, hw->regs + USI_CNT);
  182. spin_unlock_irqrestore(&hw->lock, flags);
  183. }
  184. static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge)
  185. {
  186. unsigned int val;
  187. unsigned long flags;
  188. spin_lock_irqsave(&hw->lock, flags);
  189. val = __raw_readl(hw->regs + USI_CNT);
  190. if (edge)
  191. val |= RXNEG;
  192. else
  193. val &= ~RXNEG;
  194. __raw_writel(val, hw->regs + USI_CNT);
  195. spin_unlock_irqrestore(&hw->lock, flags);
  196. }
  197. static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb)
  198. {
  199. unsigned int val;
  200. unsigned long flags;
  201. spin_lock_irqsave(&hw->lock, flags);
  202. val = __raw_readl(hw->regs + USI_CNT);
  203. if (lsb)
  204. val |= LSB;
  205. else
  206. val &= ~LSB;
  207. __raw_writel(val, hw->regs + USI_CNT);
  208. spin_unlock_irqrestore(&hw->lock, flags);
  209. }
  210. static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep)
  211. {
  212. unsigned int val;
  213. unsigned long flags;
  214. spin_lock_irqsave(&hw->lock, flags);
  215. val = __raw_readl(hw->regs + USI_CNT) & ~SLEEP;
  216. if (sleep)
  217. val |= (sleep << 12);
  218. __raw_writel(val, hw->regs + USI_CNT);
  219. spin_unlock_irqrestore(&hw->lock, flags);
  220. }
  221. static void nuc900_enable_int(struct nuc900_spi *hw)
  222. {
  223. unsigned int val;
  224. unsigned long flags;
  225. spin_lock_irqsave(&hw->lock, flags);
  226. val = __raw_readl(hw->regs + USI_CNT);
  227. val |= ENINT;
  228. __raw_writel(val, hw->regs + USI_CNT);
  229. spin_unlock_irqrestore(&hw->lock, flags);
  230. }
  231. static void nuc900_set_divider(struct nuc900_spi *hw)
  232. {
  233. __raw_writel(hw->pdata->divider, hw->regs + USI_DIV);
  234. }
  235. static void nuc900_init_spi(struct nuc900_spi *hw)
  236. {
  237. clk_enable(hw->clk);
  238. spin_lock_init(&hw->lock);
  239. nuc900_tx_edge(hw, hw->pdata->txneg);
  240. nuc900_rx_edge(hw, hw->pdata->rxneg);
  241. nuc900_send_first(hw, hw->pdata->lsb);
  242. nuc900_set_sleep(hw, hw->pdata->sleep);
  243. nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen);
  244. nuc900_spi_setup_txnum(hw, hw->pdata->txnum);
  245. nuc900_set_divider(hw);
  246. nuc900_enable_int(hw);
  247. }
  248. static int nuc900_spi_probe(struct platform_device *pdev)
  249. {
  250. struct nuc900_spi *hw;
  251. struct spi_master *master;
  252. struct resource *res;
  253. int err = 0;
  254. master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
  255. if (master == NULL) {
  256. dev_err(&pdev->dev, "No memory for spi_master\n");
  257. return -ENOMEM;
  258. }
  259. hw = spi_master_get_devdata(master);
  260. hw->master = master;
  261. hw->pdata = dev_get_platdata(&pdev->dev);
  262. if (hw->pdata == NULL) {
  263. dev_err(&pdev->dev, "No platform data supplied\n");
  264. err = -ENOENT;
  265. goto err_pdata;
  266. }
  267. platform_set_drvdata(pdev, hw);
  268. init_completion(&hw->done);
  269. master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
  270. if (hw->pdata->lsb)
  271. master->mode_bits |= SPI_LSB_FIRST;
  272. master->num_chipselect = hw->pdata->num_cs;
  273. master->bus_num = hw->pdata->bus_num;
  274. hw->bitbang.master = hw->master;
  275. hw->bitbang.chipselect = nuc900_spi_chipsel;
  276. hw->bitbang.txrx_bufs = nuc900_spi_txrx;
  277. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  278. hw->regs = devm_ioremap_resource(&pdev->dev, res);
  279. if (IS_ERR(hw->regs)) {
  280. err = PTR_ERR(hw->regs);
  281. goto err_pdata;
  282. }
  283. hw->irq = platform_get_irq(pdev, 0);
  284. if (hw->irq < 0) {
  285. dev_err(&pdev->dev, "No IRQ specified\n");
  286. err = -ENOENT;
  287. goto err_pdata;
  288. }
  289. err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0,
  290. pdev->name, hw);
  291. if (err) {
  292. dev_err(&pdev->dev, "Cannot claim IRQ\n");
  293. goto err_pdata;
  294. }
  295. hw->clk = devm_clk_get(&pdev->dev, "spi");
  296. if (IS_ERR(hw->clk)) {
  297. dev_err(&pdev->dev, "No clock for device\n");
  298. err = PTR_ERR(hw->clk);
  299. goto err_pdata;
  300. }
  301. mfp_set_groupg(&pdev->dev, NULL);
  302. nuc900_init_spi(hw);
  303. err = spi_bitbang_start(&hw->bitbang);
  304. if (err) {
  305. dev_err(&pdev->dev, "Failed to register SPI master\n");
  306. goto err_register;
  307. }
  308. return 0;
  309. err_register:
  310. clk_disable(hw->clk);
  311. err_pdata:
  312. spi_master_put(hw->master);
  313. return err;
  314. }
  315. static int nuc900_spi_remove(struct platform_device *dev)
  316. {
  317. struct nuc900_spi *hw = platform_get_drvdata(dev);
  318. spi_bitbang_stop(&hw->bitbang);
  319. clk_disable(hw->clk);
  320. spi_master_put(hw->master);
  321. return 0;
  322. }
  323. static struct platform_driver nuc900_spi_driver = {
  324. .probe = nuc900_spi_probe,
  325. .remove = nuc900_spi_remove,
  326. .driver = {
  327. .name = "nuc900-spi",
  328. .owner = THIS_MODULE,
  329. },
  330. };
  331. module_platform_driver(nuc900_spi_driver);
  332. MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
  333. MODULE_DESCRIPTION("nuc900 spi driver!");
  334. MODULE_LICENSE("GPL");
  335. MODULE_ALIAS("platform:nuc900-spi");