i2c-iop3xx.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /* ------------------------------------------------------------------------- */
  2. /* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */
  3. /* ------------------------------------------------------------------------- */
  4. /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
  5. * <Peter dot Milne at D hyphen TACQ dot com>
  6. *
  7. * With acknowledgements to i2c-algo-ibm_ocp.c by
  8. * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
  9. *
  10. * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
  11. *
  12. * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
  13. *
  14. * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
  15. * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
  16. *
  17. * Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005:
  18. *
  19. * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs
  20. * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference
  21. * - Make it work with IXP46x chips
  22. * - Cleanup function names, coding style, etc
  23. *
  24. * This program is free software; you can redistribute it and/or modify
  25. * it under the terms of the GNU General Public License as published by
  26. * the Free Software Foundation, version 2.
  27. */
  28. #include <linux/config.h>
  29. #include <linux/interrupt.h>
  30. #include <linux/kernel.h>
  31. #include <linux/module.h>
  32. #include <linux/delay.h>
  33. #include <linux/slab.h>
  34. #include <linux/init.h>
  35. #include <linux/errno.h>
  36. #include <linux/sched.h>
  37. #include <linux/platform_device.h>
  38. #include <linux/i2c.h>
  39. #include <asm/io.h>
  40. #include "i2c-iop3xx.h"
  41. /* global unit counter */
  42. static int i2c_id;
  43. static inline unsigned char
  44. iic_cook_addr(struct i2c_msg *msg)
  45. {
  46. unsigned char addr;
  47. addr = (msg->addr << 1);
  48. if (msg->flags & I2C_M_RD)
  49. addr |= 1;
  50. /*
  51. * Read or Write?
  52. */
  53. if (msg->flags & I2C_M_REV_DIR_ADDR)
  54. addr ^= 1;
  55. return addr;
  56. }
  57. static void
  58. iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
  59. {
  60. /* Follows devman 9.3 */
  61. __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
  62. __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
  63. __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
  64. }
  65. static void
  66. iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
  67. {
  68. __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET);
  69. }
  70. static void
  71. iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
  72. {
  73. u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
  74. /*
  75. * Every time unit enable is asserted, GPOD needs to be cleared
  76. * on IOP321 to avoid data corruption on the bus.
  77. */
  78. #ifdef CONFIG_ARCH_IOP321
  79. #define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
  80. #define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
  81. *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 :
  82. ~IOP321_GPOD_I2C1;
  83. #endif
  84. /* NB SR bits not same position as CR IE bits :-( */
  85. iop3xx_adap->SR_enabled =
  86. IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
  87. IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
  88. cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
  89. IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE;
  90. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  91. }
  92. static void
  93. iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
  94. {
  95. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  96. cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
  97. IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
  98. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  99. }
  100. /*
  101. * NB: the handler has to clear the source of the interrupt!
  102. * Then it passes the SR flags of interest to BH via adap data
  103. */
  104. static irqreturn_t
  105. iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
  106. {
  107. struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
  108. u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
  109. if ((sr &= iop3xx_adap->SR_enabled)) {
  110. __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET);
  111. iop3xx_adap->SR_received |= sr;
  112. wake_up_interruptible(&iop3xx_adap->waitq);
  113. }
  114. return IRQ_HANDLED;
  115. }
  116. /* check all error conditions, clear them , report most important */
  117. static int
  118. iop3xx_i2c_error(u32 sr)
  119. {
  120. int rc = 0;
  121. if ((sr & IOP3XX_ISR_BERRD)) {
  122. if ( !rc ) rc = -I2C_ERR_BERR;
  123. }
  124. if ((sr & IOP3XX_ISR_ALD)) {
  125. if ( !rc ) rc = -I2C_ERR_ALD;
  126. }
  127. return rc;
  128. }
  129. static inline u32
  130. iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
  131. {
  132. unsigned long flags;
  133. u32 sr;
  134. spin_lock_irqsave(&iop3xx_adap->lock, flags);
  135. sr = iop3xx_adap->SR_received;
  136. iop3xx_adap->SR_received = 0;
  137. spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
  138. return sr;
  139. }
  140. /*
  141. * sleep until interrupted, then recover and analyse the SR
  142. * saved by handler
  143. */
  144. typedef int (* compare_func)(unsigned test, unsigned mask);
  145. /* returns 1 on correct comparison */
  146. static int
  147. iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
  148. unsigned flags, unsigned* status,
  149. compare_func compare)
  150. {
  151. unsigned sr = 0;
  152. int interrupted;
  153. int done;
  154. int rc = 0;
  155. do {
  156. interrupted = wait_event_interruptible_timeout (
  157. iop3xx_adap->waitq,
  158. (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
  159. 1 * HZ;
  160. );
  161. if ((rc = iop3xx_i2c_error(sr)) < 0) {
  162. *status = sr;
  163. return rc;
  164. } else if (!interrupted) {
  165. *status = sr;
  166. return -ETIMEDOUT;
  167. }
  168. } while(!done);
  169. *status = sr;
  170. return 0;
  171. }
  172. /*
  173. * Concrete compare_funcs
  174. */
  175. static int
  176. all_bits_clear(unsigned test, unsigned mask)
  177. {
  178. return (test & mask) == 0;
  179. }
  180. static int
  181. any_bits_set(unsigned test, unsigned mask)
  182. {
  183. return (test & mask) != 0;
  184. }
  185. static int
  186. iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
  187. {
  188. return iop3xx_i2c_wait_event(
  189. iop3xx_adap,
  190. IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
  191. status, any_bits_set);
  192. }
  193. static int
  194. iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
  195. {
  196. return iop3xx_i2c_wait_event(
  197. iop3xx_adap,
  198. IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
  199. status, any_bits_set);
  200. }
  201. static int
  202. iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
  203. {
  204. return iop3xx_i2c_wait_event(
  205. iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
  206. }
  207. static int
  208. iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
  209. struct i2c_msg* msg)
  210. {
  211. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  212. int status;
  213. int rc;
  214. __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
  215. cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
  216. cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
  217. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  218. rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
  219. return rc;
  220. }
  221. static int
  222. iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
  223. int stop)
  224. {
  225. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  226. int status;
  227. int rc = 0;
  228. __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET);
  229. cr &= ~IOP3XX_ICR_MSTART;
  230. if (stop) {
  231. cr |= IOP3XX_ICR_MSTOP;
  232. } else {
  233. cr &= ~IOP3XX_ICR_MSTOP;
  234. }
  235. cr |= IOP3XX_ICR_TBYTE;
  236. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  237. rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
  238. return rc;
  239. }
  240. static int
  241. iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
  242. int stop)
  243. {
  244. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  245. int status;
  246. int rc = 0;
  247. cr &= ~IOP3XX_ICR_MSTART;
  248. if (stop) {
  249. cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK;
  250. } else {
  251. cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
  252. }
  253. cr |= IOP3XX_ICR_TBYTE;
  254. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  255. rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status);
  256. *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET);
  257. return rc;
  258. }
  259. static int
  260. iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
  261. {
  262. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  263. int ii;
  264. int rc = 0;
  265. for (ii = 0; rc == 0 && ii != count; ++ii)
  266. rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
  267. return rc;
  268. }
  269. static int
  270. iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
  271. {
  272. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  273. int ii;
  274. int rc = 0;
  275. for (ii = 0; rc == 0 && ii != count; ++ii)
  276. rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
  277. return rc;
  278. }
  279. /*
  280. * Description: This function implements combined transactions. Combined
  281. * transactions consist of combinations of reading and writing blocks of data.
  282. * FROM THE SAME ADDRESS
  283. * Each transfer (i.e. a read or a write) is separated by a repeated start
  284. * condition.
  285. */
  286. static int
  287. iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
  288. {
  289. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  290. int rc;
  291. rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg);
  292. if (rc < 0) {
  293. return rc;
  294. }
  295. if ((pmsg->flags&I2C_M_RD)) {
  296. return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
  297. } else {
  298. return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
  299. }
  300. }
  301. /*
  302. * master_xfer() - main read/write entry
  303. */
  304. static int
  305. iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
  306. int num)
  307. {
  308. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  309. int im = 0;
  310. int ret = 0;
  311. int status;
  312. iop3xx_i2c_wait_idle(iop3xx_adap, &status);
  313. iop3xx_i2c_reset(iop3xx_adap);
  314. iop3xx_i2c_enable(iop3xx_adap);
  315. for (im = 0; ret == 0 && im != num; im++) {
  316. ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]);
  317. }
  318. iop3xx_i2c_transaction_cleanup(iop3xx_adap);
  319. if(ret)
  320. return ret;
  321. return im;
  322. }
  323. static int
  324. iop3xx_i2c_algo_control(struct i2c_adapter *adapter, unsigned int cmd,
  325. unsigned long arg)
  326. {
  327. return 0;
  328. }
  329. static u32
  330. iop3xx_i2c_func(struct i2c_adapter *adap)
  331. {
  332. return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
  333. }
  334. static struct i2c_algorithm iop3xx_i2c_algo = {
  335. .master_xfer = iop3xx_i2c_master_xfer,
  336. .algo_control = iop3xx_i2c_algo_control,
  337. .functionality = iop3xx_i2c_func,
  338. };
  339. static int
  340. iop3xx_i2c_remove(struct platform_device *pdev)
  341. {
  342. struct i2c_adapter *padapter = platform_get_drvdata(pdev);
  343. struct i2c_algo_iop3xx_data *adapter_data =
  344. (struct i2c_algo_iop3xx_data *)padapter->algo_data;
  345. struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  346. unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
  347. /*
  348. * Disable the actual HW unit
  349. */
  350. cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
  351. IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE);
  352. __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET);
  353. iounmap((void __iomem*)adapter_data->ioaddr);
  354. release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
  355. kfree(adapter_data);
  356. kfree(padapter);
  357. platform_set_drvdata(pdev, NULL);
  358. return 0;
  359. }
  360. static int
  361. iop3xx_i2c_probe(struct platform_device *pdev)
  362. {
  363. struct resource *res;
  364. int ret, irq;
  365. struct i2c_adapter *new_adapter;
  366. struct i2c_algo_iop3xx_data *adapter_data;
  367. new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
  368. if (!new_adapter) {
  369. ret = -ENOMEM;
  370. goto out;
  371. }
  372. adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
  373. if (!adapter_data) {
  374. ret = -ENOMEM;
  375. goto free_adapter;
  376. }
  377. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  378. if (!res) {
  379. ret = -ENODEV;
  380. goto free_both;
  381. }
  382. if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) {
  383. ret = -EBUSY;
  384. goto free_both;
  385. }
  386. /* set the adapter enumeration # */
  387. adapter_data->id = i2c_id++;
  388. adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE);
  389. if (!adapter_data->ioaddr) {
  390. ret = -ENOMEM;
  391. goto release_region;
  392. }
  393. irq = platform_get_irq(pdev, 0);
  394. if (irq < 0) {
  395. ret = -ENXIO;
  396. goto unmap;
  397. }
  398. ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
  399. pdev->name, adapter_data);
  400. if (ret) {
  401. ret = -EIO;
  402. goto unmap;
  403. }
  404. memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
  405. new_adapter->id = I2C_HW_IOP3XX;
  406. new_adapter->owner = THIS_MODULE;
  407. new_adapter->dev.parent = &pdev->dev;
  408. /*
  409. * Default values...should these come in from board code?
  410. */
  411. new_adapter->timeout = 100;
  412. new_adapter->retries = 3;
  413. new_adapter->algo = &iop3xx_i2c_algo;
  414. init_waitqueue_head(&adapter_data->waitq);
  415. spin_lock_init(&adapter_data->lock);
  416. iop3xx_i2c_reset(adapter_data);
  417. iop3xx_i2c_set_slave_addr(adapter_data);
  418. iop3xx_i2c_enable(adapter_data);
  419. platform_set_drvdata(pdev, new_adapter);
  420. new_adapter->algo_data = adapter_data;
  421. i2c_add_adapter(new_adapter);
  422. return 0;
  423. unmap:
  424. iounmap((void __iomem*)adapter_data->ioaddr);
  425. release_region:
  426. release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
  427. free_both:
  428. kfree(adapter_data);
  429. free_adapter:
  430. kfree(new_adapter);
  431. out:
  432. return ret;
  433. }
  434. static struct platform_driver iop3xx_i2c_driver = {
  435. .probe = iop3xx_i2c_probe,
  436. .remove = iop3xx_i2c_remove,
  437. .driver = {
  438. .owner = THIS_MODULE,
  439. .name = "IOP3xx-I2C",
  440. },
  441. };
  442. static int __init
  443. i2c_iop3xx_init (void)
  444. {
  445. return platform_driver_register(&iop3xx_i2c_driver);
  446. }
  447. static void __exit
  448. i2c_iop3xx_exit (void)
  449. {
  450. platform_driver_unregister(&iop3xx_i2c_driver);
  451. return;
  452. }
  453. module_init (i2c_iop3xx_init);
  454. module_exit (i2c_iop3xx_exit);
  455. MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
  456. MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
  457. MODULE_LICENSE("GPL");