88pm860x-i2c.c 4.3 KB

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