regmap.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2015 Google, Inc
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <errno.h>
  9. #include <log.h>
  10. #include <asm/global_data.h>
  11. #include <linux/libfdt.h>
  12. #include <malloc.h>
  13. #include <mapmem.h>
  14. #include <regmap.h>
  15. #include <asm/io.h>
  16. #include <dm/of_addr.h>
  17. #include <dm/devres.h>
  18. #include <linux/ioport.h>
  19. #include <linux/compat.h>
  20. #include <linux/err.h>
  21. #include <linux/bitops.h>
  22. /*
  23. * Internal representation of a regmap field. Instead of storing the MSB and
  24. * LSB, store the shift and mask. This makes the code a bit cleaner and faster
  25. * because the shift and mask don't have to be calculated every time.
  26. */
  27. struct regmap_field {
  28. struct regmap *regmap;
  29. unsigned int mask;
  30. /* lsb */
  31. unsigned int shift;
  32. unsigned int reg;
  33. };
  34. DECLARE_GLOBAL_DATA_PTR;
  35. /**
  36. * regmap_alloc() - Allocate a regmap with a given number of ranges.
  37. *
  38. * @count: Number of ranges to be allocated for the regmap.
  39. *
  40. * The default regmap width is set to REGMAP_SIZE_32. Callers can override it
  41. * if they need.
  42. *
  43. * Return: A pointer to the newly allocated regmap, or NULL on error.
  44. */
  45. static struct regmap *regmap_alloc(int count)
  46. {
  47. struct regmap *map;
  48. size_t size = sizeof(*map) + sizeof(map->ranges[0]) * count;
  49. map = calloc(1, size);
  50. if (!map)
  51. return NULL;
  52. map->range_count = count;
  53. map->width = REGMAP_SIZE_32;
  54. return map;
  55. }
  56. #if CONFIG_IS_ENABLED(OF_PLATDATA)
  57. int regmap_init_mem_plat(struct udevice *dev, fdt_val_t *reg, int count,
  58. struct regmap **mapp)
  59. {
  60. struct regmap_range *range;
  61. struct regmap *map;
  62. map = regmap_alloc(count);
  63. if (!map)
  64. return -ENOMEM;
  65. for (range = map->ranges; count > 0; reg += 2, range++, count--) {
  66. range->start = *reg;
  67. range->size = reg[1];
  68. }
  69. *mapp = map;
  70. return 0;
  71. }
  72. #else
  73. /**
  74. * init_range() - Initialize a single range of a regmap
  75. * @node: Device node that will use the map in question
  76. * @range: Pointer to a regmap_range structure that will be initialized
  77. * @addr_len: The length of the addr parts of the reg property
  78. * @size_len: The length of the size parts of the reg property
  79. * @index: The index of the range to initialize
  80. *
  81. * This function will read the necessary 'reg' information from the device tree
  82. * (the 'addr' part, and the 'length' part), and initialize the range in
  83. * quesion.
  84. *
  85. * Return: 0 if OK, -ve on error
  86. */
  87. static int init_range(ofnode node, struct regmap_range *range, int addr_len,
  88. int size_len, int index)
  89. {
  90. fdt_size_t sz;
  91. struct resource r;
  92. if (of_live_active()) {
  93. int ret;
  94. ret = of_address_to_resource(ofnode_to_np(node),
  95. index, &r);
  96. if (ret) {
  97. debug("%s: Could not read resource of range %d (ret = %d)\n",
  98. ofnode_get_name(node), index, ret);
  99. return ret;
  100. }
  101. range->start = r.start;
  102. range->size = r.end - r.start + 1;
  103. } else {
  104. int offset = ofnode_to_offset(node);
  105. range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset,
  106. "reg", index,
  107. addr_len, size_len,
  108. &sz, true);
  109. if (range->start == FDT_ADDR_T_NONE) {
  110. debug("%s: Could not read start of range %d\n",
  111. ofnode_get_name(node), index);
  112. return -EINVAL;
  113. }
  114. range->size = sz;
  115. }
  116. return 0;
  117. }
  118. int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index)
  119. {
  120. struct regmap *map;
  121. int addr_len, size_len;
  122. int ret;
  123. addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
  124. if (addr_len < 0) {
  125. debug("%s: Error while reading the addr length (ret = %d)\n",
  126. ofnode_get_name(node), addr_len);
  127. return addr_len;
  128. }
  129. size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
  130. if (size_len < 0) {
  131. debug("%s: Error while reading the size length: (ret = %d)\n",
  132. ofnode_get_name(node), size_len);
  133. return size_len;
  134. }
  135. map = regmap_alloc(1);
  136. if (!map)
  137. return -ENOMEM;
  138. ret = init_range(node, map->ranges, addr_len, size_len, index);
  139. if (ret)
  140. goto err;
  141. if (ofnode_read_bool(node, "little-endian"))
  142. map->endianness = REGMAP_LITTLE_ENDIAN;
  143. else if (ofnode_read_bool(node, "big-endian"))
  144. map->endianness = REGMAP_BIG_ENDIAN;
  145. else if (ofnode_read_bool(node, "native-endian"))
  146. map->endianness = REGMAP_NATIVE_ENDIAN;
  147. else /* Default: native endianness */
  148. map->endianness = REGMAP_NATIVE_ENDIAN;
  149. *mapp = map;
  150. return 0;
  151. err:
  152. regmap_uninit(map);
  153. return ret;
  154. }
  155. int regmap_init_mem_range(ofnode node, ulong r_start, ulong r_size,
  156. struct regmap **mapp)
  157. {
  158. struct regmap *map;
  159. struct regmap_range *range;
  160. map = regmap_alloc(1);
  161. if (!map)
  162. return -ENOMEM;
  163. range = &map->ranges[0];
  164. range->start = r_start;
  165. range->size = r_size;
  166. if (ofnode_read_bool(node, "little-endian"))
  167. map->endianness = REGMAP_LITTLE_ENDIAN;
  168. else if (ofnode_read_bool(node, "big-endian"))
  169. map->endianness = REGMAP_BIG_ENDIAN;
  170. else if (ofnode_read_bool(node, "native-endian"))
  171. map->endianness = REGMAP_NATIVE_ENDIAN;
  172. else /* Default: native endianness */
  173. map->endianness = REGMAP_NATIVE_ENDIAN;
  174. *mapp = map;
  175. return 0;
  176. }
  177. int regmap_init_mem(ofnode node, struct regmap **mapp)
  178. {
  179. struct regmap_range *range;
  180. struct regmap *map;
  181. int count;
  182. int addr_len, size_len, both_len;
  183. int len;
  184. int index;
  185. int ret;
  186. addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
  187. if (addr_len < 0) {
  188. debug("%s: Error while reading the addr length (ret = %d)\n",
  189. ofnode_get_name(node), addr_len);
  190. return addr_len;
  191. }
  192. size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
  193. if (size_len < 0) {
  194. debug("%s: Error while reading the size length: (ret = %d)\n",
  195. ofnode_get_name(node), size_len);
  196. return size_len;
  197. }
  198. both_len = addr_len + size_len;
  199. if (!both_len) {
  200. debug("%s: Both addr and size length are zero\n",
  201. ofnode_get_name(node));
  202. return -EINVAL;
  203. }
  204. len = ofnode_read_size(node, "reg");
  205. if (len < 0) {
  206. debug("%s: Error while reading reg size (ret = %d)\n",
  207. ofnode_get_name(node), len);
  208. return len;
  209. }
  210. len /= sizeof(fdt32_t);
  211. count = len / both_len;
  212. if (!count) {
  213. debug("%s: Not enough data in reg property\n",
  214. ofnode_get_name(node));
  215. return -EINVAL;
  216. }
  217. map = regmap_alloc(count);
  218. if (!map)
  219. return -ENOMEM;
  220. for (range = map->ranges, index = 0; count > 0;
  221. count--, range++, index++) {
  222. ret = init_range(node, range, addr_len, size_len, index);
  223. if (ret)
  224. goto err;
  225. }
  226. if (ofnode_read_bool(node, "little-endian"))
  227. map->endianness = REGMAP_LITTLE_ENDIAN;
  228. else if (ofnode_read_bool(node, "big-endian"))
  229. map->endianness = REGMAP_BIG_ENDIAN;
  230. else if (ofnode_read_bool(node, "native-endian"))
  231. map->endianness = REGMAP_NATIVE_ENDIAN;
  232. else /* Default: native endianness */
  233. map->endianness = REGMAP_NATIVE_ENDIAN;
  234. *mapp = map;
  235. return 0;
  236. err:
  237. regmap_uninit(map);
  238. return ret;
  239. }
  240. static void devm_regmap_release(struct udevice *dev, void *res)
  241. {
  242. regmap_uninit(*(struct regmap **)res);
  243. }
  244. struct regmap *devm_regmap_init(struct udevice *dev,
  245. const struct regmap_bus *bus,
  246. void *bus_context,
  247. const struct regmap_config *config)
  248. {
  249. int rc;
  250. struct regmap **mapp, *map;
  251. /* this looks like a leak, but devres takes care of it */
  252. mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *),
  253. __GFP_ZERO);
  254. if (unlikely(!mapp))
  255. return ERR_PTR(-ENOMEM);
  256. if (config && config->r_size != 0)
  257. rc = regmap_init_mem_range(dev_ofnode(dev), config->r_start,
  258. config->r_size, mapp);
  259. else
  260. rc = regmap_init_mem(dev_ofnode(dev), mapp);
  261. if (rc)
  262. return ERR_PTR(rc);
  263. map = *mapp;
  264. if (config) {
  265. map->width = config->width;
  266. map->reg_offset_shift = config->reg_offset_shift;
  267. }
  268. devres_add(dev, mapp);
  269. return *mapp;
  270. }
  271. #endif
  272. void *regmap_get_range(struct regmap *map, unsigned int range_num)
  273. {
  274. struct regmap_range *range;
  275. if (range_num >= map->range_count)
  276. return NULL;
  277. range = &map->ranges[range_num];
  278. return map_sysmem(range->start, range->size);
  279. }
  280. int regmap_uninit(struct regmap *map)
  281. {
  282. free(map);
  283. return 0;
  284. }
  285. static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
  286. {
  287. return readb(addr);
  288. }
  289. static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
  290. {
  291. switch (endianness) {
  292. case REGMAP_LITTLE_ENDIAN:
  293. return in_le16(addr);
  294. case REGMAP_BIG_ENDIAN:
  295. return in_be16(addr);
  296. case REGMAP_NATIVE_ENDIAN:
  297. return readw(addr);
  298. }
  299. return readw(addr);
  300. }
  301. static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
  302. {
  303. switch (endianness) {
  304. case REGMAP_LITTLE_ENDIAN:
  305. return in_le32(addr);
  306. case REGMAP_BIG_ENDIAN:
  307. return in_be32(addr);
  308. case REGMAP_NATIVE_ENDIAN:
  309. return readl(addr);
  310. }
  311. return readl(addr);
  312. }
  313. #if defined(in_le64) && defined(in_be64) && defined(readq)
  314. static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
  315. {
  316. switch (endianness) {
  317. case REGMAP_LITTLE_ENDIAN:
  318. return in_le64(addr);
  319. case REGMAP_BIG_ENDIAN:
  320. return in_be64(addr);
  321. case REGMAP_NATIVE_ENDIAN:
  322. return readq(addr);
  323. }
  324. return readq(addr);
  325. }
  326. #endif
  327. int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
  328. void *valp, size_t val_len)
  329. {
  330. struct regmap_range *range;
  331. void *ptr;
  332. if (range_num >= map->range_count) {
  333. debug("%s: range index %d larger than range count\n",
  334. __func__, range_num);
  335. return -ERANGE;
  336. }
  337. range = &map->ranges[range_num];
  338. offset <<= map->reg_offset_shift;
  339. if (offset + val_len > range->size) {
  340. debug("%s: offset/size combination invalid\n", __func__);
  341. return -ERANGE;
  342. }
  343. ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
  344. switch (val_len) {
  345. case REGMAP_SIZE_8:
  346. *((u8 *)valp) = __read_8(ptr, map->endianness);
  347. break;
  348. case REGMAP_SIZE_16:
  349. *((u16 *)valp) = __read_16(ptr, map->endianness);
  350. break;
  351. case REGMAP_SIZE_32:
  352. *((u32 *)valp) = __read_32(ptr, map->endianness);
  353. break;
  354. #if defined(in_le64) && defined(in_be64) && defined(readq)
  355. case REGMAP_SIZE_64:
  356. *((u64 *)valp) = __read_64(ptr, map->endianness);
  357. break;
  358. #endif
  359. default:
  360. debug("%s: regmap size %zu unknown\n", __func__, val_len);
  361. return -EINVAL;
  362. }
  363. return 0;
  364. }
  365. int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len)
  366. {
  367. return regmap_raw_read_range(map, 0, offset, valp, val_len);
  368. }
  369. int regmap_read(struct regmap *map, uint offset, uint *valp)
  370. {
  371. union {
  372. u8 v8;
  373. u16 v16;
  374. u32 v32;
  375. u64 v64;
  376. } u;
  377. int res;
  378. res = regmap_raw_read(map, offset, &u, map->width);
  379. if (res)
  380. return res;
  381. switch (map->width) {
  382. case REGMAP_SIZE_8:
  383. *valp = u.v8;
  384. break;
  385. case REGMAP_SIZE_16:
  386. *valp = u.v16;
  387. break;
  388. case REGMAP_SIZE_32:
  389. *valp = u.v32;
  390. break;
  391. case REGMAP_SIZE_64:
  392. *valp = u.v64;
  393. break;
  394. default:
  395. unreachable();
  396. }
  397. return 0;
  398. }
  399. static inline void __write_8(u8 *addr, const u8 *val,
  400. enum regmap_endianness_t endianness)
  401. {
  402. writeb(*val, addr);
  403. }
  404. static inline void __write_16(u16 *addr, const u16 *val,
  405. enum regmap_endianness_t endianness)
  406. {
  407. switch (endianness) {
  408. case REGMAP_NATIVE_ENDIAN:
  409. writew(*val, addr);
  410. break;
  411. case REGMAP_LITTLE_ENDIAN:
  412. out_le16(addr, *val);
  413. break;
  414. case REGMAP_BIG_ENDIAN:
  415. out_be16(addr, *val);
  416. break;
  417. }
  418. }
  419. static inline void __write_32(u32 *addr, const u32 *val,
  420. enum regmap_endianness_t endianness)
  421. {
  422. switch (endianness) {
  423. case REGMAP_NATIVE_ENDIAN:
  424. writel(*val, addr);
  425. break;
  426. case REGMAP_LITTLE_ENDIAN:
  427. out_le32(addr, *val);
  428. break;
  429. case REGMAP_BIG_ENDIAN:
  430. out_be32(addr, *val);
  431. break;
  432. }
  433. }
  434. #if defined(out_le64) && defined(out_be64) && defined(writeq)
  435. static inline void __write_64(u64 *addr, const u64 *val,
  436. enum regmap_endianness_t endianness)
  437. {
  438. switch (endianness) {
  439. case REGMAP_NATIVE_ENDIAN:
  440. writeq(*val, addr);
  441. break;
  442. case REGMAP_LITTLE_ENDIAN:
  443. out_le64(addr, *val);
  444. break;
  445. case REGMAP_BIG_ENDIAN:
  446. out_be64(addr, *val);
  447. break;
  448. }
  449. }
  450. #endif
  451. int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
  452. const void *val, size_t val_len)
  453. {
  454. struct regmap_range *range;
  455. void *ptr;
  456. if (range_num >= map->range_count) {
  457. debug("%s: range index %d larger than range count\n",
  458. __func__, range_num);
  459. return -ERANGE;
  460. }
  461. range = &map->ranges[range_num];
  462. offset <<= map->reg_offset_shift;
  463. if (offset + val_len > range->size) {
  464. debug("%s: offset/size combination invalid\n", __func__);
  465. return -ERANGE;
  466. }
  467. ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
  468. switch (val_len) {
  469. case REGMAP_SIZE_8:
  470. __write_8(ptr, val, map->endianness);
  471. break;
  472. case REGMAP_SIZE_16:
  473. __write_16(ptr, val, map->endianness);
  474. break;
  475. case REGMAP_SIZE_32:
  476. __write_32(ptr, val, map->endianness);
  477. break;
  478. #if defined(out_le64) && defined(out_be64) && defined(writeq)
  479. case REGMAP_SIZE_64:
  480. __write_64(ptr, val, map->endianness);
  481. break;
  482. #endif
  483. default:
  484. debug("%s: regmap size %zu unknown\n", __func__, val_len);
  485. return -EINVAL;
  486. }
  487. return 0;
  488. }
  489. int regmap_raw_write(struct regmap *map, uint offset, const void *val,
  490. size_t val_len)
  491. {
  492. return regmap_raw_write_range(map, 0, offset, val, val_len);
  493. }
  494. int regmap_write(struct regmap *map, uint offset, uint val)
  495. {
  496. union {
  497. u8 v8;
  498. u16 v16;
  499. u32 v32;
  500. u64 v64;
  501. } u;
  502. switch (map->width) {
  503. case REGMAP_SIZE_8:
  504. u.v8 = val;
  505. break;
  506. case REGMAP_SIZE_16:
  507. u.v16 = val;
  508. break;
  509. case REGMAP_SIZE_32:
  510. u.v32 = val;
  511. break;
  512. case REGMAP_SIZE_64:
  513. u.v64 = val;
  514. break;
  515. default:
  516. debug("%s: regmap size %zu unknown\n", __func__,
  517. (size_t)map->width);
  518. return -EINVAL;
  519. }
  520. return regmap_raw_write(map, offset, &u, map->width);
  521. }
  522. int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
  523. {
  524. uint reg;
  525. int ret;
  526. ret = regmap_read(map, offset, &reg);
  527. if (ret)
  528. return ret;
  529. reg &= ~mask;
  530. return regmap_write(map, offset, reg | (val & mask));
  531. }
  532. int regmap_field_read(struct regmap_field *field, unsigned int *val)
  533. {
  534. int ret;
  535. unsigned int reg_val;
  536. ret = regmap_read(field->regmap, field->reg, &reg_val);
  537. if (ret != 0)
  538. return ret;
  539. reg_val &= field->mask;
  540. reg_val >>= field->shift;
  541. *val = reg_val;
  542. return ret;
  543. }
  544. int regmap_field_write(struct regmap_field *field, unsigned int val)
  545. {
  546. return regmap_update_bits(field->regmap, field->reg, field->mask,
  547. val << field->shift);
  548. }
  549. static void regmap_field_init(struct regmap_field *rm_field,
  550. struct regmap *regmap,
  551. struct reg_field reg_field)
  552. {
  553. rm_field->regmap = regmap;
  554. rm_field->reg = reg_field.reg;
  555. rm_field->shift = reg_field.lsb;
  556. rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb);
  557. }
  558. struct regmap_field *devm_regmap_field_alloc(struct udevice *dev,
  559. struct regmap *regmap,
  560. struct reg_field reg_field)
  561. {
  562. struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field),
  563. GFP_KERNEL);
  564. if (!rm_field)
  565. return ERR_PTR(-ENOMEM);
  566. regmap_field_init(rm_field, regmap, reg_field);
  567. return rm_field;
  568. }
  569. void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field)
  570. {
  571. devm_kfree(dev, field);
  572. }
  573. struct regmap_field *regmap_field_alloc(struct regmap *regmap,
  574. struct reg_field reg_field)
  575. {
  576. struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
  577. if (!rm_field)
  578. return ERR_PTR(-ENOMEM);
  579. regmap_field_init(rm_field, regmap, reg_field);
  580. return rm_field;
  581. }
  582. void regmap_field_free(struct regmap_field *field)
  583. {
  584. kfree(field);
  585. }