regmap-fsi.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Register map access API - FSI support
  4. //
  5. // Copyright 2022 IBM Corp
  6. //
  7. // Author: Eddie James <eajames@linux.ibm.com>
  8. #include <linux/fsi.h>
  9. #include <linux/module.h>
  10. #include <linux/regmap.h>
  11. #include "internal.h"
  12. static int regmap_fsi32_reg_read(void *context, unsigned int reg, unsigned int *val)
  13. {
  14. u32 v;
  15. int ret;
  16. ret = fsi_slave_read(context, reg, &v, sizeof(v));
  17. if (ret)
  18. return ret;
  19. *val = v;
  20. return 0;
  21. }
  22. static int regmap_fsi32_reg_write(void *context, unsigned int reg, unsigned int val)
  23. {
  24. u32 v = val;
  25. return fsi_slave_write(context, reg, &v, sizeof(v));
  26. }
  27. static const struct regmap_bus regmap_fsi32 = {
  28. .reg_write = regmap_fsi32_reg_write,
  29. .reg_read = regmap_fsi32_reg_read,
  30. };
  31. static int regmap_fsi32le_reg_read(void *context, unsigned int reg, unsigned int *val)
  32. {
  33. __be32 v;
  34. int ret;
  35. ret = fsi_slave_read(context, reg, &v, sizeof(v));
  36. if (ret)
  37. return ret;
  38. *val = be32_to_cpu(v);
  39. return 0;
  40. }
  41. static int regmap_fsi32le_reg_write(void *context, unsigned int reg, unsigned int val)
  42. {
  43. __be32 v = cpu_to_be32(val);
  44. return fsi_slave_write(context, reg, &v, sizeof(v));
  45. }
  46. static const struct regmap_bus regmap_fsi32le = {
  47. .reg_write = regmap_fsi32le_reg_write,
  48. .reg_read = regmap_fsi32le_reg_read,
  49. };
  50. static int regmap_fsi16_reg_read(void *context, unsigned int reg, unsigned int *val)
  51. {
  52. u16 v;
  53. int ret;
  54. ret = fsi_slave_read(context, reg, &v, sizeof(v));
  55. if (ret)
  56. return ret;
  57. *val = v;
  58. return 0;
  59. }
  60. static int regmap_fsi16_reg_write(void *context, unsigned int reg, unsigned int val)
  61. {
  62. u16 v;
  63. if (val > 0xffff)
  64. return -EINVAL;
  65. v = val;
  66. return fsi_slave_write(context, reg, &v, sizeof(v));
  67. }
  68. static const struct regmap_bus regmap_fsi16 = {
  69. .reg_write = regmap_fsi16_reg_write,
  70. .reg_read = regmap_fsi16_reg_read,
  71. };
  72. static int regmap_fsi16le_reg_read(void *context, unsigned int reg, unsigned int *val)
  73. {
  74. __be16 v;
  75. int ret;
  76. ret = fsi_slave_read(context, reg, &v, sizeof(v));
  77. if (ret)
  78. return ret;
  79. *val = be16_to_cpu(v);
  80. return 0;
  81. }
  82. static int regmap_fsi16le_reg_write(void *context, unsigned int reg, unsigned int val)
  83. {
  84. __be16 v;
  85. if (val > 0xffff)
  86. return -EINVAL;
  87. v = cpu_to_be16(val);
  88. return fsi_slave_write(context, reg, &v, sizeof(v));
  89. }
  90. static const struct regmap_bus regmap_fsi16le = {
  91. .reg_write = regmap_fsi16le_reg_write,
  92. .reg_read = regmap_fsi16le_reg_read,
  93. };
  94. static int regmap_fsi8_reg_read(void *context, unsigned int reg, unsigned int *val)
  95. {
  96. u8 v;
  97. int ret;
  98. ret = fsi_slave_read(context, reg, &v, sizeof(v));
  99. if (ret)
  100. return ret;
  101. *val = v;
  102. return 0;
  103. }
  104. static int regmap_fsi8_reg_write(void *context, unsigned int reg, unsigned int val)
  105. {
  106. u8 v;
  107. if (val > 0xff)
  108. return -EINVAL;
  109. v = val;
  110. return fsi_slave_write(context, reg, &v, sizeof(v));
  111. }
  112. static const struct regmap_bus regmap_fsi8 = {
  113. .reg_write = regmap_fsi8_reg_write,
  114. .reg_read = regmap_fsi8_reg_read,
  115. };
  116. static const struct regmap_bus *regmap_get_fsi_bus(struct fsi_device *fsi_dev,
  117. const struct regmap_config *config)
  118. {
  119. const struct regmap_bus *bus = NULL;
  120. if (config->reg_bits == 8 || config->reg_bits == 16 || config->reg_bits == 32) {
  121. switch (config->val_bits) {
  122. case 8:
  123. bus = &regmap_fsi8;
  124. break;
  125. case 16:
  126. switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) {
  127. case REGMAP_ENDIAN_LITTLE:
  128. #ifdef __LITTLE_ENDIAN
  129. case REGMAP_ENDIAN_NATIVE:
  130. #endif
  131. bus = &regmap_fsi16le;
  132. break;
  133. case REGMAP_ENDIAN_DEFAULT:
  134. case REGMAP_ENDIAN_BIG:
  135. #ifdef __BIG_ENDIAN
  136. case REGMAP_ENDIAN_NATIVE:
  137. #endif
  138. bus = &regmap_fsi16;
  139. break;
  140. default:
  141. break;
  142. }
  143. break;
  144. case 32:
  145. switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) {
  146. case REGMAP_ENDIAN_LITTLE:
  147. #ifdef __LITTLE_ENDIAN
  148. case REGMAP_ENDIAN_NATIVE:
  149. #endif
  150. bus = &regmap_fsi32le;
  151. break;
  152. case REGMAP_ENDIAN_DEFAULT:
  153. case REGMAP_ENDIAN_BIG:
  154. #ifdef __BIG_ENDIAN
  155. case REGMAP_ENDIAN_NATIVE:
  156. #endif
  157. bus = &regmap_fsi32;
  158. break;
  159. default:
  160. break;
  161. }
  162. break;
  163. }
  164. }
  165. return bus ?: ERR_PTR(-EOPNOTSUPP);
  166. }
  167. struct regmap *__regmap_init_fsi(struct fsi_device *fsi_dev, const struct regmap_config *config,
  168. struct lock_class_key *lock_key, const char *lock_name)
  169. {
  170. const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config);
  171. if (IS_ERR(bus))
  172. return ERR_CAST(bus);
  173. return __regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name);
  174. }
  175. EXPORT_SYMBOL_GPL(__regmap_init_fsi);
  176. struct regmap *__devm_regmap_init_fsi(struct fsi_device *fsi_dev,
  177. const struct regmap_config *config,
  178. struct lock_class_key *lock_key, const char *lock_name)
  179. {
  180. const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config);
  181. if (IS_ERR(bus))
  182. return ERR_CAST(bus);
  183. return __devm_regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name);
  184. }
  185. EXPORT_SYMBOL_GPL(__devm_regmap_init_fsi);
  186. MODULE_LICENSE("GPL");