88pm860x-i2c.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * I2C driver for Marvell 88PM860x
  4. *
  5. * Copyright (C) 2009 Marvell International Ltd.
  6. *
  7. * Author: Haojian Zhuang <[email protected]>
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/i2c.h>
  12. #include <linux/regmap.h>
  13. #include <linux/mfd/88pm860x.h>
  14. int pm860x_reg_read(struct i2c_client *i2c, int reg)
  15. {
  16. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  17. struct regmap *map = (i2c == chip->client) ? chip->regmap
  18. : chip->regmap_companion;
  19. unsigned int data;
  20. int ret;
  21. ret = regmap_read(map, reg, &data);
  22. if (ret < 0)
  23. return ret;
  24. else
  25. return (int)data;
  26. }
  27. EXPORT_SYMBOL(pm860x_reg_read);
  28. int pm860x_reg_write(struct i2c_client *i2c, int reg,
  29. unsigned char data)
  30. {
  31. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  32. struct regmap *map = (i2c == chip->client) ? chip->regmap
  33. : chip->regmap_companion;
  34. int ret;
  35. ret = regmap_write(map, reg, data);
  36. return ret;
  37. }
  38. EXPORT_SYMBOL(pm860x_reg_write);
  39. int pm860x_bulk_read(struct i2c_client *i2c, int reg,
  40. int count, unsigned char *buf)
  41. {
  42. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  43. struct regmap *map = (i2c == chip->client) ? chip->regmap
  44. : chip->regmap_companion;
  45. int ret;
  46. ret = regmap_raw_read(map, reg, buf, count);
  47. return ret;
  48. }
  49. EXPORT_SYMBOL(pm860x_bulk_read);
  50. int pm860x_bulk_write(struct i2c_client *i2c, int reg,
  51. int count, unsigned char *buf)
  52. {
  53. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  54. struct regmap *map = (i2c == chip->client) ? chip->regmap
  55. : chip->regmap_companion;
  56. int ret;
  57. ret = regmap_raw_write(map, reg, buf, count);
  58. return ret;
  59. }
  60. EXPORT_SYMBOL(pm860x_bulk_write);
  61. int pm860x_set_bits(struct i2c_client *i2c, int reg,
  62. unsigned char mask, unsigned char data)
  63. {
  64. struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  65. struct regmap *map = (i2c == chip->client) ? chip->regmap
  66. : chip->regmap_companion;
  67. int ret;
  68. ret = regmap_update_bits(map, reg, mask, data);
  69. return ret;
  70. }
  71. EXPORT_SYMBOL(pm860x_set_bits);
  72. static int read_device(struct i2c_client *i2c, int reg,
  73. int bytes, void *dest)
  74. {
  75. unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
  76. unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
  77. struct i2c_adapter *adap = i2c->adapter;
  78. struct i2c_msg msg[2] = {
  79. {
  80. .addr = i2c->addr,
  81. .flags = 0,
  82. .len = 1,
  83. .buf = msgbuf0
  84. },
  85. { .addr = i2c->addr,
  86. .flags = I2C_M_RD,
  87. .len = 0,
  88. .buf = msgbuf1
  89. },
  90. };
  91. int num = 1, ret = 0;
  92. if (dest == NULL)
  93. return -EINVAL;
  94. msgbuf0[0] = (unsigned char)reg; /* command */
  95. msg[1].len = bytes;
  96. /* if data needs to read back, num should be 2 */
  97. if (bytes > 0)
  98. num = 2;
  99. ret = adap->algo->master_xfer(adap, msg, num);
  100. memcpy(dest, msgbuf1, bytes);
  101. if (ret < 0)
  102. return ret;
  103. return 0;
  104. }
  105. static int write_device(struct i2c_client *i2c, int reg,
  106. int bytes, void *src)
  107. {
  108. unsigned char buf[2];
  109. struct i2c_adapter *adap = i2c->adapter;
  110. struct i2c_msg msg;
  111. int ret;
  112. buf[0] = (unsigned char)reg;
  113. memcpy(&buf[1], src, bytes);
  114. msg.addr = i2c->addr;
  115. msg.flags = 0;
  116. msg.len = bytes + 1;
  117. msg.buf = buf;
  118. ret = adap->algo->master_xfer(adap, &msg, 1);
  119. if (ret < 0)
  120. return ret;
  121. return 0;
  122. }
  123. int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
  124. unsigned char data)
  125. {
  126. unsigned char zero;
  127. int ret;
  128. i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
  129. read_device(i2c, 0xFA, 0, &zero);
  130. read_device(i2c, 0xFB, 0, &zero);
  131. read_device(i2c, 0xFF, 0, &zero);
  132. ret = write_device(i2c, reg, 1, &data);
  133. read_device(i2c, 0xFE, 0, &zero);
  134. read_device(i2c, 0xFC, 0, &zero);
  135. i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
  136. return ret;
  137. }
  138. EXPORT_SYMBOL(pm860x_page_reg_write);
  139. int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
  140. int count, unsigned char *buf)
  141. {
  142. unsigned char zero = 0;
  143. int ret;
  144. i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
  145. read_device(i2c, 0xfa, 0, &zero);
  146. read_device(i2c, 0xfb, 0, &zero);
  147. read_device(i2c, 0xff, 0, &zero);
  148. ret = read_device(i2c, reg, count, buf);
  149. read_device(i2c, 0xFE, 0, &zero);
  150. read_device(i2c, 0xFC, 0, &zero);
  151. i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
  152. return ret;
  153. }
  154. EXPORT_SYMBOL(pm860x_page_bulk_read);