regmap-i2c.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Register map access API - I2C support
  3. *
  4. * Copyright 2011 Wolfson Microelectronics plc
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/regmap.h>
  13. #include <linux/i2c.h>
  14. #include <linux/module.h>
  15. #include "internal.h"
  16. static int regmap_smbus_byte_reg_read(void *context, unsigned int reg,
  17. unsigned int *val)
  18. {
  19. struct device *dev = context;
  20. struct i2c_client *i2c = to_i2c_client(dev);
  21. int ret;
  22. if (reg > 0xff)
  23. return -EINVAL;
  24. ret = i2c_smbus_read_byte_data(i2c, reg);
  25. if (ret < 0)
  26. return ret;
  27. *val = ret;
  28. return 0;
  29. }
  30. static int regmap_smbus_byte_reg_write(void *context, unsigned int reg,
  31. unsigned int val)
  32. {
  33. struct device *dev = context;
  34. struct i2c_client *i2c = to_i2c_client(dev);
  35. if (val > 0xff || reg > 0xff)
  36. return -EINVAL;
  37. return i2c_smbus_write_byte_data(i2c, reg, val);
  38. }
  39. static struct regmap_bus regmap_smbus_byte = {
  40. .reg_write = regmap_smbus_byte_reg_write,
  41. .reg_read = regmap_smbus_byte_reg_read,
  42. };
  43. static int regmap_smbus_word_reg_read(void *context, unsigned int reg,
  44. unsigned int *val)
  45. {
  46. struct device *dev = context;
  47. struct i2c_client *i2c = to_i2c_client(dev);
  48. int ret;
  49. if (reg > 0xff)
  50. return -EINVAL;
  51. ret = i2c_smbus_read_word_data(i2c, reg);
  52. if (ret < 0)
  53. return ret;
  54. *val = ret;
  55. return 0;
  56. }
  57. static int regmap_smbus_word_reg_write(void *context, unsigned int reg,
  58. unsigned int val)
  59. {
  60. struct device *dev = context;
  61. struct i2c_client *i2c = to_i2c_client(dev);
  62. if (val > 0xffff || reg > 0xff)
  63. return -EINVAL;
  64. return i2c_smbus_write_word_data(i2c, reg, val);
  65. }
  66. static struct regmap_bus regmap_smbus_word = {
  67. .reg_write = regmap_smbus_word_reg_write,
  68. .reg_read = regmap_smbus_word_reg_read,
  69. };
  70. static int regmap_smbus_word_read_swapped(void *context, unsigned int reg,
  71. unsigned int *val)
  72. {
  73. struct device *dev = context;
  74. struct i2c_client *i2c = to_i2c_client(dev);
  75. int ret;
  76. if (reg > 0xff)
  77. return -EINVAL;
  78. ret = i2c_smbus_read_word_swapped(i2c, reg);
  79. if (ret < 0)
  80. return ret;
  81. *val = ret;
  82. return 0;
  83. }
  84. static int regmap_smbus_word_write_swapped(void *context, unsigned int reg,
  85. unsigned int val)
  86. {
  87. struct device *dev = context;
  88. struct i2c_client *i2c = to_i2c_client(dev);
  89. if (val > 0xffff || reg > 0xff)
  90. return -EINVAL;
  91. return i2c_smbus_write_word_swapped(i2c, reg, val);
  92. }
  93. static struct regmap_bus regmap_smbus_word_swapped = {
  94. .reg_write = regmap_smbus_word_write_swapped,
  95. .reg_read = regmap_smbus_word_read_swapped,
  96. };
  97. static int regmap_i2c_write(void *context, const void *data, size_t count)
  98. {
  99. struct device *dev = context;
  100. struct i2c_client *i2c = to_i2c_client(dev);
  101. int ret;
  102. ret = i2c_master_send(i2c, data, count);
  103. if (ret == count)
  104. return 0;
  105. else if (ret < 0)
  106. return ret;
  107. else
  108. return -EIO;
  109. }
  110. static int regmap_i2c_gather_write(void *context,
  111. const void *reg, size_t reg_size,
  112. const void *val, size_t val_size)
  113. {
  114. struct device *dev = context;
  115. struct i2c_client *i2c = to_i2c_client(dev);
  116. struct i2c_msg xfer[2];
  117. int ret;
  118. /* If the I2C controller can't do a gather tell the core, it
  119. * will substitute in a linear write for us.
  120. */
  121. if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_NOSTART))
  122. return -ENOTSUPP;
  123. xfer[0].addr = i2c->addr;
  124. xfer[0].flags = 0;
  125. xfer[0].len = reg_size;
  126. xfer[0].buf = (void *)reg;
  127. xfer[1].addr = i2c->addr;
  128. xfer[1].flags = I2C_M_NOSTART;
  129. xfer[1].len = val_size;
  130. xfer[1].buf = (void *)val;
  131. ret = i2c_transfer(i2c->adapter, xfer, 2);
  132. if (ret == 2)
  133. return 0;
  134. if (ret < 0)
  135. return ret;
  136. else
  137. return -EIO;
  138. }
  139. static int regmap_i2c_read(void *context,
  140. const void *reg, size_t reg_size,
  141. void *val, size_t val_size)
  142. {
  143. struct device *dev = context;
  144. struct i2c_client *i2c = to_i2c_client(dev);
  145. struct i2c_msg xfer[2];
  146. int ret;
  147. xfer[0].addr = i2c->addr;
  148. xfer[0].flags = 0;
  149. xfer[0].len = reg_size;
  150. xfer[0].buf = (void *)reg;
  151. xfer[1].addr = i2c->addr;
  152. xfer[1].flags = I2C_M_RD;
  153. xfer[1].len = val_size;
  154. xfer[1].buf = val;
  155. ret = i2c_transfer(i2c->adapter, xfer, 2);
  156. if (ret == 2)
  157. return 0;
  158. else if (ret < 0)
  159. return ret;
  160. else
  161. return -EIO;
  162. }
  163. static struct regmap_bus regmap_i2c = {
  164. .write = regmap_i2c_write,
  165. .gather_write = regmap_i2c_gather_write,
  166. .read = regmap_i2c_read,
  167. .reg_format_endian_default = REGMAP_ENDIAN_BIG,
  168. .val_format_endian_default = REGMAP_ENDIAN_BIG,
  169. };
  170. static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
  171. const struct regmap_config *config)
  172. {
  173. if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
  174. return &regmap_i2c;
  175. else if (config->val_bits == 16 && config->reg_bits == 8 &&
  176. i2c_check_functionality(i2c->adapter,
  177. I2C_FUNC_SMBUS_WORD_DATA))
  178. switch (regmap_get_val_endian(&i2c->dev, NULL, config)) {
  179. case REGMAP_ENDIAN_LITTLE:
  180. return &regmap_smbus_word;
  181. case REGMAP_ENDIAN_BIG:
  182. return &regmap_smbus_word_swapped;
  183. default: /* everything else is not supported */
  184. break;
  185. }
  186. else if (config->val_bits == 8 && config->reg_bits == 8 &&
  187. i2c_check_functionality(i2c->adapter,
  188. I2C_FUNC_SMBUS_BYTE_DATA))
  189. return &regmap_smbus_byte;
  190. return ERR_PTR(-ENOTSUPP);
  191. }
  192. /**
  193. * regmap_init_i2c(): Initialise register map
  194. *
  195. * @i2c: Device that will be interacted with
  196. * @config: Configuration for register map
  197. *
  198. * The return value will be an ERR_PTR() on error or a valid pointer to
  199. * a struct regmap.
  200. */
  201. struct regmap *regmap_init_i2c(struct i2c_client *i2c,
  202. const struct regmap_config *config)
  203. {
  204. const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
  205. if (IS_ERR(bus))
  206. return ERR_CAST(bus);
  207. return regmap_init(&i2c->dev, bus, &i2c->dev, config);
  208. }
  209. EXPORT_SYMBOL_GPL(regmap_init_i2c);
  210. /**
  211. * devm_regmap_init_i2c(): Initialise managed register map
  212. *
  213. * @i2c: Device that will be interacted with
  214. * @config: Configuration for register map
  215. *
  216. * The return value will be an ERR_PTR() on error or a valid pointer
  217. * to a struct regmap. The regmap will be automatically freed by the
  218. * device management code.
  219. */
  220. struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
  221. const struct regmap_config *config)
  222. {
  223. const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
  224. if (IS_ERR(bus))
  225. return ERR_CAST(bus);
  226. return devm_regmap_init(&i2c->dev, bus, &i2c->dev, config);
  227. }
  228. EXPORT_SYMBOL_GPL(devm_regmap_init_i2c);
  229. MODULE_LICENSE("GPL");