i2c-iop3xx.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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. * - writing to slave address causes latchup on iop331.
  25. * fix: driver refuses to address self.
  26. *
  27. * This program is free software; you can redistribute it and/or modify
  28. * it under the terms of the GNU General Public License as published by
  29. * the Free Software Foundation, version 2.
  30. */
  31. #include <linux/interrupt.h>
  32. #include <linux/kernel.h>
  33. #include <linux/module.h>
  34. #include <linux/delay.h>
  35. #include <linux/slab.h>
  36. #include <linux/errno.h>
  37. #include <linux/platform_device.h>
  38. #include <linux/i2c.h>
  39. #include <linux/io.h>
  40. #include <linux/gpio.h>
  41. #include "i2c-iop3xx.h"
  42. /* global unit counter */
  43. static int i2c_id;
  44. static inline unsigned char
  45. iic_cook_addr(struct i2c_msg *msg)
  46. {
  47. unsigned char addr;
  48. addr = i2c_8bit_addr_from_msg(msg);
  49. return addr;
  50. }
  51. static void
  52. iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
  53. {
  54. /* Follows devman 9.3 */
  55. __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
  56. __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
  57. __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
  58. }
  59. static void
  60. iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
  61. {
  62. u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
  63. /*
  64. * Every time unit enable is asserted, GPOD needs to be cleared
  65. * on IOP3XX to avoid data corruption on the bus.
  66. */
  67. #if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
  68. if (iop3xx_adap->id == 0) {
  69. gpio_set_value(7, 0);
  70. gpio_set_value(6, 0);
  71. } else {
  72. gpio_set_value(5, 0);
  73. gpio_set_value(4, 0);
  74. }
  75. #endif
  76. /* NB SR bits not same position as CR IE bits :-( */
  77. iop3xx_adap->SR_enabled =
  78. IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
  79. IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
  80. cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
  81. IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE;
  82. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  83. }
  84. static void
  85. iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
  86. {
  87. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  88. cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
  89. IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
  90. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  91. }
  92. /*
  93. * NB: the handler has to clear the source of the interrupt!
  94. * Then it passes the SR flags of interest to BH via adap data
  95. */
  96. static irqreturn_t
  97. iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
  98. {
  99. struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
  100. u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
  101. if ((sr &= iop3xx_adap->SR_enabled)) {
  102. __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET);
  103. iop3xx_adap->SR_received |= sr;
  104. wake_up_interruptible(&iop3xx_adap->waitq);
  105. }
  106. return IRQ_HANDLED;
  107. }
  108. /* check all error conditions, clear them , report most important */
  109. static int
  110. iop3xx_i2c_error(u32 sr)
  111. {
  112. int rc = 0;
  113. if ((sr & IOP3XX_ISR_BERRD)) {
  114. if ( !rc ) rc = -I2C_ERR_BERR;
  115. }
  116. if ((sr & IOP3XX_ISR_ALD)) {
  117. if ( !rc ) rc = -I2C_ERR_ALD;
  118. }
  119. return rc;
  120. }
  121. static inline u32
  122. iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
  123. {
  124. unsigned long flags;
  125. u32 sr;
  126. spin_lock_irqsave(&iop3xx_adap->lock, flags);
  127. sr = iop3xx_adap->SR_received;
  128. iop3xx_adap->SR_received = 0;
  129. spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
  130. return sr;
  131. }
  132. /*
  133. * sleep until interrupted, then recover and analyse the SR
  134. * saved by handler
  135. */
  136. typedef int (* compare_func)(unsigned test, unsigned mask);
  137. /* returns 1 on correct comparison */
  138. static int
  139. iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
  140. unsigned flags, unsigned* status,
  141. compare_func compare)
  142. {
  143. unsigned sr = 0;
  144. int interrupted;
  145. int done;
  146. int rc = 0;
  147. do {
  148. interrupted = wait_event_interruptible_timeout (
  149. iop3xx_adap->waitq,
  150. (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
  151. 1 * HZ
  152. );
  153. if ((rc = iop3xx_i2c_error(sr)) < 0) {
  154. *status = sr;
  155. return rc;
  156. } else if (!interrupted) {
  157. *status = sr;
  158. return -ETIMEDOUT;
  159. }
  160. } while(!done);
  161. *status = sr;
  162. return 0;
  163. }
  164. /*
  165. * Concrete compare_funcs
  166. */
  167. static int
  168. all_bits_clear(unsigned test, unsigned mask)
  169. {
  170. return (test & mask) == 0;
  171. }
  172. static int
  173. any_bits_set(unsigned test, unsigned mask)
  174. {
  175. return (test & mask) != 0;
  176. }
  177. static int
  178. iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
  179. {
  180. return iop3xx_i2c_wait_event(
  181. iop3xx_adap,
  182. IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
  183. status, any_bits_set);
  184. }
  185. static int
  186. iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
  187. {
  188. return iop3xx_i2c_wait_event(
  189. iop3xx_adap,
  190. IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
  191. status, any_bits_set);
  192. }
  193. static int
  194. iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
  195. {
  196. return iop3xx_i2c_wait_event(
  197. iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
  198. }
  199. static int
  200. iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
  201. struct i2c_msg* msg)
  202. {
  203. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  204. int status;
  205. int rc;
  206. /* avoid writing to my slave address (hangs on 80331),
  207. * forbidden in Intel developer manual
  208. */
  209. if (msg->addr == MYSAR) {
  210. return -EBUSY;
  211. }
  212. __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
  213. cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
  214. cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
  215. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  216. rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
  217. return rc;
  218. }
  219. static int
  220. iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
  221. int stop)
  222. {
  223. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  224. int status;
  225. int rc = 0;
  226. __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET);
  227. cr &= ~IOP3XX_ICR_MSTART;
  228. if (stop) {
  229. cr |= IOP3XX_ICR_MSTOP;
  230. } else {
  231. cr &= ~IOP3XX_ICR_MSTOP;
  232. }
  233. cr |= IOP3XX_ICR_TBYTE;
  234. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  235. rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
  236. return rc;
  237. }
  238. static int
  239. iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
  240. int stop)
  241. {
  242. unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
  243. int status;
  244. int rc = 0;
  245. cr &= ~IOP3XX_ICR_MSTART;
  246. if (stop) {
  247. cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK;
  248. } else {
  249. cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
  250. }
  251. cr |= IOP3XX_ICR_TBYTE;
  252. __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
  253. rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status);
  254. *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET);
  255. return rc;
  256. }
  257. static int
  258. iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
  259. {
  260. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  261. int ii;
  262. int rc = 0;
  263. for (ii = 0; rc == 0 && ii != count; ++ii)
  264. rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
  265. return rc;
  266. }
  267. static int
  268. iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
  269. {
  270. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  271. int ii;
  272. int rc = 0;
  273. for (ii = 0; rc == 0 && ii != count; ++ii)
  274. rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
  275. return rc;
  276. }
  277. /*
  278. * Description: This function implements combined transactions. Combined
  279. * transactions consist of combinations of reading and writing blocks of data.
  280. * FROM THE SAME ADDRESS
  281. * Each transfer (i.e. a read or a write) is separated by a repeated start
  282. * condition.
  283. */
  284. static int
  285. iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
  286. {
  287. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  288. int rc;
  289. rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg);
  290. if (rc < 0) {
  291. return rc;
  292. }
  293. if ((pmsg->flags&I2C_M_RD)) {
  294. return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
  295. } else {
  296. return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
  297. }
  298. }
  299. /*
  300. * master_xfer() - main read/write entry
  301. */
  302. static int
  303. iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
  304. int num)
  305. {
  306. struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
  307. int im = 0;
  308. int ret = 0;
  309. int status;
  310. iop3xx_i2c_wait_idle(iop3xx_adap, &status);
  311. iop3xx_i2c_reset(iop3xx_adap);
  312. iop3xx_i2c_enable(iop3xx_adap);
  313. for (im = 0; ret == 0 && im != num; im++) {
  314. ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]);
  315. }
  316. iop3xx_i2c_transaction_cleanup(iop3xx_adap);
  317. if(ret)
  318. return ret;
  319. return im;
  320. }
  321. static u32
  322. iop3xx_i2c_func(struct i2c_adapter *adap)
  323. {
  324. return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
  325. }
  326. static const struct i2c_algorithm iop3xx_i2c_algo = {
  327. .master_xfer = iop3xx_i2c_master_xfer,
  328. .functionality = iop3xx_i2c_func,
  329. };
  330. static int
  331. iop3xx_i2c_remove(struct platform_device *pdev)
  332. {
  333. struct i2c_adapter *padapter = platform_get_drvdata(pdev);
  334. struct i2c_algo_iop3xx_data *adapter_data =
  335. (struct i2c_algo_iop3xx_data *)padapter->algo_data;
  336. struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  337. unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
  338. /*
  339. * Disable the actual HW unit
  340. */
  341. cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
  342. IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE);
  343. __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET);
  344. iounmap(adapter_data->ioaddr);
  345. release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
  346. kfree(adapter_data);
  347. kfree(padapter);
  348. return 0;
  349. }
  350. static int
  351. iop3xx_i2c_probe(struct platform_device *pdev)
  352. {
  353. struct resource *res;
  354. int ret, irq;
  355. struct i2c_adapter *new_adapter;
  356. struct i2c_algo_iop3xx_data *adapter_data;
  357. new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
  358. if (!new_adapter) {
  359. ret = -ENOMEM;
  360. goto out;
  361. }
  362. adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
  363. if (!adapter_data) {
  364. ret = -ENOMEM;
  365. goto free_adapter;
  366. }
  367. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  368. if (!res) {
  369. ret = -ENODEV;
  370. goto free_both;
  371. }
  372. if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) {
  373. ret = -EBUSY;
  374. goto free_both;
  375. }
  376. /* set the adapter enumeration # */
  377. adapter_data->id = i2c_id++;
  378. adapter_data->ioaddr = ioremap(res->start, IOP3XX_I2C_IO_SIZE);
  379. if (!adapter_data->ioaddr) {
  380. ret = -ENOMEM;
  381. goto release_region;
  382. }
  383. irq = platform_get_irq(pdev, 0);
  384. if (irq < 0) {
  385. ret = -ENXIO;
  386. goto unmap;
  387. }
  388. ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
  389. pdev->name, adapter_data);
  390. if (ret) {
  391. ret = -EIO;
  392. goto unmap;
  393. }
  394. memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
  395. new_adapter->owner = THIS_MODULE;
  396. new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
  397. new_adapter->dev.parent = &pdev->dev;
  398. new_adapter->nr = pdev->id;
  399. /*
  400. * Default values...should these come in from board code?
  401. */
  402. new_adapter->timeout = HZ;
  403. new_adapter->algo = &iop3xx_i2c_algo;
  404. init_waitqueue_head(&adapter_data->waitq);
  405. spin_lock_init(&adapter_data->lock);
  406. iop3xx_i2c_reset(adapter_data);
  407. iop3xx_i2c_enable(adapter_data);
  408. platform_set_drvdata(pdev, new_adapter);
  409. new_adapter->algo_data = adapter_data;
  410. i2c_add_numbered_adapter(new_adapter);
  411. return 0;
  412. unmap:
  413. iounmap(adapter_data->ioaddr);
  414. release_region:
  415. release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
  416. free_both:
  417. kfree(adapter_data);
  418. free_adapter:
  419. kfree(new_adapter);
  420. out:
  421. return ret;
  422. }
  423. static struct platform_driver iop3xx_i2c_driver = {
  424. .probe = iop3xx_i2c_probe,
  425. .remove = iop3xx_i2c_remove,
  426. .driver = {
  427. .name = "IOP3xx-I2C",
  428. },
  429. };
  430. module_platform_driver(iop3xx_i2c_driver);
  431. MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
  432. MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
  433. MODULE_LICENSE("GPL");
  434. MODULE_ALIAS("platform:IOP3xx-I2C");