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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* ------------------------------------------------------------------------- */
  2. /* i2c-philips-par.c i2c-hw access for philips style parallel port adapters  */
  3. /* ------------------------------------------------------------------------- */
  4. /*   Copyright (C) 1995-2000 Simon G. Vogl
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.     You should have received a copy of the GNU General Public License
  14.     along with this program; if not, write to the Free Software
  15.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.      */
  16. /* ------------------------------------------------------------------------- */ 
  17. /* With some changes from Ky鰏ti M鋖kki <kmalkki@cc.hut.fi> and even
  18.    Frodo Looijaard <frodol@dds.nl> */
  19. /* $Id: i2c-philips-par.c,v 1.18 2000/07/06 19:21:49 frodo Exp $ */
  20. #include <linux/kernel.h>
  21. #include <linux/ioport.h>
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/stddef.h>
  25. #include <linux/parport.h>
  26. #include <linux/i2c.h>
  27. #include <linux/i2c-algo-bit.h>
  28. #ifndef __exit
  29. #define __exit __init
  30. #endif
  31. static int type;
  32. struct i2c_par
  33. {
  34. struct pardevice *pdev;
  35. struct i2c_adapter adapter;
  36. struct i2c_algo_bit_data bit_lp_data;
  37. struct i2c_par *next;
  38. };
  39. static struct i2c_par *adapter_list;
  40. /* ----- global defines ----------------------------------------------- */
  41. #define DEB(x) /* should be reasonable open, close &c.  */
  42. #define DEB2(x)  /* low level debugging - very slow  */
  43. #define DEBE(x) x /* error messages  */
  44. /* ----- printer port defines ------------------------------------------*/
  45. /* Pin Port  Inverted name */
  46. #define I2C_ON 0x20 /* 12 status N paper */
  47. /* ... only for phil. not used  */
  48. #define I2C_SDA 0x80 /*  9 data   N data7 */
  49. #define I2C_SCL 0x08 /* 17 ctrl   N dsel */
  50. #define I2C_SDAIN 0x80 /* 11 stat   Y busy */
  51. #define I2C_SCLIN 0x08 /* 15 stat   Y enable */
  52. #define I2C_DMASK 0x7f
  53. #define I2C_CMASK 0xf7
  54. /* ----- local functions ---------------------------------------------- */
  55. static void bit_lp_setscl(void *data, int state)
  56. {
  57. /*be cautious about state of the control register - 
  58. touch only the one bit needed*/
  59. if (state) {
  60. parport_write_control((struct parport *) data,
  61.       parport_read_control((struct parport *) data)|I2C_SCL);
  62. } else {
  63. parport_write_control((struct parport *) data,
  64.       parport_read_control((struct parport *) data)&I2C_CMASK);
  65. }
  66. }
  67. static void bit_lp_setsda(void *data, int state)
  68. {
  69. if (state) {
  70. parport_write_data((struct parport *) data, I2C_DMASK);
  71. } else {
  72. parport_write_data((struct parport *) data, I2C_SDA);
  73. }
  74. }
  75. static int bit_lp_getscl(void *data)
  76. {
  77. return parport_read_status((struct parport *) data) & I2C_SCLIN;
  78. }
  79. static int bit_lp_getsda(void *data)
  80. {
  81. return parport_read_status((struct parport *) data) & I2C_SDAIN;
  82. }
  83. static void bit_lp_setscl2(void *data, int state)
  84. {
  85. if (state) {
  86. parport_write_data((struct parport *) data,
  87.       parport_read_data((struct parport *) data)|0x1);
  88. } else {
  89. parport_write_data((struct parport *) data,
  90.       parport_read_data((struct parport *) data)&0xfe);
  91. }
  92. }
  93. static void bit_lp_setsda2(void *data, int state)
  94. {
  95. if (state) {
  96. parport_write_data((struct parport *) data,
  97.       parport_read_data((struct parport *) data)|0x2);
  98. } else {
  99. parport_write_data((struct parport *) data,
  100.       parport_read_data((struct parport *) data)&0xfd);
  101. }
  102. }
  103. static int bit_lp_getsda2(void *data)
  104. {
  105. return (parport_read_status((struct parport *) data) & 
  106.              PARPORT_STATUS_BUSY) ? 0 : 1;
  107. }
  108. static int bit_lp_reg(struct i2c_client *client)
  109. {
  110. return 0;
  111. }
  112. static int bit_lp_unreg(struct i2c_client *client)
  113. {
  114. return 0;
  115. }
  116. static void bit_lp_inc_use(struct i2c_adapter *adap)
  117. {
  118. MOD_INC_USE_COUNT;
  119. }
  120. static void bit_lp_dec_use(struct i2c_adapter *adap)
  121. {
  122. MOD_DEC_USE_COUNT;
  123. }
  124. /* ------------------------------------------------------------------------
  125.  * Encapsulate the above functions in the correct operations structure.
  126.  * This is only done when more than one hardware adapter is supported.
  127.  */
  128.  
  129. static struct i2c_algo_bit_data bit_lp_data = {
  130. NULL,
  131. bit_lp_setsda,
  132. bit_lp_setscl,
  133. bit_lp_getsda,
  134. bit_lp_getscl,
  135. 80, 80, 100, /* waits, timeout */
  136. }; 
  137. static struct i2c_algo_bit_data bit_lp_data2 = {
  138. NULL,
  139. bit_lp_setsda2,
  140. bit_lp_setscl2,
  141. bit_lp_getsda2,
  142. NULL,
  143. 80, 80, 100, /* waits, timeout */
  144. }; 
  145. static struct i2c_adapter bit_lp_ops = {
  146. "Philips Parallel port adapter",
  147. I2C_HW_B_LP,
  148. NULL,
  149. NULL,
  150. bit_lp_inc_use,
  151. bit_lp_dec_use,
  152. bit_lp_reg,
  153. bit_lp_unreg,
  154. };
  155. static void i2c_parport_attach (struct parport *port)
  156. {
  157. struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par),
  158.   GFP_KERNEL);
  159. if (!adapter) {
  160. printk("i2c-philips-par: Unable to malloc.n");
  161. return;
  162. }
  163. printk("i2c-philips-par.o: attaching to %sn", port->name);
  164. adapter->pdev = parport_register_device(port, "i2c-philips-par",
  165. NULL, NULL, NULL, 
  166. PARPORT_FLAG_EXCL,
  167. NULL);
  168. if (!adapter->pdev) {
  169. printk("i2c-philips-par: Unable to register with parport.n");
  170. return;
  171. }
  172. adapter->adapter = bit_lp_ops;
  173. adapter->adapter.algo_data = &adapter->bit_lp_data;
  174. adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data;
  175. adapter->bit_lp_data.data = port;
  176. /* reset hardware to sane state */
  177. parport_claim_or_block(adapter->pdev);
  178. bit_lp_setsda(port, 1);
  179. bit_lp_setscl(port, 1);
  180. parport_release(adapter->pdev);
  181. if (i2c_bit_add_bus(&adapter->adapter) < 0)
  182. {
  183. printk("i2c-philips-par: Unable to register with I2C.n");
  184. parport_unregister_device(adapter->pdev);
  185. kfree(adapter);
  186. return; /* No good */
  187. }
  188. adapter->next = adapter_list;
  189. adapter_list = adapter;
  190. }
  191. static void i2c_parport_detach (struct parport *port)
  192. {
  193. struct i2c_par *adapter, *prev = NULL;
  194. for (adapter = adapter_list; adapter; adapter = adapter->next)
  195. {
  196. if (adapter->pdev->port == port)
  197. {
  198. parport_unregister_device(adapter->pdev);
  199. i2c_bit_del_bus(&adapter->adapter);
  200. if (prev)
  201. prev->next = adapter->next;
  202. else
  203. adapter_list = adapter->next;
  204. kfree(adapter);
  205. return;
  206. }
  207. prev = adapter;
  208. }
  209. }
  210. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
  211. static struct parport_driver i2c_driver = {
  212. "i2c-philips-par",
  213. i2c_parport_attach,
  214. i2c_parport_detach,
  215. NULL
  216. };
  217. #endif
  218. static int __init i2c_bitlp_init(void)
  219. {
  220. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,4)
  221. struct parport *port;
  222. #endif
  223. printk("i2c-philips-par.o: i2c Philips parallel port adapter modulen");
  224. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
  225. parport_register_driver(&i2c_driver);
  226. #else
  227. for (port = parport_enumerate(); port; port=port->next)
  228. i2c_parport_attach(port);
  229. #endif
  230. return 0;
  231. }
  232. static void __exit i2c_bitlp_exit(void)
  233. {
  234. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
  235. parport_unregister_driver(&i2c_driver);
  236. #else
  237. struct parport *port;
  238. for (port = parport_enumerate(); port; port=port->next)
  239. i2c_parport_detach(port);
  240. #endif
  241. }
  242. EXPORT_NO_SYMBOLS;
  243. MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  244. MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter");
  245. MODULE_LICENSE("GPL");
  246. MODULE_PARM(type, "i");
  247. module_init(i2c_bitlp_init);
  248. module_exit(i2c_bitlp_exit);