power_core.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2011 Samsung Electronics
  4. * Lukasz Majewski <l.majewski@samsung.com>
  5. *
  6. * (C) Copyright 2010
  7. * Stefano Babic, DENX Software Engineering, sbabic@denx.de
  8. *
  9. * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
  10. */
  11. #include <common.h>
  12. #include <command.h>
  13. #include <log.h>
  14. #include <malloc.h>
  15. #include <linux/types.h>
  16. #include <linux/list.h>
  17. #include <power/pmic.h>
  18. static LIST_HEAD(pmic_list);
  19. int check_reg(struct pmic *p, u32 reg)
  20. {
  21. if (reg >= p->number_of_regs) {
  22. printf("<reg num> = %d is invalid. Should be less than %d\n",
  23. reg, p->number_of_regs);
  24. return -EINVAL;
  25. }
  26. return 0;
  27. }
  28. int pmic_set_output(struct pmic *p, u32 reg, int out, int on)
  29. {
  30. u32 val;
  31. if (pmic_reg_read(p, reg, &val))
  32. return -ENOTSUPP;
  33. if (on)
  34. val |= out;
  35. else
  36. val &= ~out;
  37. if (pmic_reg_write(p, reg, val))
  38. return -ENOTSUPP;
  39. return 0;
  40. }
  41. struct pmic *pmic_alloc(void)
  42. {
  43. struct pmic *p;
  44. p = calloc(sizeof(*p), 1);
  45. if (!p) {
  46. printf("%s: No available memory for allocation!\n", __func__);
  47. return NULL;
  48. }
  49. list_add_tail(&p->list, &pmic_list);
  50. debug("%s: new pmic struct: 0x%p\n", __func__, p);
  51. return p;
  52. }
  53. struct pmic *pmic_get(const char *s)
  54. {
  55. struct pmic *p;
  56. list_for_each_entry(p, &pmic_list, list) {
  57. if (strcmp(p->name, s) == 0) {
  58. debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p);
  59. return p;
  60. }
  61. }
  62. return NULL;
  63. }
  64. #ifndef CONFIG_SPL_BUILD
  65. static int pmic_dump(struct pmic *p)
  66. {
  67. int i, ret;
  68. u32 val;
  69. if (!p) {
  70. puts("Wrong PMIC name!\n");
  71. return -ENODEV;
  72. }
  73. printf("PMIC: %s\n", p->name);
  74. for (i = 0; i < p->number_of_regs; i++) {
  75. ret = pmic_reg_read(p, i, &val);
  76. if (ret)
  77. puts("PMIC: Registers dump failed\n");
  78. if (!(i % 8))
  79. printf("\n0x%02x: ", i);
  80. printf("%08x ", val);
  81. }
  82. puts("\n");
  83. return 0;
  84. }
  85. static const char *power_get_interface(int interface)
  86. {
  87. const char *power_interface[] = {"I2C", "SPI", "|+|-|"};
  88. return power_interface[interface];
  89. }
  90. static void pmic_list_names(void)
  91. {
  92. struct pmic *p;
  93. puts("PMIC devices:\n");
  94. list_for_each_entry(p, &pmic_list, list) {
  95. printf("name: %s bus: %s_%d\n", p->name,
  96. power_get_interface(p->interface), p->bus);
  97. }
  98. }
  99. static int do_pmic(struct cmd_tbl *cmdtp, int flag, int argc,
  100. char *const argv[])
  101. {
  102. u32 ret, reg, val;
  103. char *cmd, *name;
  104. struct pmic *p;
  105. /* at least two arguments please */
  106. if (argc < 2)
  107. return CMD_RET_USAGE;
  108. if (strcmp(argv[1], "list") == 0) {
  109. pmic_list_names();
  110. return CMD_RET_SUCCESS;
  111. }
  112. if (argc < 3)
  113. return CMD_RET_USAGE;
  114. name = argv[1];
  115. cmd = argv[2];
  116. debug("%s: name: %s cmd: %s\n", __func__, name, cmd);
  117. p = pmic_get(name);
  118. if (!p)
  119. return CMD_RET_FAILURE;
  120. if (strcmp(cmd, "dump") == 0) {
  121. if (pmic_dump(p))
  122. return CMD_RET_FAILURE;
  123. return CMD_RET_SUCCESS;
  124. }
  125. if (strcmp(cmd, "read") == 0) {
  126. if (argc < 4)
  127. return CMD_RET_USAGE;
  128. reg = hextoul(argv[3], NULL);
  129. ret = pmic_reg_read(p, reg, &val);
  130. if (ret)
  131. puts("PMIC: Register read failed\n");
  132. printf("\n0x%02x: 0x%08x\n", reg, val);
  133. return CMD_RET_SUCCESS;
  134. }
  135. if (strcmp(cmd, "write") == 0) {
  136. if (argc < 5)
  137. return CMD_RET_USAGE;
  138. reg = hextoul(argv[3], NULL);
  139. val = hextoul(argv[4], NULL);
  140. pmic_reg_write(p, reg, val);
  141. return CMD_RET_SUCCESS;
  142. }
  143. if (strcmp(cmd, "bat") == 0) {
  144. if (argc < 4)
  145. return CMD_RET_USAGE;
  146. if (!p->pbat) {
  147. printf("%s is not a battery\n", p->name);
  148. return CMD_RET_FAILURE;
  149. }
  150. if (strcmp(argv[3], "state") == 0)
  151. p->fg->fg_battery_check(p->pbat->fg, p);
  152. if (strcmp(argv[3], "charge") == 0) {
  153. printf("BAT: %s charging (ctrl+c to break)\n",
  154. p->name);
  155. if (p->low_power_mode)
  156. p->low_power_mode();
  157. if (p->pbat->battery_charge)
  158. p->pbat->battery_charge(p);
  159. }
  160. return CMD_RET_SUCCESS;
  161. }
  162. /* No subcommand found */
  163. return CMD_RET_SUCCESS;
  164. }
  165. U_BOOT_CMD(
  166. pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
  167. "PMIC",
  168. "list - list available PMICs\n"
  169. "pmic name dump - dump named PMIC registers\n"
  170. "pmic name read <reg> - read register\n"
  171. "pmic name write <reg> <value> - write register\n"
  172. "pmic name bat state - write register\n"
  173. "pmic name bat charge - write register\n"
  174. );
  175. #endif