i2c-sibyte.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright (C) 2004 Steven J. Hill
  3. * Copyright (C) 2001,2002,2003 Broadcom Corporation
  4. * Copyright (C) 1995-2000 Simon G. Vogl
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/module.h>
  22. #include <linux/init.h>
  23. #include <linux/i2c.h>
  24. #include <asm/io.h>
  25. #include <asm/sibyte/sb1250_regs.h>
  26. #include <asm/sibyte/sb1250_smbus.h>
  27. struct i2c_algo_sibyte_data {
  28. void *data; /* private data */
  29. int bus; /* which bus */
  30. void *reg_base; /* CSR base */
  31. };
  32. /* ----- global defines ----------------------------------------------- */
  33. #define SMB_CSR(a,r) ((long)(a->reg_base + r))
  34. /* ----- global variables --------------------------------------------- */
  35. /* module parameters:
  36. */
  37. static int bit_scan; /* have a look at what's hanging 'round */
  38. module_param(bit_scan, int, 0);
  39. MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
  40. static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
  41. unsigned short flags, char read_write,
  42. u8 command, int size, union i2c_smbus_data * data)
  43. {
  44. struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
  45. int data_bytes = 0;
  46. int error;
  47. while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
  48. ;
  49. switch (size) {
  50. case I2C_SMBUS_QUICK:
  51. csr_out32((V_SMB_ADDR(addr) |
  52. (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
  53. V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
  54. break;
  55. case I2C_SMBUS_BYTE:
  56. if (read_write == I2C_SMBUS_READ) {
  57. csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
  58. SMB_CSR(adap, R_SMB_START));
  59. data_bytes = 1;
  60. } else {
  61. csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
  62. csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
  63. SMB_CSR(adap, R_SMB_START));
  64. }
  65. break;
  66. case I2C_SMBUS_BYTE_DATA:
  67. csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
  68. if (read_write == I2C_SMBUS_READ) {
  69. csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
  70. SMB_CSR(adap, R_SMB_START));
  71. data_bytes = 1;
  72. } else {
  73. csr_out32(V_SMB_LB(data->byte),
  74. SMB_CSR(adap, R_SMB_DATA));
  75. csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
  76. SMB_CSR(adap, R_SMB_START));
  77. }
  78. break;
  79. case I2C_SMBUS_WORD_DATA:
  80. csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
  81. if (read_write == I2C_SMBUS_READ) {
  82. csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
  83. SMB_CSR(adap, R_SMB_START));
  84. data_bytes = 2;
  85. } else {
  86. csr_out32(V_SMB_LB(data->word & 0xff),
  87. SMB_CSR(adap, R_SMB_DATA));
  88. csr_out32(V_SMB_MB(data->word >> 8),
  89. SMB_CSR(adap, R_SMB_DATA));
  90. csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
  91. SMB_CSR(adap, R_SMB_START));
  92. }
  93. break;
  94. default:
  95. return -1; /* XXXKW better error code? */
  96. }
  97. while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
  98. ;
  99. error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
  100. if (error & M_SMB_ERROR) {
  101. /* Clear error bit by writing a 1 */
  102. csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
  103. return -1; /* XXXKW better error code? */
  104. }
  105. if (data_bytes == 1)
  106. data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
  107. if (data_bytes == 2)
  108. data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
  109. return 0;
  110. }
  111. static u32 bit_func(struct i2c_adapter *adap)
  112. {
  113. return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
  114. I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
  115. }
  116. /* -----exported algorithm data: ------------------------------------- */
  117. static const struct i2c_algorithm i2c_sibyte_algo = {
  118. .smbus_xfer = smbus_xfer,
  119. .functionality = bit_func,
  120. };
  121. /*
  122. * registering functions to load algorithms at runtime
  123. */
  124. int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
  125. {
  126. int i;
  127. struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
  128. /* register new adapter to i2c module... */
  129. i2c_adap->algo = &i2c_sibyte_algo;
  130. /* Set the frequency to 100 kHz */
  131. csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
  132. csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
  133. /* scan bus */
  134. if (bit_scan) {
  135. union i2c_smbus_data data;
  136. int rc;
  137. printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
  138. i2c_adap->name);
  139. for (i = 0x00; i < 0x7f; i++) {
  140. /* XXXKW is this a realistic probe? */
  141. rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
  142. I2C_SMBUS_BYTE_DATA, &data);
  143. if (!rc) {
  144. printk("(%02x)",i);
  145. } else
  146. printk(".");
  147. }
  148. printk("\n");
  149. }
  150. return i2c_add_adapter(i2c_adap);
  151. }
  152. static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
  153. { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
  154. { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
  155. };
  156. static struct i2c_adapter sibyte_board_adapter[2] = {
  157. {
  158. .owner = THIS_MODULE,
  159. .id = I2C_HW_SIBYTE,
  160. .class = I2C_CLASS_HWMON,
  161. .algo = NULL,
  162. .algo_data = &sibyte_board_data[0],
  163. .name = "SiByte SMBus 0",
  164. },
  165. {
  166. .owner = THIS_MODULE,
  167. .id = I2C_HW_SIBYTE,
  168. .class = I2C_CLASS_HWMON,
  169. .algo = NULL,
  170. .algo_data = &sibyte_board_data[1],
  171. .name = "SiByte SMBus 1",
  172. },
  173. };
  174. static int __init i2c_sibyte_init(void)
  175. {
  176. printk("i2c-swarm.o: i2c SMBus adapter module for SiByte board\n");
  177. if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0)
  178. return -ENODEV;
  179. if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], K_SMB_FREQ_400KHZ) < 0)
  180. return -ENODEV;
  181. return 0;
  182. }
  183. static void __exit i2c_sibyte_exit(void)
  184. {
  185. i2c_del_adapter(&sibyte_board_adapter[0]);
  186. i2c_del_adapter(&sibyte_board_adapter[1]);
  187. }
  188. module_init(i2c_sibyte_init);
  189. module_exit(i2c_sibyte_exit);
  190. MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>");
  191. MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
  192. MODULE_LICENSE("GPL");