88pm860x-i2c.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * I2C driver for Marvell 88PM860x
  3. *
  4. * Copyright (C) 2009 Marvell International Ltd.
  5. * Haojian Zhuang <haojian.zhuang@marvell.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/i2c.h>
  14. #include <linux/regmap.h>
  15. #include <linux/mfd/88pm860x.h>
  16. int pm860x_reg_read(struct i2c_client *i2c, int reg)
  17. {
  18. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  19. struct regmap *map = (i2c == chip->client) ? chip->regmap
  20. : chip->regmap_companion;
  21. unsigned int data;
  22. int ret;
  23. ret = regmap_read(map, reg, &data);
  24. if (ret < 0)
  25. return ret;
  26. else
  27. return (int)data;
  28. }
  29. EXPORT_SYMBOL(pm860x_reg_read);
  30. int pm860x_reg_write(struct i2c_client *i2c, int reg,
  31. unsigned char data)
  32. {
  33. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  34. struct regmap *map = (i2c == chip->client) ? chip->regmap
  35. : chip->regmap_companion;
  36. int ret;
  37. ret = regmap_write(map, reg, data);
  38. return ret;
  39. }
  40. EXPORT_SYMBOL(pm860x_reg_write);
  41. int pm860x_bulk_read(struct i2c_client *i2c, int reg,
  42. int count, unsigned char *buf)
  43. {
  44. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  45. struct regmap *map = (i2c == chip->client) ? chip->regmap
  46. : chip->regmap_companion;
  47. int ret;
  48. ret = regmap_raw_read(map, reg, buf, count);
  49. return ret;
  50. }
  51. EXPORT_SYMBOL(pm860x_bulk_read);
  52. int pm860x_bulk_write(struct i2c_client *i2c, int reg,
  53. int count, unsigned char *buf)
  54. {
  55. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  56. struct regmap *map = (i2c == chip->client) ? chip->regmap
  57. : chip->regmap_companion;
  58. int ret;
  59. ret = regmap_raw_write(map, reg, buf, count);
  60. return ret;
  61. }
  62. EXPORT_SYMBOL(pm860x_bulk_write);
  63. int pm860x_set_bits(struct i2c_client *i2c, int reg,
  64. unsigned char mask, unsigned char data)
  65. {
  66. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  67. struct regmap *map = (i2c == chip->client) ? chip->regmap
  68. : chip->regmap_companion;
  69. int ret;
  70. ret = regmap_update_bits(map, reg, mask, data);
  71. return ret;
  72. }
  73. EXPORT_SYMBOL(pm860x_set_bits);
  74. static int read_device(struct i2c_client *i2c, int reg,
  75. int bytes, void *dest)
  76. {
  77. unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
  78. unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
  79. struct i2c_adapter *adap = i2c->adapter;
  80. struct i2c_msg msg[2] = {
  81. {
  82. .addr = i2c->addr,
  83. .flags = 0,
  84. .len = 1,
  85. .buf = msgbuf0
  86. },
  87. { .addr = i2c->addr,
  88. .flags = I2C_M_RD,
  89. .len = 0,
  90. .buf = msgbuf1
  91. },
  92. };
  93. int num = 1, ret = 0;
  94. if (dest == NULL)
  95. return -EINVAL;
  96. msgbuf0[0] = (unsigned char)reg; /* command */
  97. msg[1].len = bytes;
  98. /* if data needs to read back, num should be 2 */
  99. if (bytes > 0)
  100. num = 2;
  101. ret = adap->algo->master_xfer(adap, msg, num);
  102. memcpy(dest, msgbuf1, bytes);
  103. if (ret < 0)
  104. return ret;
  105. return 0;
  106. }
  107. static int write_device(struct i2c_client *i2c, int reg,
  108. int bytes, void *src)
  109. {
  110. unsigned char buf[bytes + 1];
  111. struct i2c_adapter *adap = i2c->adapter;
  112. struct i2c_msg msg;
  113. int ret;
  114. buf[0] = (unsigned char)reg;
  115. memcpy(&buf[1], src, bytes);
  116. msg.addr = i2c->addr;
  117. msg.flags = 0;
  118. msg.len = bytes + 1;
  119. msg.buf = buf;
  120. ret = adap->algo->master_xfer(adap, &msg, 1);
  121. if (ret < 0)
  122. return ret;
  123. return 0;
  124. }
  125. int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
  126. {
  127. unsigned char zero = 0;
  128. unsigned char data;
  129. int ret;
  130. i2c_lock_adapter(i2c->adapter);
  131. read_device(i2c, 0xFA, 0, &zero);
  132. read_device(i2c, 0xFB, 0, &zero);
  133. read_device(i2c, 0xFF, 0, &zero);
  134. ret = read_device(i2c, reg, 1, &data);
  135. if (ret >= 0)
  136. ret = (int)data;
  137. read_device(i2c, 0xFE, 0, &zero);
  138. read_device(i2c, 0xFC, 0, &zero);
  139. i2c_unlock_adapter(i2c->adapter);
  140. return ret;
  141. }
  142. EXPORT_SYMBOL(pm860x_page_reg_read);
  143. int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
  144. unsigned char data)
  145. {
  146. unsigned char zero;
  147. int ret;
  148. i2c_lock_adapter(i2c->adapter);
  149. read_device(i2c, 0xFA, 0, &zero);
  150. read_device(i2c, 0xFB, 0, &zero);
  151. read_device(i2c, 0xFF, 0, &zero);
  152. ret = write_device(i2c, reg, 1, &data);
  153. read_device(i2c, 0xFE, 0, &zero);
  154. read_device(i2c, 0xFC, 0, &zero);
  155. i2c_unlock_adapter(i2c->adapter);
  156. return ret;
  157. }
  158. EXPORT_SYMBOL(pm860x_page_reg_write);
  159. int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
  160. int count, unsigned char *buf)
  161. {
  162. unsigned char zero = 0;
  163. int ret;
  164. i2c_lock_adapter(i2c->adapter);
  165. read_device(i2c, 0xfa, 0, &zero);
  166. read_device(i2c, 0xfb, 0, &zero);
  167. read_device(i2c, 0xff, 0, &zero);
  168. ret = read_device(i2c, reg, count, buf);
  169. read_device(i2c, 0xFE, 0, &zero);
  170. read_device(i2c, 0xFC, 0, &zero);
  171. i2c_unlock_adapter(i2c->adapter);
  172. return ret;
  173. }
  174. EXPORT_SYMBOL(pm860x_page_bulk_read);
  175. int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
  176. int count, unsigned char *buf)
  177. {
  178. unsigned char zero = 0;
  179. int ret;
  180. i2c_lock_adapter(i2c->adapter);
  181. read_device(i2c, 0xFA, 0, &zero);
  182. read_device(i2c, 0xFB, 0, &zero);
  183. read_device(i2c, 0xFF, 0, &zero);
  184. ret = write_device(i2c, reg, count, buf);
  185. read_device(i2c, 0xFE, 0, &zero);
  186. read_device(i2c, 0xFC, 0, &zero);
  187. i2c_unlock_adapter(i2c->adapter);
  188. i2c_unlock_adapter(i2c->adapter);
  189. return ret;
  190. }
  191. EXPORT_SYMBOL(pm860x_page_bulk_write);
  192. int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
  193. unsigned char mask, unsigned char data)
  194. {
  195. unsigned char zero;
  196. unsigned char value;
  197. int ret;
  198. i2c_lock_adapter(i2c->adapter);
  199. read_device(i2c, 0xFA, 0, &zero);
  200. read_device(i2c, 0xFB, 0, &zero);
  201. read_device(i2c, 0xFF, 0, &zero);
  202. ret = read_device(i2c, reg, 1, &value);
  203. if (ret < 0)
  204. goto out;
  205. value &= ~mask;
  206. value |= data;
  207. ret = write_device(i2c, reg, 1, &value);
  208. out:
  209. read_device(i2c, 0xFE, 0, &zero);
  210. read_device(i2c, 0xFC, 0, &zero);
  211. i2c_unlock_adapter(i2c->adapter);
  212. return ret;
  213. }
  214. EXPORT_SYMBOL(pm860x_page_set_bits);