sead3-pic32-i2c-drv.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
  7. */
  8. #include <linux/delay.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/init.h>
  14. #include <linux/errno.h>
  15. #include <linux/i2c.h>
  16. #include <linux/slab.h>
  17. #define PIC32_I2CxCON 0x0000
  18. #define PIC32_I2CxCONCLR 0x0004
  19. #define PIC32_I2CxCONSET 0x0008
  20. #define PIC32_I2CxCONINV 0x000C
  21. #define I2CCON_ON (1<<15)
  22. #define I2CCON_FRZ (1<<14)
  23. #define I2CCON_SIDL (1<<13)
  24. #define I2CCON_SCLREL (1<<12)
  25. #define I2CCON_STRICT (1<<11)
  26. #define I2CCON_A10M (1<<10)
  27. #define I2CCON_DISSLW (1<<9)
  28. #define I2CCON_SMEN (1<<8)
  29. #define I2CCON_GCEN (1<<7)
  30. #define I2CCON_STREN (1<<6)
  31. #define I2CCON_ACKDT (1<<5)
  32. #define I2CCON_ACKEN (1<<4)
  33. #define I2CCON_RCEN (1<<3)
  34. #define I2CCON_PEN (1<<2)
  35. #define I2CCON_RSEN (1<<1)
  36. #define I2CCON_SEN (1<<0)
  37. #define PIC32_I2CxSTAT 0x0010
  38. #define PIC32_I2CxSTATCLR 0x0014
  39. #define PIC32_I2CxSTATSET 0x0018
  40. #define PIC32_I2CxSTATINV 0x001C
  41. #define I2CSTAT_ACKSTAT (1<<15)
  42. #define I2CSTAT_TRSTAT (1<<14)
  43. #define I2CSTAT_BCL (1<<10)
  44. #define I2CSTAT_GCSTAT (1<<9)
  45. #define I2CSTAT_ADD10 (1<<8)
  46. #define I2CSTAT_IWCOL (1<<7)
  47. #define I2CSTAT_I2COV (1<<6)
  48. #define I2CSTAT_DA (1<<5)
  49. #define I2CSTAT_P (1<<4)
  50. #define I2CSTAT_S (1<<3)
  51. #define I2CSTAT_RW (1<<2)
  52. #define I2CSTAT_RBF (1<<1)
  53. #define I2CSTAT_TBF (1<<0)
  54. #define PIC32_I2CxADD 0x0020
  55. #define PIC32_I2CxADDCLR 0x0024
  56. #define PIC32_I2CxADDSET 0x0028
  57. #define PIC32_I2CxADDINV 0x002C
  58. #define PIC32_I2CxMSK 0x0030
  59. #define PIC32_I2CxMSKCLR 0x0034
  60. #define PIC32_I2CxMSKSET 0x0038
  61. #define PIC32_I2CxMSKINV 0x003C
  62. #define PIC32_I2CxBRG 0x0040
  63. #define PIC32_I2CxBRGCLR 0x0044
  64. #define PIC32_I2CxBRGSET 0x0048
  65. #define PIC32_I2CxBRGINV 0x004C
  66. #define PIC32_I2CxTRN 0x0050
  67. #define PIC32_I2CxTRNCLR 0x0054
  68. #define PIC32_I2CxTRNSET 0x0058
  69. #define PIC32_I2CxTRNINV 0x005C
  70. #define PIC32_I2CxRCV 0x0060
  71. struct i2c_platform_data {
  72. u32 base;
  73. struct i2c_adapter adap;
  74. u32 xfer_timeout;
  75. u32 ack_timeout;
  76. u32 ctl_timeout;
  77. };
  78. extern u32 pic32_bus_readl(u32 reg);
  79. extern void pic32_bus_writel(u32 val, u32 reg);
  80. static inline void
  81. StartI2C(struct i2c_platform_data *adap)
  82. {
  83. pr_debug("StartI2C\n");
  84. pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
  85. }
  86. static inline void
  87. StopI2C(struct i2c_platform_data *adap)
  88. {
  89. pr_debug("StopI2C\n");
  90. pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
  91. }
  92. static inline void
  93. AckI2C(struct i2c_platform_data *adap)
  94. {
  95. pr_debug("AckI2C\n");
  96. pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
  97. pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
  98. }
  99. static inline void
  100. NotAckI2C(struct i2c_platform_data *adap)
  101. {
  102. pr_debug("NakI2C\n");
  103. pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
  104. pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
  105. }
  106. static inline int
  107. IdleI2C(struct i2c_platform_data *adap)
  108. {
  109. int i;
  110. pr_debug("IdleI2C\n");
  111. for (i = 0; i < adap->ctl_timeout; i++) {
  112. if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
  113. (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN |
  114. I2CCON_SEN)) == 0) &&
  115. ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
  116. (I2CSTAT_TRSTAT)) == 0))
  117. return 0;
  118. udelay(1);
  119. }
  120. return -ETIMEDOUT;
  121. }
  122. static inline u32
  123. MasterWriteI2C(struct i2c_platform_data *adap, u32 byte)
  124. {
  125. pr_debug("MasterWriteI2C\n");
  126. pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
  127. return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL;
  128. }
  129. static inline u32
  130. MasterReadI2C(struct i2c_platform_data *adap)
  131. {
  132. pr_debug("MasterReadI2C\n");
  133. pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
  134. while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN)
  135. ;
  136. pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
  137. return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
  138. }
  139. static int
  140. do_address(struct i2c_platform_data *adap, unsigned int addr, int rd)
  141. {
  142. pr_debug("doaddress\n");
  143. IdleI2C(adap);
  144. StartI2C(adap);
  145. IdleI2C(adap);
  146. addr <<= 1;
  147. if (rd)
  148. addr |= 1;
  149. if (MasterWriteI2C(adap, addr))
  150. return -EIO;
  151. IdleI2C(adap);
  152. if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT)
  153. return -EIO;
  154. return 0;
  155. }
  156. static int
  157. i2c_read(struct i2c_platform_data *adap, unsigned char *buf,
  158. unsigned int len)
  159. {
  160. int i;
  161. u32 data;
  162. pr_debug("i2c_read\n");
  163. i = 0;
  164. while (i < len) {
  165. data = MasterReadI2C(adap);
  166. buf[i++] = data;
  167. if (i < len)
  168. AckI2C(adap);
  169. else
  170. NotAckI2C(adap);
  171. }
  172. StopI2C(adap);
  173. IdleI2C(adap);
  174. return 0;
  175. }
  176. static int
  177. i2c_write(struct i2c_platform_data *adap, unsigned char *buf,
  178. unsigned int len)
  179. {
  180. int i;
  181. u32 data;
  182. pr_debug("i2c_write\n");
  183. i = 0;
  184. while (i < len) {
  185. data = buf[i];
  186. if (MasterWriteI2C(adap, data))
  187. return -EIO;
  188. IdleI2C(adap);
  189. if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
  190. I2CSTAT_ACKSTAT)
  191. return -EIO;
  192. i++;
  193. }
  194. StopI2C(adap);
  195. IdleI2C(adap);
  196. return 0;
  197. }
  198. static int
  199. platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
  200. {
  201. struct i2c_platform_data *adap = i2c_adap->algo_data;
  202. struct i2c_msg *p;
  203. int i, err = 0;
  204. pr_debug("platform_xfer\n");
  205. for (i = 0; i < num; i++) {
  206. #define __BUFSIZE 80
  207. int ii;
  208. static char buf[__BUFSIZE];
  209. char *b = buf;
  210. p = &msgs[i];
  211. b += sprintf(buf, " [%d bytes]", p->len);
  212. if ((p->flags & I2C_M_RD) == 0) {
  213. for (ii = 0; ii < p->len; ii++) {
  214. if (b < &buf[__BUFSIZE-4]) {
  215. b += sprintf(b, " %02x", p->buf[ii]);
  216. } else {
  217. strcat(b, "...");
  218. break;
  219. }
  220. }
  221. }
  222. pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr,
  223. (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf);
  224. }
  225. for (i = 0; !err && i < num; i++) {
  226. p = &msgs[i];
  227. err = do_address(adap, p->addr, p->flags & I2C_M_RD);
  228. if (err || !p->len)
  229. continue;
  230. if (p->flags & I2C_M_RD)
  231. err = i2c_read(adap, p->buf, p->len);
  232. else
  233. err = i2c_write(adap, p->buf, p->len);
  234. }
  235. /* Return the number of messages processed, or the error code. */
  236. if (err == 0)
  237. err = num;
  238. return err;
  239. }
  240. static u32
  241. platform_func(struct i2c_adapter *adap)
  242. {
  243. pr_debug("platform_algo\n");
  244. return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
  245. }
  246. static const struct i2c_algorithm platform_algo = {
  247. .master_xfer = platform_xfer,
  248. .functionality = platform_func,
  249. };
  250. static void i2c_platform_setup(struct i2c_platform_data *priv)
  251. {
  252. pr_debug("i2c_platform_setup\n");
  253. pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
  254. pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
  255. pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET);
  256. pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL),
  257. (priv->base + PIC32_I2CxSTATCLR));
  258. }
  259. static void i2c_platform_disable(struct i2c_platform_data *priv)
  260. {
  261. pr_debug("i2c_platform_disable\n");
  262. }
  263. static int i2c_platform_probe(struct platform_device *pdev)
  264. {
  265. struct i2c_platform_data *priv;
  266. struct resource *r;
  267. int ret;
  268. pr_debug("i2c_platform_probe\n");
  269. r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  270. if (!r) {
  271. ret = -ENODEV;
  272. goto out;
  273. }
  274. priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL);
  275. if (!priv) {
  276. ret = -ENOMEM;
  277. goto out;
  278. }
  279. /* FIXME: need to allocate resource in PIC32 space */
  280. #if 0
  281. priv->base = bus_request_region(r->start, resource_size(r),
  282. pdev->name);
  283. #else
  284. priv->base = r->start;
  285. #endif
  286. if (!priv->base) {
  287. ret = -EBUSY;
  288. goto out_mem;
  289. }
  290. priv->xfer_timeout = 200;
  291. priv->ack_timeout = 200;
  292. priv->ctl_timeout = 200;
  293. priv->adap.nr = pdev->id;
  294. priv->adap.algo = &platform_algo;
  295. priv->adap.algo_data = priv;
  296. priv->adap.dev.parent = &pdev->dev;
  297. strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name));
  298. i2c_platform_setup(priv);
  299. ret = i2c_add_numbered_adapter(&priv->adap);
  300. if (ret == 0) {
  301. platform_set_drvdata(pdev, priv);
  302. return 0;
  303. }
  304. i2c_platform_disable(priv);
  305. out_mem:
  306. kfree(priv);
  307. out:
  308. return ret;
  309. }
  310. static int i2c_platform_remove(struct platform_device *pdev)
  311. {
  312. struct i2c_platform_data *priv = platform_get_drvdata(pdev);
  313. pr_debug("i2c_platform_remove\n");
  314. platform_set_drvdata(pdev, NULL);
  315. i2c_del_adapter(&priv->adap);
  316. i2c_platform_disable(priv);
  317. kfree(priv);
  318. return 0;
  319. }
  320. #ifdef CONFIG_PM
  321. static int
  322. i2c_platform_suspend(struct platform_device *pdev, pm_message_t state)
  323. {
  324. struct i2c_platform_data *priv = platform_get_drvdata(pdev);
  325. dev_dbg(&pdev->dev, "i2c_platform_disable\n");
  326. i2c_platform_disable(priv);
  327. return 0;
  328. }
  329. static int
  330. i2c_platform_resume(struct platform_device *pdev)
  331. {
  332. struct i2c_platform_data *priv = platform_get_drvdata(pdev);
  333. dev_dbg(&pdev->dev, "i2c_platform_setup\n");
  334. i2c_platform_setup(priv);
  335. return 0;
  336. }
  337. #else
  338. #define i2c_platform_suspend NULL
  339. #define i2c_platform_resume NULL
  340. #endif
  341. static struct platform_driver i2c_platform_driver = {
  342. .driver = {
  343. .name = "i2c_pic32",
  344. .owner = THIS_MODULE,
  345. },
  346. .probe = i2c_platform_probe,
  347. .remove = i2c_platform_remove,
  348. .suspend = i2c_platform_suspend,
  349. .resume = i2c_platform_resume,
  350. };
  351. static int __init
  352. i2c_platform_init(void)
  353. {
  354. pr_debug("i2c_platform_init\n");
  355. return platform_driver_register(&i2c_platform_driver);
  356. }
  357. static void __exit
  358. i2c_platform_exit(void)
  359. {
  360. pr_debug("i2c_platform_exit\n");
  361. platform_driver_unregister(&i2c_platform_driver);
  362. }
  363. MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
  364. MODULE_DESCRIPTION("PIC32 I2C driver");
  365. MODULE_LICENSE("GPL");
  366. module_init(i2c_platform_init);
  367. module_exit(i2c_platform_exit);