power_core.c 4.1 KB

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