regmap-i2c.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 <linux/init.h>
  16. static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
  17. {
  18. struct i2c_client *i2c = to_i2c_client(dev);
  19. int ret;
  20. ret = i2c_master_send(i2c, data, count);
  21. if (ret == count)
  22. return 0;
  23. else if (ret < 0)
  24. return ret;
  25. else
  26. return -EIO;
  27. }
  28. static int regmap_i2c_gather_write(struct device *dev,
  29. const void *reg, size_t reg_size,
  30. const void *val, size_t val_size)
  31. {
  32. struct i2c_client *i2c = to_i2c_client(dev);
  33. struct i2c_msg xfer[2];
  34. int ret;
  35. /* If the I2C controller can't do a gather tell the core, it
  36. * will substitute in a linear write for us.
  37. */
  38. if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
  39. return -ENOTSUPP;
  40. xfer[0].addr = i2c->addr;
  41. xfer[0].flags = 0;
  42. xfer[0].len = reg_size;
  43. xfer[0].buf = (void *)reg;
  44. xfer[1].addr = i2c->addr;
  45. xfer[1].flags = I2C_M_NOSTART;
  46. xfer[1].len = val_size;
  47. xfer[1].buf = (void *)val;
  48. ret = i2c_transfer(i2c->adapter, xfer, 2);
  49. if (ret == 2)
  50. return 0;
  51. if (ret < 0)
  52. return ret;
  53. else
  54. return -EIO;
  55. }
  56. static int regmap_i2c_read(struct device *dev,
  57. const void *reg, size_t reg_size,
  58. void *val, size_t val_size)
  59. {
  60. struct i2c_client *i2c = to_i2c_client(dev);
  61. struct i2c_msg xfer[2];
  62. int ret;
  63. xfer[0].addr = i2c->addr;
  64. xfer[0].flags = 0;
  65. xfer[0].len = reg_size;
  66. xfer[0].buf = (void *)reg;
  67. xfer[1].addr = i2c->addr;
  68. xfer[1].flags = I2C_M_RD;
  69. xfer[1].len = val_size;
  70. xfer[1].buf = val;
  71. ret = i2c_transfer(i2c->adapter, xfer, 2);
  72. if (ret == 2)
  73. return 0;
  74. else if (ret < 0)
  75. return ret;
  76. else
  77. return -EIO;
  78. }
  79. static struct regmap_bus regmap_i2c = {
  80. .type = &i2c_bus_type,
  81. .write = regmap_i2c_write,
  82. .gather_write = regmap_i2c_gather_write,
  83. .read = regmap_i2c_read,
  84. .owner = THIS_MODULE,
  85. };
  86. /**
  87. * regmap_init_i2c(): Initialise register map
  88. *
  89. * @i2c: Device that will be interacted with
  90. * @config: Configuration for register map
  91. *
  92. * The return value will be an ERR_PTR() on error or a valid pointer to
  93. * a struct regmap.
  94. */
  95. struct regmap *regmap_init_i2c(struct i2c_client *i2c,
  96. const struct regmap_config *config)
  97. {
  98. return regmap_init(&i2c->dev, &regmap_i2c, config);
  99. }
  100. EXPORT_SYMBOL_GPL(regmap_init_i2c);