regmap-mmio.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. * Register map access API - MMIO support
  3. *
  4. * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <linux/clk.h>
  19. #include <linux/err.h>
  20. #include <linux/io.h>
  21. #include <linux/module.h>
  22. #include <linux/regmap.h>
  23. #include <linux/slab.h>
  24. #include "internal.h"
  25. struct regmap_mmio_context {
  26. void __iomem *regs;
  27. unsigned val_bytes;
  28. struct clk *clk;
  29. void (*reg_write)(struct regmap_mmio_context *ctx,
  30. unsigned int reg, unsigned int val);
  31. unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
  32. unsigned int reg);
  33. };
  34. static int regmap_mmio_regbits_check(size_t reg_bits)
  35. {
  36. switch (reg_bits) {
  37. case 8:
  38. case 16:
  39. case 32:
  40. #ifdef CONFIG_64BIT
  41. case 64:
  42. #endif
  43. return 0;
  44. default:
  45. return -EINVAL;
  46. }
  47. }
  48. static int regmap_mmio_get_min_stride(size_t val_bits)
  49. {
  50. int min_stride;
  51. switch (val_bits) {
  52. case 8:
  53. /* The core treats 0 as 1 */
  54. min_stride = 0;
  55. return 0;
  56. case 16:
  57. min_stride = 2;
  58. break;
  59. case 32:
  60. min_stride = 4;
  61. break;
  62. #ifdef CONFIG_64BIT
  63. case 64:
  64. min_stride = 8;
  65. break;
  66. #endif
  67. default:
  68. return -EINVAL;
  69. }
  70. return min_stride;
  71. }
  72. static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
  73. unsigned int reg,
  74. unsigned int val)
  75. {
  76. writeb(val, ctx->regs + reg);
  77. }
  78. static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
  79. unsigned int reg,
  80. unsigned int val)
  81. {
  82. writew(val, ctx->regs + reg);
  83. }
  84. static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
  85. unsigned int reg,
  86. unsigned int val)
  87. {
  88. iowrite16be(val, ctx->regs + reg);
  89. }
  90. static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
  91. unsigned int reg,
  92. unsigned int val)
  93. {
  94. writel(val, ctx->regs + reg);
  95. }
  96. static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
  97. unsigned int reg,
  98. unsigned int val)
  99. {
  100. iowrite32be(val, ctx->regs + reg);
  101. }
  102. #ifdef CONFIG_64BIT
  103. static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
  104. unsigned int reg,
  105. unsigned int val)
  106. {
  107. writeq(val, ctx->regs + reg);
  108. }
  109. #endif
  110. static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
  111. {
  112. struct regmap_mmio_context *ctx = context;
  113. int ret;
  114. if (!IS_ERR(ctx->clk)) {
  115. ret = clk_enable(ctx->clk);
  116. if (ret < 0)
  117. return ret;
  118. }
  119. ctx->reg_write(ctx, reg, val);
  120. if (!IS_ERR(ctx->clk))
  121. clk_disable(ctx->clk);
  122. return 0;
  123. }
  124. static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
  125. unsigned int reg)
  126. {
  127. return readb(ctx->regs + reg);
  128. }
  129. static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
  130. unsigned int reg)
  131. {
  132. return readw(ctx->regs + reg);
  133. }
  134. static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
  135. unsigned int reg)
  136. {
  137. return ioread16be(ctx->regs + reg);
  138. }
  139. static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
  140. unsigned int reg)
  141. {
  142. return readl(ctx->regs + reg);
  143. }
  144. static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
  145. unsigned int reg)
  146. {
  147. return ioread32be(ctx->regs + reg);
  148. }
  149. #ifdef CONFIG_64BIT
  150. static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
  151. unsigned int reg)
  152. {
  153. return readq(ctx->regs + reg);
  154. }
  155. #endif
  156. static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
  157. {
  158. struct regmap_mmio_context *ctx = context;
  159. int ret;
  160. if (!IS_ERR(ctx->clk)) {
  161. ret = clk_enable(ctx->clk);
  162. if (ret < 0)
  163. return ret;
  164. }
  165. *val = ctx->reg_read(ctx, reg);
  166. if (!IS_ERR(ctx->clk))
  167. clk_disable(ctx->clk);
  168. return 0;
  169. }
  170. static void regmap_mmio_free_context(void *context)
  171. {
  172. struct regmap_mmio_context *ctx = context;
  173. if (!IS_ERR(ctx->clk)) {
  174. clk_unprepare(ctx->clk);
  175. clk_put(ctx->clk);
  176. }
  177. kfree(context);
  178. }
  179. static const struct regmap_bus regmap_mmio = {
  180. .fast_io = true,
  181. .reg_write = regmap_mmio_write,
  182. .reg_read = regmap_mmio_read,
  183. .free_context = regmap_mmio_free_context,
  184. .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
  185. };
  186. static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
  187. const char *clk_id,
  188. void __iomem *regs,
  189. const struct regmap_config *config)
  190. {
  191. struct regmap_mmio_context *ctx;
  192. int min_stride;
  193. int ret;
  194. ret = regmap_mmio_regbits_check(config->reg_bits);
  195. if (ret)
  196. return ERR_PTR(ret);
  197. if (config->pad_bits)
  198. return ERR_PTR(-EINVAL);
  199. min_stride = regmap_mmio_get_min_stride(config->val_bits);
  200. if (min_stride < 0)
  201. return ERR_PTR(min_stride);
  202. if (config->reg_stride < min_stride)
  203. return ERR_PTR(-EINVAL);
  204. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  205. if (!ctx)
  206. return ERR_PTR(-ENOMEM);
  207. ctx->regs = regs;
  208. ctx->val_bytes = config->val_bits / 8;
  209. ctx->clk = ERR_PTR(-ENODEV);
  210. switch (regmap_get_val_endian(dev, &regmap_mmio, config)) {
  211. case REGMAP_ENDIAN_DEFAULT:
  212. case REGMAP_ENDIAN_LITTLE:
  213. #ifdef __LITTLE_ENDIAN
  214. case REGMAP_ENDIAN_NATIVE:
  215. #endif
  216. switch (config->val_bits) {
  217. case 8:
  218. ctx->reg_read = regmap_mmio_read8;
  219. ctx->reg_write = regmap_mmio_write8;
  220. break;
  221. case 16:
  222. ctx->reg_read = regmap_mmio_read16le;
  223. ctx->reg_write = regmap_mmio_write16le;
  224. break;
  225. case 32:
  226. ctx->reg_read = regmap_mmio_read32le;
  227. ctx->reg_write = regmap_mmio_write32le;
  228. break;
  229. #ifdef CONFIG_64BIT
  230. case 64:
  231. ctx->reg_read = regmap_mmio_read64le;
  232. ctx->reg_write = regmap_mmio_write64le;
  233. break;
  234. #endif
  235. default:
  236. ret = -EINVAL;
  237. goto err_free;
  238. }
  239. break;
  240. case REGMAP_ENDIAN_BIG:
  241. #ifdef __BIG_ENDIAN
  242. case REGMAP_ENDIAN_NATIVE:
  243. #endif
  244. switch (config->val_bits) {
  245. case 8:
  246. ctx->reg_read = regmap_mmio_read8;
  247. ctx->reg_write = regmap_mmio_write8;
  248. break;
  249. case 16:
  250. ctx->reg_read = regmap_mmio_read16be;
  251. ctx->reg_write = regmap_mmio_write16be;
  252. break;
  253. case 32:
  254. ctx->reg_read = regmap_mmio_read32be;
  255. ctx->reg_write = regmap_mmio_write32be;
  256. break;
  257. default:
  258. ret = -EINVAL;
  259. goto err_free;
  260. }
  261. break;
  262. default:
  263. ret = -EINVAL;
  264. goto err_free;
  265. }
  266. if (clk_id == NULL)
  267. return ctx;
  268. ctx->clk = clk_get(dev, clk_id);
  269. if (IS_ERR(ctx->clk)) {
  270. ret = PTR_ERR(ctx->clk);
  271. goto err_free;
  272. }
  273. ret = clk_prepare(ctx->clk);
  274. if (ret < 0) {
  275. clk_put(ctx->clk);
  276. goto err_free;
  277. }
  278. return ctx;
  279. err_free:
  280. kfree(ctx);
  281. return ERR_PTR(ret);
  282. }
  283. struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
  284. void __iomem *regs,
  285. const struct regmap_config *config,
  286. struct lock_class_key *lock_key,
  287. const char *lock_name)
  288. {
  289. struct regmap_mmio_context *ctx;
  290. ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
  291. if (IS_ERR(ctx))
  292. return ERR_CAST(ctx);
  293. return __regmap_init(dev, &regmap_mmio, ctx, config,
  294. lock_key, lock_name);
  295. }
  296. EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk);
  297. struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
  298. const char *clk_id,
  299. void __iomem *regs,
  300. const struct regmap_config *config,
  301. struct lock_class_key *lock_key,
  302. const char *lock_name)
  303. {
  304. struct regmap_mmio_context *ctx;
  305. ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
  306. if (IS_ERR(ctx))
  307. return ERR_CAST(ctx);
  308. return __devm_regmap_init(dev, &regmap_mmio, ctx, config,
  309. lock_key, lock_name);
  310. }
  311. EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
  312. MODULE_LICENSE("GPL v2");