regmap-mmio.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Register map access API - MMIO support
  4. //
  5. // Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
  6. #include <linux/clk.h>
  7. #include <linux/err.h>
  8. #include <linux/io.h>
  9. #include <linux/module.h>
  10. #include <linux/regmap.h>
  11. #include <linux/slab.h>
  12. #include <linux/swab.h>
  13. #include "internal.h"
  14. struct regmap_mmio_context {
  15. void __iomem *regs;
  16. unsigned int val_bytes;
  17. bool big_endian;
  18. bool attached_clk;
  19. struct clk *clk;
  20. void (*reg_write)(struct regmap_mmio_context *ctx,
  21. unsigned int reg, unsigned int val);
  22. unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
  23. unsigned int reg);
  24. };
  25. static int regmap_mmio_regbits_check(size_t reg_bits)
  26. {
  27. switch (reg_bits) {
  28. case 8:
  29. case 16:
  30. case 32:
  31. return 0;
  32. default:
  33. return -EINVAL;
  34. }
  35. }
  36. static int regmap_mmio_get_min_stride(size_t val_bits)
  37. {
  38. int min_stride;
  39. switch (val_bits) {
  40. case 8:
  41. /* The core treats 0 as 1 */
  42. min_stride = 0;
  43. break;
  44. case 16:
  45. min_stride = 2;
  46. break;
  47. case 32:
  48. min_stride = 4;
  49. break;
  50. default:
  51. return -EINVAL;
  52. }
  53. return min_stride;
  54. }
  55. static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
  56. unsigned int reg,
  57. unsigned int val)
  58. {
  59. writeb(val, ctx->regs + reg);
  60. }
  61. static void regmap_mmio_write8_relaxed(struct regmap_mmio_context *ctx,
  62. unsigned int reg,
  63. unsigned int val)
  64. {
  65. writeb_relaxed(val, ctx->regs + reg);
  66. }
  67. static void regmap_mmio_iowrite8(struct regmap_mmio_context *ctx,
  68. unsigned int reg, unsigned int val)
  69. {
  70. iowrite8(val, ctx->regs + reg);
  71. }
  72. static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
  73. unsigned int reg,
  74. unsigned int val)
  75. {
  76. writew(val, ctx->regs + reg);
  77. }
  78. static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context *ctx,
  79. unsigned int reg,
  80. unsigned int val)
  81. {
  82. writew_relaxed(val, ctx->regs + reg);
  83. }
  84. static void regmap_mmio_iowrite16le(struct regmap_mmio_context *ctx,
  85. unsigned int reg, unsigned int val)
  86. {
  87. iowrite16(val, ctx->regs + reg);
  88. }
  89. static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
  90. unsigned int reg,
  91. unsigned int val)
  92. {
  93. writew(swab16(val), ctx->regs + reg);
  94. }
  95. static void regmap_mmio_iowrite16be(struct regmap_mmio_context *ctx,
  96. unsigned int reg, unsigned int val)
  97. {
  98. iowrite16be(val, ctx->regs + reg);
  99. }
  100. static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
  101. unsigned int reg,
  102. unsigned int val)
  103. {
  104. writel(val, ctx->regs + reg);
  105. }
  106. static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context *ctx,
  107. unsigned int reg,
  108. unsigned int val)
  109. {
  110. writel_relaxed(val, ctx->regs + reg);
  111. }
  112. static void regmap_mmio_iowrite32le(struct regmap_mmio_context *ctx,
  113. unsigned int reg, unsigned int val)
  114. {
  115. iowrite32(val, ctx->regs + reg);
  116. }
  117. static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
  118. unsigned int reg,
  119. unsigned int val)
  120. {
  121. writel(swab32(val), ctx->regs + reg);
  122. }
  123. static void regmap_mmio_iowrite32be(struct regmap_mmio_context *ctx,
  124. unsigned int reg, unsigned int val)
  125. {
  126. iowrite32be(val, ctx->regs + reg);
  127. }
  128. static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
  129. {
  130. struct regmap_mmio_context *ctx = context;
  131. int ret;
  132. if (!IS_ERR(ctx->clk)) {
  133. ret = clk_enable(ctx->clk);
  134. if (ret < 0)
  135. return ret;
  136. }
  137. ctx->reg_write(ctx, reg, val);
  138. if (!IS_ERR(ctx->clk))
  139. clk_disable(ctx->clk);
  140. return 0;
  141. }
  142. static int regmap_mmio_noinc_write(void *context, unsigned int reg,
  143. const void *val, size_t val_count)
  144. {
  145. struct regmap_mmio_context *ctx = context;
  146. int ret = 0;
  147. int i;
  148. if (!IS_ERR(ctx->clk)) {
  149. ret = clk_enable(ctx->clk);
  150. if (ret < 0)
  151. return ret;
  152. }
  153. /*
  154. * There are no native, assembly-optimized write single register
  155. * operations for big endian, so fall back to emulation if this
  156. * is needed. (Single bytes are fine, they are not affected by
  157. * endianness.)
  158. */
  159. if (ctx->big_endian && (ctx->val_bytes > 1)) {
  160. switch (ctx->val_bytes) {
  161. case 2:
  162. {
  163. const u16 *valp = (const u16 *)val;
  164. for (i = 0; i < val_count; i++)
  165. writew(swab16(valp[i]), ctx->regs + reg);
  166. goto out_clk;
  167. }
  168. case 4:
  169. {
  170. const u32 *valp = (const u32 *)val;
  171. for (i = 0; i < val_count; i++)
  172. writel(swab32(valp[i]), ctx->regs + reg);
  173. goto out_clk;
  174. }
  175. default:
  176. ret = -EINVAL;
  177. goto out_clk;
  178. }
  179. }
  180. switch (ctx->val_bytes) {
  181. case 1:
  182. writesb(ctx->regs + reg, (const u8 *)val, val_count);
  183. break;
  184. case 2:
  185. writesw(ctx->regs + reg, (const u16 *)val, val_count);
  186. break;
  187. case 4:
  188. writesl(ctx->regs + reg, (const u32 *)val, val_count);
  189. break;
  190. default:
  191. ret = -EINVAL;
  192. break;
  193. }
  194. out_clk:
  195. if (!IS_ERR(ctx->clk))
  196. clk_disable(ctx->clk);
  197. return ret;
  198. }
  199. static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
  200. unsigned int reg)
  201. {
  202. return readb(ctx->regs + reg);
  203. }
  204. static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx,
  205. unsigned int reg)
  206. {
  207. return readb_relaxed(ctx->regs + reg);
  208. }
  209. static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context *ctx,
  210. unsigned int reg)
  211. {
  212. return ioread8(ctx->regs + reg);
  213. }
  214. static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
  215. unsigned int reg)
  216. {
  217. return readw(ctx->regs + reg);
  218. }
  219. static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx,
  220. unsigned int reg)
  221. {
  222. return readw_relaxed(ctx->regs + reg);
  223. }
  224. static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context *ctx,
  225. unsigned int reg)
  226. {
  227. return ioread16(ctx->regs + reg);
  228. }
  229. static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
  230. unsigned int reg)
  231. {
  232. return swab16(readw(ctx->regs + reg));
  233. }
  234. static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context *ctx,
  235. unsigned int reg)
  236. {
  237. return ioread16be(ctx->regs + reg);
  238. }
  239. static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
  240. unsigned int reg)
  241. {
  242. return readl(ctx->regs + reg);
  243. }
  244. static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx,
  245. unsigned int reg)
  246. {
  247. return readl_relaxed(ctx->regs + reg);
  248. }
  249. static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context *ctx,
  250. unsigned int reg)
  251. {
  252. return ioread32(ctx->regs + reg);
  253. }
  254. static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
  255. unsigned int reg)
  256. {
  257. return swab32(readl(ctx->regs + reg));
  258. }
  259. static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context *ctx,
  260. unsigned int reg)
  261. {
  262. return ioread32be(ctx->regs + reg);
  263. }
  264. static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
  265. {
  266. struct regmap_mmio_context *ctx = context;
  267. int ret;
  268. if (!IS_ERR(ctx->clk)) {
  269. ret = clk_enable(ctx->clk);
  270. if (ret < 0)
  271. return ret;
  272. }
  273. *val = ctx->reg_read(ctx, reg);
  274. if (!IS_ERR(ctx->clk))
  275. clk_disable(ctx->clk);
  276. return 0;
  277. }
  278. static int regmap_mmio_noinc_read(void *context, unsigned int reg,
  279. void *val, size_t val_count)
  280. {
  281. struct regmap_mmio_context *ctx = context;
  282. int ret = 0;
  283. if (!IS_ERR(ctx->clk)) {
  284. ret = clk_enable(ctx->clk);
  285. if (ret < 0)
  286. return ret;
  287. }
  288. switch (ctx->val_bytes) {
  289. case 1:
  290. readsb(ctx->regs + reg, (u8 *)val, val_count);
  291. break;
  292. case 2:
  293. readsw(ctx->regs + reg, (u16 *)val, val_count);
  294. break;
  295. case 4:
  296. readsl(ctx->regs + reg, (u32 *)val, val_count);
  297. break;
  298. default:
  299. ret = -EINVAL;
  300. goto out_clk;
  301. }
  302. /*
  303. * There are no native, assembly-optimized write single register
  304. * operations for big endian, so fall back to emulation if this
  305. * is needed. (Single bytes are fine, they are not affected by
  306. * endianness.)
  307. */
  308. if (ctx->big_endian && (ctx->val_bytes > 1)) {
  309. switch (ctx->val_bytes) {
  310. case 2:
  311. swab16_array(val, val_count);
  312. break;
  313. case 4:
  314. swab32_array(val, val_count);
  315. break;
  316. default:
  317. ret = -EINVAL;
  318. break;
  319. }
  320. }
  321. out_clk:
  322. if (!IS_ERR(ctx->clk))
  323. clk_disable(ctx->clk);
  324. return ret;
  325. }
  326. static void regmap_mmio_free_context(void *context)
  327. {
  328. struct regmap_mmio_context *ctx = context;
  329. if (!IS_ERR(ctx->clk)) {
  330. clk_unprepare(ctx->clk);
  331. if (!ctx->attached_clk)
  332. clk_put(ctx->clk);
  333. }
  334. kfree(context);
  335. }
  336. static const struct regmap_bus regmap_mmio = {
  337. .fast_io = true,
  338. .reg_write = regmap_mmio_write,
  339. .reg_read = regmap_mmio_read,
  340. .reg_noinc_write = regmap_mmio_noinc_write,
  341. .reg_noinc_read = regmap_mmio_noinc_read,
  342. .free_context = regmap_mmio_free_context,
  343. .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
  344. };
  345. static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
  346. const char *clk_id,
  347. void __iomem *regs,
  348. const struct regmap_config *config)
  349. {
  350. struct regmap_mmio_context *ctx;
  351. int min_stride;
  352. int ret;
  353. ret = regmap_mmio_regbits_check(config->reg_bits);
  354. if (ret)
  355. return ERR_PTR(ret);
  356. if (config->pad_bits)
  357. return ERR_PTR(-EINVAL);
  358. min_stride = regmap_mmio_get_min_stride(config->val_bits);
  359. if (min_stride < 0)
  360. return ERR_PTR(min_stride);
  361. if (config->reg_stride && config->reg_stride < min_stride)
  362. return ERR_PTR(-EINVAL);
  363. if (config->use_relaxed_mmio && config->io_port)
  364. return ERR_PTR(-EINVAL);
  365. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  366. if (!ctx)
  367. return ERR_PTR(-ENOMEM);
  368. ctx->regs = regs;
  369. ctx->val_bytes = config->val_bits / 8;
  370. ctx->clk = ERR_PTR(-ENODEV);
  371. switch (regmap_get_val_endian(dev, &regmap_mmio, config)) {
  372. case REGMAP_ENDIAN_DEFAULT:
  373. case REGMAP_ENDIAN_LITTLE:
  374. #ifdef __LITTLE_ENDIAN
  375. case REGMAP_ENDIAN_NATIVE:
  376. #endif
  377. switch (config->val_bits) {
  378. case 8:
  379. if (config->io_port) {
  380. ctx->reg_read = regmap_mmio_ioread8;
  381. ctx->reg_write = regmap_mmio_iowrite8;
  382. } else if (config->use_relaxed_mmio) {
  383. ctx->reg_read = regmap_mmio_read8_relaxed;
  384. ctx->reg_write = regmap_mmio_write8_relaxed;
  385. } else {
  386. ctx->reg_read = regmap_mmio_read8;
  387. ctx->reg_write = regmap_mmio_write8;
  388. }
  389. break;
  390. case 16:
  391. if (config->io_port) {
  392. ctx->reg_read = regmap_mmio_ioread16le;
  393. ctx->reg_write = regmap_mmio_iowrite16le;
  394. } else if (config->use_relaxed_mmio) {
  395. ctx->reg_read = regmap_mmio_read16le_relaxed;
  396. ctx->reg_write = regmap_mmio_write16le_relaxed;
  397. } else {
  398. ctx->reg_read = regmap_mmio_read16le;
  399. ctx->reg_write = regmap_mmio_write16le;
  400. }
  401. break;
  402. case 32:
  403. if (config->io_port) {
  404. ctx->reg_read = regmap_mmio_ioread32le;
  405. ctx->reg_write = regmap_mmio_iowrite32le;
  406. } else if (config->use_relaxed_mmio) {
  407. ctx->reg_read = regmap_mmio_read32le_relaxed;
  408. ctx->reg_write = regmap_mmio_write32le_relaxed;
  409. } else {
  410. ctx->reg_read = regmap_mmio_read32le;
  411. ctx->reg_write = regmap_mmio_write32le;
  412. }
  413. break;
  414. default:
  415. ret = -EINVAL;
  416. goto err_free;
  417. }
  418. break;
  419. case REGMAP_ENDIAN_BIG:
  420. #ifdef __BIG_ENDIAN
  421. case REGMAP_ENDIAN_NATIVE:
  422. #endif
  423. ctx->big_endian = true;
  424. switch (config->val_bits) {
  425. case 8:
  426. if (config->io_port) {
  427. ctx->reg_read = regmap_mmio_ioread8;
  428. ctx->reg_write = regmap_mmio_iowrite8;
  429. } else {
  430. ctx->reg_read = regmap_mmio_read8;
  431. ctx->reg_write = regmap_mmio_write8;
  432. }
  433. break;
  434. case 16:
  435. if (config->io_port) {
  436. ctx->reg_read = regmap_mmio_ioread16be;
  437. ctx->reg_write = regmap_mmio_iowrite16be;
  438. } else {
  439. ctx->reg_read = regmap_mmio_read16be;
  440. ctx->reg_write = regmap_mmio_write16be;
  441. }
  442. break;
  443. case 32:
  444. if (config->io_port) {
  445. ctx->reg_read = regmap_mmio_ioread32be;
  446. ctx->reg_write = regmap_mmio_iowrite32be;
  447. } else {
  448. ctx->reg_read = regmap_mmio_read32be;
  449. ctx->reg_write = regmap_mmio_write32be;
  450. }
  451. break;
  452. default:
  453. ret = -EINVAL;
  454. goto err_free;
  455. }
  456. break;
  457. default:
  458. ret = -EINVAL;
  459. goto err_free;
  460. }
  461. if (clk_id == NULL)
  462. return ctx;
  463. ctx->clk = clk_get(dev, clk_id);
  464. if (IS_ERR(ctx->clk)) {
  465. ret = PTR_ERR(ctx->clk);
  466. goto err_free;
  467. }
  468. ret = clk_prepare(ctx->clk);
  469. if (ret < 0) {
  470. clk_put(ctx->clk);
  471. goto err_free;
  472. }
  473. return ctx;
  474. err_free:
  475. kfree(ctx);
  476. return ERR_PTR(ret);
  477. }
  478. struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
  479. void __iomem *regs,
  480. const struct regmap_config *config,
  481. struct lock_class_key *lock_key,
  482. const char *lock_name)
  483. {
  484. struct regmap_mmio_context *ctx;
  485. ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
  486. if (IS_ERR(ctx))
  487. return ERR_CAST(ctx);
  488. return __regmap_init(dev, &regmap_mmio, ctx, config,
  489. lock_key, lock_name);
  490. }
  491. EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk);
  492. struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
  493. const char *clk_id,
  494. void __iomem *regs,
  495. const struct regmap_config *config,
  496. struct lock_class_key *lock_key,
  497. const char *lock_name)
  498. {
  499. struct regmap_mmio_context *ctx;
  500. ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
  501. if (IS_ERR(ctx))
  502. return ERR_CAST(ctx);
  503. return __devm_regmap_init(dev, &regmap_mmio, ctx, config,
  504. lock_key, lock_name);
  505. }
  506. EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
  507. int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
  508. {
  509. struct regmap_mmio_context *ctx = map->bus_context;
  510. ctx->clk = clk;
  511. ctx->attached_clk = true;
  512. return clk_prepare(ctx->clk);
  513. }
  514. EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk);
  515. void regmap_mmio_detach_clk(struct regmap *map)
  516. {
  517. struct regmap_mmio_context *ctx = map->bus_context;
  518. clk_unprepare(ctx->clk);
  519. ctx->attached_clk = false;
  520. ctx->clk = NULL;
  521. }
  522. EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk);
  523. MODULE_LICENSE("GPL v2");