i2c-s6000.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * drivers/i2c/busses/i2c-s6000.c
  3. *
  4. * Description: Driver for S6000 Family I2C Interface
  5. * Copyright (c) 2008 emlix GmbH
  6. * Author: Oskar Schirmer <os@emlix.com>
  7. *
  8. * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com>
  9. * Copyright (c) 2005-2007 Analog Devices, Inc.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
  24. */
  25. #include <linux/clk.h>
  26. #include <linux/err.h>
  27. #include <linux/module.h>
  28. #include <linux/kernel.h>
  29. #include <linux/init.h>
  30. #include <linux/delay.h>
  31. #include <linux/i2c.h>
  32. #include <linux/i2c/s6000.h>
  33. #include <linux/timer.h>
  34. #include <linux/spinlock.h>
  35. #include <linux/completion.h>
  36. #include <linux/interrupt.h>
  37. #include <linux/platform_device.h>
  38. #include <linux/io.h>
  39. #include "i2c-s6000.h"
  40. #define DRV_NAME "i2c-s6000"
  41. #define POLL_TIMEOUT (2 * HZ)
  42. struct s6i2c_if {
  43. u8 __iomem *reg; /* memory mapped registers */
  44. int irq;
  45. spinlock_t lock;
  46. struct i2c_msg *msgs; /* messages currently handled */
  47. int msgs_num; /* nb of msgs to do */
  48. int msgs_push; /* nb of msgs read/written */
  49. int msgs_done; /* nb of msgs finally handled */
  50. unsigned push; /* nb of bytes read/written in msg */
  51. unsigned done; /* nb of bytes finally handled */
  52. int timeout_count; /* timeout retries left */
  53. struct timer_list timeout_timer;
  54. struct i2c_adapter adap;
  55. struct completion complete;
  56. struct clk *clk;
  57. struct resource *res;
  58. };
  59. static inline u16 i2c_rd16(struct s6i2c_if *iface, unsigned n)
  60. {
  61. return readw(iface->reg + (n));
  62. }
  63. static inline void i2c_wr16(struct s6i2c_if *iface, unsigned n, u16 v)
  64. {
  65. writew(v, iface->reg + (n));
  66. }
  67. static inline u32 i2c_rd32(struct s6i2c_if *iface, unsigned n)
  68. {
  69. return readl(iface->reg + (n));
  70. }
  71. static inline void i2c_wr32(struct s6i2c_if *iface, unsigned n, u32 v)
  72. {
  73. writel(v, iface->reg + (n));
  74. }
  75. static struct s6i2c_if s6i2c_if;
  76. static void s6i2c_handle_interrupt(struct s6i2c_if *iface)
  77. {
  78. if (i2c_rd16(iface, S6_I2C_INTRSTAT) & (1 << S6_I2C_INTR_TXABRT)) {
  79. i2c_rd16(iface, S6_I2C_CLRTXABRT);
  80. i2c_wr16(iface, S6_I2C_INTRMASK, 0);
  81. complete(&iface->complete);
  82. return;
  83. }
  84. if (iface->msgs_done >= iface->msgs_num) {
  85. dev_err(&iface->adap.dev, "s6i2c: spurious I2C irq: %04x\n",
  86. i2c_rd16(iface, S6_I2C_INTRSTAT));
  87. i2c_wr16(iface, S6_I2C_INTRMASK, 0);
  88. return;
  89. }
  90. while ((iface->msgs_push < iface->msgs_num)
  91. && (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_TFNF))) {
  92. struct i2c_msg *m = &iface->msgs[iface->msgs_push];
  93. if (!(m->flags & I2C_M_RD))
  94. i2c_wr16(iface, S6_I2C_DATACMD, m->buf[iface->push]);
  95. else
  96. i2c_wr16(iface, S6_I2C_DATACMD,
  97. 1 << S6_I2C_DATACMD_READ);
  98. if (++iface->push >= m->len) {
  99. iface->push = 0;
  100. iface->msgs_push += 1;
  101. }
  102. }
  103. do {
  104. struct i2c_msg *m = &iface->msgs[iface->msgs_done];
  105. if (!(m->flags & I2C_M_RD)) {
  106. if (iface->msgs_done < iface->msgs_push)
  107. iface->msgs_done += 1;
  108. else
  109. break;
  110. } else if (i2c_rd16(iface, S6_I2C_STATUS)
  111. & (1 << S6_I2C_STATUS_RFNE)) {
  112. m->buf[iface->done] = i2c_rd16(iface, S6_I2C_DATACMD);
  113. if (++iface->done >= m->len) {
  114. iface->done = 0;
  115. iface->msgs_done += 1;
  116. }
  117. } else{
  118. break;
  119. }
  120. } while (iface->msgs_done < iface->msgs_num);
  121. if (iface->msgs_done >= iface->msgs_num) {
  122. i2c_wr16(iface, S6_I2C_INTRMASK, 1 << S6_I2C_INTR_TXABRT);
  123. complete(&iface->complete);
  124. } else if (iface->msgs_push >= iface->msgs_num) {
  125. i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
  126. (1 << S6_I2C_INTR_RXFULL));
  127. } else {
  128. i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
  129. (1 << S6_I2C_INTR_TXEMPTY) |
  130. (1 << S6_I2C_INTR_RXFULL));
  131. }
  132. }
  133. static irqreturn_t s6i2c_interrupt_entry(int irq, void *dev_id)
  134. {
  135. struct s6i2c_if *iface = dev_id;
  136. if (!(i2c_rd16(iface, S6_I2C_STATUS) & ((1 << S6_I2C_INTR_RXUNDER)
  137. | (1 << S6_I2C_INTR_RXOVER)
  138. | (1 << S6_I2C_INTR_RXFULL)
  139. | (1 << S6_I2C_INTR_TXOVER)
  140. | (1 << S6_I2C_INTR_TXEMPTY)
  141. | (1 << S6_I2C_INTR_RDREQ)
  142. | (1 << S6_I2C_INTR_TXABRT)
  143. | (1 << S6_I2C_INTR_RXDONE)
  144. | (1 << S6_I2C_INTR_ACTIVITY)
  145. | (1 << S6_I2C_INTR_STOPDET)
  146. | (1 << S6_I2C_INTR_STARTDET)
  147. | (1 << S6_I2C_INTR_GENCALL))))
  148. return IRQ_NONE;
  149. spin_lock(&iface->lock);
  150. del_timer(&iface->timeout_timer);
  151. s6i2c_handle_interrupt(iface);
  152. spin_unlock(&iface->lock);
  153. return IRQ_HANDLED;
  154. }
  155. static void s6i2c_timeout(unsigned long data)
  156. {
  157. struct s6i2c_if *iface = (struct s6i2c_if *)data;
  158. unsigned long flags;
  159. spin_lock_irqsave(&iface->lock, flags);
  160. s6i2c_handle_interrupt(iface);
  161. if (--iface->timeout_count > 0) {
  162. iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
  163. add_timer(&iface->timeout_timer);
  164. } else {
  165. complete(&iface->complete);
  166. i2c_wr16(iface, S6_I2C_INTRMASK, 0);
  167. }
  168. spin_unlock_irqrestore(&iface->lock, flags);
  169. }
  170. static int s6i2c_master_xfer(struct i2c_adapter *adap,
  171. struct i2c_msg *msgs, int num)
  172. {
  173. struct s6i2c_if *iface = adap->algo_data;
  174. int i;
  175. if (num == 0)
  176. return 0;
  177. if (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
  178. yield();
  179. i2c_wr16(iface, S6_I2C_INTRMASK, 0);
  180. i2c_rd16(iface, S6_I2C_CLRINTR);
  181. for (i = 0; i < num; i++) {
  182. if (msgs[i].flags & I2C_M_TEN) {
  183. dev_err(&adap->dev,
  184. "s6i2c: 10 bits addr not supported\n");
  185. return -EINVAL;
  186. }
  187. if (msgs[i].len == 0) {
  188. dev_err(&adap->dev,
  189. "s6i2c: zero length message not supported\n");
  190. return -EINVAL;
  191. }
  192. if (msgs[i].addr != msgs[0].addr) {
  193. dev_err(&adap->dev,
  194. "s6i2c: multiple xfer cannot change target\n");
  195. return -EINVAL;
  196. }
  197. }
  198. iface->msgs = msgs;
  199. iface->msgs_num = num;
  200. iface->msgs_push = 0;
  201. iface->msgs_done = 0;
  202. iface->push = 0;
  203. iface->done = 0;
  204. iface->timeout_count = 10;
  205. i2c_wr16(iface, S6_I2C_TAR, msgs[0].addr);
  206. i2c_wr16(iface, S6_I2C_ENABLE, 1);
  207. i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXEMPTY) |
  208. (1 << S6_I2C_INTR_TXABRT));
  209. iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
  210. add_timer(&iface->timeout_timer);
  211. wait_for_completion(&iface->complete);
  212. del_timer_sync(&iface->timeout_timer);
  213. while (i2c_rd32(iface, S6_I2C_TXFLR) > 0)
  214. schedule();
  215. while (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
  216. schedule();
  217. i2c_wr16(iface, S6_I2C_INTRMASK, 0);
  218. i2c_wr16(iface, S6_I2C_ENABLE, 0);
  219. return iface->msgs_done;
  220. }
  221. static u32 s6i2c_functionality(struct i2c_adapter *adap)
  222. {
  223. return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
  224. }
  225. static struct i2c_algorithm s6i2c_algorithm = {
  226. .master_xfer = s6i2c_master_xfer,
  227. .functionality = s6i2c_functionality,
  228. };
  229. static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
  230. {
  231. u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000;
  232. if (dividend > 0xffff)
  233. return 0xffff;
  234. return dividend;
  235. }
  236. static int __devinit s6i2c_probe(struct platform_device *dev)
  237. {
  238. struct s6i2c_if *iface = &s6i2c_if;
  239. struct i2c_adapter *p_adap;
  240. const char *clock;
  241. int bus_num, rc;
  242. spin_lock_init(&iface->lock);
  243. init_completion(&iface->complete);
  244. iface->irq = platform_get_irq(dev, 0);
  245. if (iface->irq < 0) {
  246. rc = iface->irq;
  247. goto err_out;
  248. }
  249. iface->res = platform_get_resource(dev, IORESOURCE_MEM, 0);
  250. if (!iface->res) {
  251. rc = -ENXIO;
  252. goto err_out;
  253. }
  254. iface->res = request_mem_region(iface->res->start,
  255. resource_size(iface->res),
  256. dev->dev.bus_id);
  257. if (!iface->res) {
  258. rc = -EBUSY;
  259. goto err_out;
  260. }
  261. iface->reg = ioremap_nocache(iface->res->start,
  262. resource_size(iface->res));
  263. if (!iface->reg) {
  264. rc = -ENOMEM;
  265. goto err_reg;
  266. }
  267. clock = 0;
  268. bus_num = -1;
  269. if (dev->dev.platform_data) {
  270. struct s6_i2c_platform_data *pdata = dev->dev.platform_data;
  271. bus_num = pdata->bus_num;
  272. clock = pdata->clock;
  273. }
  274. iface->clk = clk_get(&dev->dev, clock);
  275. if (IS_ERR(iface->clk)) {
  276. rc = PTR_ERR(iface->clk);
  277. goto err_map;
  278. }
  279. rc = clk_enable(iface->clk);
  280. if (rc < 0)
  281. goto err_clk_put;
  282. init_timer(&iface->timeout_timer);
  283. iface->timeout_timer.function = s6i2c_timeout;
  284. iface->timeout_timer.data = (unsigned long)iface;
  285. p_adap = &iface->adap;
  286. strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
  287. p_adap->algo = &s6i2c_algorithm;
  288. p_adap->algo_data = iface;
  289. p_adap->nr = bus_num;
  290. p_adap->class = 0;
  291. p_adap->dev.parent = &dev->dev;
  292. i2c_wr16(iface, S6_I2C_INTRMASK, 0);
  293. rc = request_irq(iface->irq, s6i2c_interrupt_entry,
  294. IRQF_SHARED, dev->name, iface);
  295. if (rc) {
  296. dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq);
  297. goto err_clk_dis;
  298. }
  299. i2c_wr16(iface, S6_I2C_ENABLE, 0);
  300. udelay(1);
  301. i2c_wr32(iface, S6_I2C_SRESET, 1 << S6_I2C_SRESET_IC_SRST);
  302. i2c_wr16(iface, S6_I2C_CLRTXABRT, 1);
  303. i2c_wr16(iface, S6_I2C_CON,
  304. (1 << S6_I2C_CON_MASTER) |
  305. (S6_I2C_CON_SPEED_NORMAL << S6_I2C_CON_SPEED) |
  306. (0 << S6_I2C_CON_10BITSLAVE) |
  307. (0 << S6_I2C_CON_10BITMASTER) |
  308. (1 << S6_I2C_CON_RESTARTENA) |
  309. (1 << S6_I2C_CON_SLAVEDISABLE));
  310. i2c_wr16(iface, S6_I2C_SSHCNT, nanoseconds_on_clk(iface, 4000));
  311. i2c_wr16(iface, S6_I2C_SSLCNT, nanoseconds_on_clk(iface, 4700));
  312. i2c_wr16(iface, S6_I2C_FSHCNT, nanoseconds_on_clk(iface, 600));
  313. i2c_wr16(iface, S6_I2C_FSLCNT, nanoseconds_on_clk(iface, 1300));
  314. i2c_wr16(iface, S6_I2C_RXTL, 0);
  315. i2c_wr16(iface, S6_I2C_TXTL, 0);
  316. platform_set_drvdata(dev, iface);
  317. rc = i2c_add_numbered_adapter(p_adap);
  318. if (rc)
  319. goto err_irq_free;
  320. return 0;
  321. err_irq_free:
  322. free_irq(iface->irq, iface);
  323. err_clk_dis:
  324. clk_disable(iface->clk);
  325. err_clk_put:
  326. clk_put(iface->clk);
  327. err_map:
  328. iounmap(iface->reg);
  329. err_reg:
  330. release_mem_region(iface->res->start,
  331. resource_size(iface->res));
  332. err_out:
  333. return rc;
  334. }
  335. static int __devexit s6i2c_remove(struct platform_device *pdev)
  336. {
  337. struct s6i2c_if *iface = platform_get_drvdata(pdev);
  338. i2c_wr16(iface, S6_I2C_ENABLE, 0);
  339. platform_set_drvdata(pdev, NULL);
  340. i2c_del_adapter(&iface->adap);
  341. free_irq(iface->irq, iface);
  342. clk_disable(iface->clk);
  343. clk_put(iface->clk);
  344. iounmap(iface->reg);
  345. release_mem_region(iface->res->start,
  346. resource_size(iface->res));
  347. return 0;
  348. }
  349. static struct platform_driver s6i2c_driver = {
  350. .probe = s6i2c_probe,
  351. .remove = __devexit_p(s6i2c_remove),
  352. .driver = {
  353. .name = DRV_NAME,
  354. .owner = THIS_MODULE,
  355. },
  356. };
  357. static int __init s6i2c_init(void)
  358. {
  359. pr_info("I2C: S6000 I2C driver\n");
  360. return platform_driver_register(&s6i2c_driver);
  361. }
  362. static void __exit s6i2c_exit(void)
  363. {
  364. platform_driver_unregister(&s6i2c_driver);
  365. }
  366. MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C");
  367. MODULE_LICENSE("GPL");
  368. MODULE_ALIAS("platform:" DRV_NAME);
  369. subsys_initcall(s6i2c_init);
  370. module_exit(s6i2c_exit);