bbc_i2c.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: bbc_i2c.c,v 1.2 2001/04/02 09:59:08 davem Exp $
  2.  * bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III
  3.  *            platforms.
  4.  *
  5.  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
  6.  */
  7. #include <linux/module.h>
  8. #include <linux/kernel.h>
  9. #include <linux/types.h>
  10. #include <linux/slab.h>
  11. #include <linux/sched.h>
  12. #include <linux/wait.h>
  13. #include <linux/delay.h>
  14. #include <linux/init.h>
  15. #include <asm/oplib.h>
  16. #include <asm/ebus.h>
  17. #include <asm/spitfire.h>
  18. #include <asm/bbc.h>
  19. #include "bbc_i2c.h"
  20. /* Convert this driver to use i2c bus layer someday... */
  21. #define I2C_PCF_PIN 0x80
  22. #define I2C_PCF_ESO 0x40
  23. #define I2C_PCF_ES1 0x20
  24. #define I2C_PCF_ES2 0x10
  25. #define I2C_PCF_ENI 0x08
  26. #define I2C_PCF_STA 0x04
  27. #define I2C_PCF_STO 0x02
  28. #define I2C_PCF_ACK 0x01
  29. #define I2C_PCF_START    (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_ENI | I2C_PCF_STA | I2C_PCF_ACK)
  30. #define I2C_PCF_STOP     (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STO | I2C_PCF_ACK)
  31. #define I2C_PCF_REPSTART (              I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK)
  32. #define I2C_PCF_IDLE     (I2C_PCF_PIN | I2C_PCF_ESO               | I2C_PCF_ACK)
  33. #define I2C_PCF_INI 0x40   /* 1 if not initialized */
  34. #define I2C_PCF_STS 0x20
  35. #define I2C_PCF_BER 0x10
  36. #define I2C_PCF_AD0 0x08
  37. #define I2C_PCF_LRB 0x08
  38. #define I2C_PCF_AAS 0x04
  39. #define I2C_PCF_LAB 0x02
  40. #define I2C_PCF_BB  0x01
  41. /* The BBC devices have two I2C controllers.  The first I2C controller
  42.  * connects mainly to configuration proms (NVRAM, cpu configuration,
  43.  * dimm types, etc.).  Whereas the second I2C controller connects to
  44.  * environmental control devices such as fans and temperature sensors.
  45.  * The second controller also connects to the smartcard reader, if present.
  46.  */
  47. #define NUM_CHILDREN 8
  48. struct bbc_i2c_bus {
  49. struct bbc_i2c_bus *next;
  50. int index;
  51. spinlock_t lock;
  52. void *i2c_bussel_reg;
  53. void *i2c_control_regs;
  54. unsigned char own, clock;
  55. wait_queue_head_t wq;
  56. volatile int waiting;
  57. struct linux_ebus_device *bus_edev;
  58. struct {
  59. struct linux_ebus_child *device;
  60. int client_claimed;
  61. } devs[NUM_CHILDREN];
  62. };
  63. static struct bbc_i2c_bus *all_bbc_i2c;
  64. struct bbc_i2c_client {
  65. struct bbc_i2c_bus *bp;
  66. struct linux_ebus_child *echild;
  67. int bus;
  68. int address;
  69. };
  70. static int find_device(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild)
  71. {
  72. int i;
  73. for (i = 0; i < NUM_CHILDREN; i++) {
  74. if (bp->devs[i].device == echild) {
  75. if (bp->devs[i].client_claimed)
  76. return 0;
  77. return 1;
  78. }
  79. }
  80. return 0;
  81. }
  82. static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild, int val)
  83. {
  84. int i;
  85. for (i = 0; i < NUM_CHILDREN; i++) {
  86. if (bp->devs[i].device == echild) {
  87. bp->devs[i].client_claimed = val;
  88. return;
  89. }
  90. }
  91. }
  92. #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1)
  93. #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0)
  94. static struct bbc_i2c_bus *find_bus_for_device(struct linux_ebus_child *echild)
  95. {
  96. struct bbc_i2c_bus *bp = all_bbc_i2c;
  97. while (bp != NULL) {
  98. if (find_device(bp, echild) != 0)
  99. break;
  100. bp = bp->next;
  101. }
  102. return bp;
  103. }
  104. struct linux_ebus_child *bbc_i2c_getdev(int index)
  105. {
  106. struct bbc_i2c_bus *bp = all_bbc_i2c;
  107. struct linux_ebus_child *echild = NULL;
  108. int curidx = 0;
  109. while (bp != NULL) {
  110. struct bbc_i2c_bus *next = bp->next;
  111. int i;
  112. for (i = 0; i < NUM_CHILDREN; i++) {
  113. if (!(echild = bp->devs[i].device))
  114. break;
  115. if (curidx == index)
  116. goto out;
  117. echild = NULL;
  118. curidx++;
  119. }
  120. bp = next;
  121. }
  122. out:
  123. if (curidx == index)
  124. return echild;
  125. return NULL;
  126. }
  127. struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild)
  128. {
  129. struct bbc_i2c_bus *bp = find_bus_for_device(echild);
  130. struct bbc_i2c_client *client;
  131. if (!bp)
  132. return NULL;
  133. client = kmalloc(sizeof(*client), GFP_KERNEL);
  134. if (!client)
  135. return NULL;
  136. memset(client, 0, sizeof(*client));
  137. client->bp = bp;
  138. client->echild = echild;
  139. client->bus = echild->resource[0].start;
  140. client->address = echild->resource[1].start;
  141. claim_device(bp, echild);
  142. return client;
  143. }
  144. void bbc_i2c_detach(struct bbc_i2c_client *client)
  145. {
  146. struct bbc_i2c_bus *bp = client->bp;
  147. struct linux_ebus_child *echild = client->echild;
  148. release_device(bp, echild);
  149. kfree(client);
  150. }
  151. static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status)
  152. {
  153. DECLARE_WAITQUEUE(wait, current);
  154. int limit = 32;
  155. int ret = 1;
  156. bp->waiting = 1;
  157. add_wait_queue(&bp->wq, &wait);
  158. while (limit-- > 0) {
  159. u8 val;
  160. current->state = TASK_INTERRUPTIBLE;
  161. *status = val = readb(bp->i2c_control_regs + 0);
  162. if ((val & I2C_PCF_PIN) == 0) {
  163. ret = 0;
  164. break;
  165. }
  166. schedule_timeout(HZ/4);
  167. }
  168. remove_wait_queue(&bp->wq, &wait);
  169. bp->waiting = 0;
  170. current->state = TASK_RUNNING;
  171. return ret;
  172. }
  173. int bbc_i2c_writeb(struct bbc_i2c_client *client, unsigned char val, int off)
  174. {
  175. struct bbc_i2c_bus *bp = client->bp;
  176. int address = client->address;
  177. u8 status;
  178. int ret = -1;
  179. if (bp->i2c_bussel_reg != NULL)
  180. writeb(client->bus, bp->i2c_bussel_reg);
  181. writeb(address, bp->i2c_control_regs + 0x1);
  182. writeb(I2C_PCF_START, bp->i2c_control_regs + 0x0);
  183. if (wait_for_pin(bp, &status))
  184. goto out;
  185. writeb(off, bp->i2c_control_regs + 0x1);
  186. if (wait_for_pin(bp, &status) ||
  187.     (status & I2C_PCF_LRB) != 0)
  188. goto out;
  189. writeb(val, bp->i2c_control_regs + 0x1);
  190. if (wait_for_pin(bp, &status))
  191. goto out;
  192. ret = 0;
  193. out:
  194. writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
  195. return ret;
  196. }
  197. int bbc_i2c_readb(struct bbc_i2c_client *client, unsigned char *byte, int off)
  198. {
  199. struct bbc_i2c_bus *bp = client->bp;
  200. unsigned char address = client->address, status;
  201. int ret = -1;
  202. if (bp->i2c_bussel_reg != NULL)
  203. writeb(client->bus, bp->i2c_bussel_reg);
  204. writeb(address, bp->i2c_control_regs + 0x1);
  205. writeb(I2C_PCF_START, bp->i2c_control_regs + 0x0);
  206. if (wait_for_pin(bp, &status))
  207. goto out;
  208. writeb(off, bp->i2c_control_regs + 0x1);
  209. if (wait_for_pin(bp, &status) ||
  210.     (status & I2C_PCF_LRB) != 0)
  211. goto out;
  212. writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
  213. address |= 0x1; /* READ */
  214. writeb(address, bp->i2c_control_regs + 0x1);
  215. writeb(I2C_PCF_START, bp->i2c_control_regs + 0x0);
  216. if (wait_for_pin(bp, &status))
  217. goto out;
  218. /* Set PIN back to one so the device sends the first
  219.  * byte.
  220.  */
  221. (void) readb(bp->i2c_control_regs + 0x1);
  222. if (wait_for_pin(bp, &status))
  223. goto out;
  224. writeb(I2C_PCF_ESO | I2C_PCF_ENI, bp->i2c_control_regs + 0x0);
  225. *byte = readb(bp->i2c_control_regs + 0x1);
  226. if (wait_for_pin(bp, &status))
  227. goto out;
  228. ret = 0;
  229. out:
  230. writeb(I2C_PCF_STOP, bp->i2c_control_regs + 0x0);
  231. (void) readb(bp->i2c_control_regs + 0x1);
  232. return ret;
  233. }
  234. int bbc_i2c_write_buf(struct bbc_i2c_client *client,
  235.       char *buf, int len, int off)
  236. {
  237. int ret = 0;
  238. while (len > 0) {
  239. int err = bbc_i2c_writeb(client, *buf, off);
  240. if (err < 0) {
  241. ret = err;
  242. break;
  243. }
  244. len--;
  245. buf++;
  246. off++;
  247. }
  248. return ret;
  249. }
  250. int bbc_i2c_read_buf(struct bbc_i2c_client *client,
  251.      char *buf, int len, int off)
  252. {
  253. int ret = 0;
  254. while (len > 0) {
  255. int err = bbc_i2c_readb(client, buf, off);
  256. if (err < 0) {
  257. ret = err;
  258. break;
  259. }
  260. len--;
  261. buf++;
  262. off++;
  263. }
  264. return ret;
  265. }
  266. EXPORT_SYMBOL(bbc_i2c_getdev);
  267. EXPORT_SYMBOL(bbc_i2c_attach);
  268. EXPORT_SYMBOL(bbc_i2c_detach);
  269. EXPORT_SYMBOL(bbc_i2c_writeb);
  270. EXPORT_SYMBOL(bbc_i2c_readb);
  271. EXPORT_SYMBOL(bbc_i2c_write_buf);
  272. EXPORT_SYMBOL(bbc_i2c_read_buf);
  273. static void bbc_i2c_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  274. {
  275. struct bbc_i2c_bus *bp = dev_id;
  276. /* PIN going from set to clear is the only event which
  277.  * makes the i2c assert an interrupt.
  278.  */
  279. if (bp->waiting &&
  280.     !(readb(bp->i2c_control_regs + 0x0) & I2C_PCF_PIN))
  281. wake_up(&bp->wq);
  282. }
  283. static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
  284. {
  285. writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
  286. writeb(bp->own, bp->i2c_control_regs + 0x1);
  287. writeb(I2C_PCF_PIN | I2C_PCF_ES1, bp->i2c_control_regs + 0x0);
  288. writeb(bp->clock, bp->i2c_control_regs + 0x1);
  289. writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
  290. }
  291. static int __init attach_one_i2c(struct linux_ebus_device *edev, int index)
  292. {
  293. struct bbc_i2c_bus *bp = kmalloc(sizeof(*bp), GFP_KERNEL);
  294. struct linux_ebus_child *echild;
  295. int entry;
  296. if (!bp)
  297. return -ENOMEM;
  298. memset(bp, 0, sizeof(*bp));
  299. bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2);
  300. if (!bp->i2c_control_regs)
  301. goto fail;
  302. if (edev->num_addrs == 2) {
  303. bp->i2c_bussel_reg = ioremap(edev->resource[1].start, 0x1);
  304. if (!bp->i2c_bussel_reg)
  305. goto fail;
  306. }
  307. bp->waiting = 0;
  308. init_waitqueue_head(&bp->wq);
  309. if (request_irq(edev->irqs[0], bbc_i2c_interrupt,
  310. SA_SHIRQ, "bbc_i2c", bp))
  311. goto fail;
  312. bp->index = index;
  313. bp->bus_edev = edev;
  314. spin_lock_init(&bp->lock);
  315. bp->next = all_bbc_i2c;
  316. all_bbc_i2c = bp;
  317. entry = 0;
  318. for (echild = edev->children;
  319.      echild && entry < 8;
  320.      echild = echild->next, entry++) {
  321. bp->devs[entry].device = echild;
  322. bp->devs[entry].client_claimed = 0;
  323. }
  324. writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
  325. bp->own = readb(bp->i2c_control_regs + 0x01);
  326. writeb(I2C_PCF_PIN | I2C_PCF_ES1, bp->i2c_control_regs + 0x0);
  327. bp->clock = readb(bp->i2c_control_regs + 0x01);
  328. printk(KERN_INFO "i2c-%d: Regs at %p, %d devices, own %02x, clock %02x.n",
  329.        bp->index, bp->i2c_control_regs, entry, bp->own, bp->clock);
  330. reset_one_i2c(bp);
  331. return 0;
  332. fail:
  333. if (bp->i2c_bussel_reg)
  334. iounmap(bp->i2c_bussel_reg);
  335. if (bp->i2c_control_regs)
  336. iounmap(bp->i2c_control_regs);
  337. kfree(bp);
  338. return -EINVAL;
  339. }
  340. static int __init bbc_present(void)
  341. {
  342. struct linux_ebus *ebus = NULL;
  343. struct linux_ebus_device *edev = NULL;
  344. for_each_ebus(ebus) {
  345. for_each_ebusdev(edev, ebus) {
  346. if (!strcmp(edev->prom_name, "bbc"))
  347. return 1;
  348. }
  349. }
  350. return 0;
  351. }
  352. extern void bbc_envctrl_init(void);
  353. extern void bbc_envctrl_cleanup(void);
  354. static int __init bbc_i2c_init(void)
  355. {
  356. struct linux_ebus *ebus = NULL;
  357. struct linux_ebus_device *edev = NULL;
  358. int index = 0;
  359. if (tlb_type != cheetah || !bbc_present())
  360. return -ENODEV;
  361. for_each_ebus(ebus) {
  362. for_each_ebusdev(edev, ebus) {
  363. if (!strcmp(edev->prom_name, "i2c")) {
  364. if (!attach_one_i2c(edev, index))
  365. index++;
  366. }
  367. }
  368. }
  369. if (!index)
  370. return -ENODEV;
  371. bbc_envctrl_init();
  372. return 0;
  373. }
  374. static void __exit bbc_i2c_cleanup(void)
  375. {
  376. struct bbc_i2c_bus *bp = all_bbc_i2c;
  377. bbc_envctrl_cleanup();
  378. while (bp != NULL) {
  379. struct bbc_i2c_bus *next = bp->next;
  380. free_irq(bp->bus_edev->irqs[0], bp);
  381. if (bp->i2c_bussel_reg)
  382. iounmap(bp->i2c_bussel_reg);
  383. if (bp->i2c_control_regs)
  384. iounmap(bp->i2c_control_regs);
  385. kfree(bp);
  386. bp = next;
  387. }
  388. all_bbc_i2c = NULL;
  389. }
  390. module_init(bbc_i2c_init);
  391. module_exit(bbc_i2c_cleanup);