]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/power/power_core.c
Merge tag 'video-for-2019.07-rc1' of git://git.denx.de/u-boot-video
[thirdparty/u-boot.git] / drivers / power / power_core.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
e542b7f0
ŁM
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.
e542b7f0
ŁM
10 */
11
12#include <common.h>
c7336815 13#include <malloc.h>
e542b7f0 14#include <linux/types.h>
c7336815
ŁM
15#include <linux/list.h>
16#include <power/pmic.h>
e542b7f0 17
c7336815 18static LIST_HEAD(pmic_list);
e542b7f0 19
c7336815 20int check_reg(struct pmic *p, u32 reg)
e542b7f0 21{
c7336815 22 if (reg >= p->number_of_regs) {
e542b7f0 23 printf("<reg num> = %d is invalid. Should be less than %d\n",
c7336815 24 reg, p->number_of_regs);
505cf475 25 return -EINVAL;
e542b7f0 26 }
c7336815 27
e542b7f0
ŁM
28 return 0;
29}
30
31int pmic_set_output(struct pmic *p, u32 reg, int out, int on)
32{
33 u32 val;
34
35 if (pmic_reg_read(p, reg, &val))
505cf475 36 return -ENOTSUPP;
e542b7f0
ŁM
37
38 if (on)
39 val |= out;
40 else
41 val &= ~out;
42
43 if (pmic_reg_write(p, reg, val))
505cf475 44 return -ENOTSUPP;
e542b7f0
ŁM
45
46 return 0;
47}
48
c7336815 49struct pmic *pmic_alloc(void)
e542b7f0 50{
c7336815
ŁM
51 struct pmic *p;
52
53 p = calloc(sizeof(*p), 1);
54 if (!p) {
55 printf("%s: No available memory for allocation!\n", __func__);
56 return NULL;
57 }
58
59 list_add_tail(&p->list, &pmic_list);
60
61 debug("%s: new pmic struct: 0x%p\n", __func__, p);
62
63 return p;
64}
65
66struct pmic *pmic_get(const char *s)
67{
68 struct pmic *p;
69
70 list_for_each_entry(p, &pmic_list, list) {
71 if (strcmp(p->name, s) == 0) {
72 debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p);
73 return p;
74 }
75 }
76
77 return NULL;
78}
79
8c0bb858
TR
80#ifndef CONFIG_SPL_BUILD
81static int pmic_dump(struct pmic *p)
82{
83 int i, ret;
84 u32 val;
85
86 if (!p) {
87 puts("Wrong PMIC name!\n");
88 return -ENODEV;
89 }
90
91 printf("PMIC: %s\n", p->name);
92 for (i = 0; i < p->number_of_regs; i++) {
93 ret = pmic_reg_read(p, i, &val);
94 if (ret)
95 puts("PMIC: Registers dump failed\n");
96
97 if (!(i % 8))
98 printf("\n0x%02x: ", i);
99
100 printf("%08x ", val);
101 }
102 puts("\n");
103 return 0;
104}
105
106static const char *power_get_interface(int interface)
7d19629f
ŁM
107{
108 const char *power_interface[] = {"I2C", "SPI", "|+|-|"};
109 return power_interface[interface];
110}
111
c7336815
ŁM
112static void pmic_list_names(void)
113{
114 struct pmic *p;
115
116 puts("PMIC devices:\n");
117 list_for_each_entry(p, &pmic_list, list) {
7d19629f
ŁM
118 printf("name: %s bus: %s_%d\n", p->name,
119 power_get_interface(p->interface), p->bus);
c7336815 120 }
e542b7f0
ŁM
121}
122
8c0bb858 123static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
e542b7f0
ŁM
124{
125 u32 ret, reg, val;
7d19629f 126 char *cmd, *name;
c7336815 127 struct pmic *p;
e542b7f0 128
e542b7f0
ŁM
129 /* at least two arguments please */
130 if (argc < 2)
c7336815 131 return CMD_RET_USAGE;
e542b7f0 132
7d19629f 133 if (strcmp(argv[1], "list") == 0) {
c7336815
ŁM
134 pmic_list_names();
135 return CMD_RET_SUCCESS;
136 }
137
eae74537
ŁM
138 if (argc < 3)
139 return CMD_RET_USAGE;
140
7d19629f
ŁM
141 name = argv[1];
142 cmd = argv[2];
143
144 debug("%s: name: %s cmd: %s\n", __func__, name, cmd);
145 p = pmic_get(name);
146 if (!p)
147 return CMD_RET_FAILURE;
148
e542b7f0 149 if (strcmp(cmd, "dump") == 0) {
c7336815
ŁM
150 if (pmic_dump(p))
151 return CMD_RET_FAILURE;
152 return CMD_RET_SUCCESS;
e542b7f0
ŁM
153 }
154
155 if (strcmp(cmd, "read") == 0) {
c7336815
ŁM
156 if (argc < 4)
157 return CMD_RET_USAGE;
e542b7f0 158
c7336815 159 reg = simple_strtoul(argv[3], NULL, 16);
e542b7f0
ŁM
160 ret = pmic_reg_read(p, reg, &val);
161
162 if (ret)
163 puts("PMIC: Register read failed\n");
164
165 printf("\n0x%02x: 0x%08x\n", reg, val);
166
c7336815 167 return CMD_RET_SUCCESS;
e542b7f0
ŁM
168 }
169
170 if (strcmp(cmd, "write") == 0) {
c7336815
ŁM
171 if (argc < 5)
172 return CMD_RET_USAGE;
173
174 reg = simple_strtoul(argv[3], NULL, 16);
175 val = simple_strtoul(argv[4], NULL, 16);
e542b7f0
ŁM
176 pmic_reg_write(p, reg, val);
177
c7336815 178 return CMD_RET_SUCCESS;
e542b7f0
ŁM
179 }
180
7d19629f
ŁM
181 if (strcmp(cmd, "bat") == 0) {
182 if (argc < 4)
183 return CMD_RET_USAGE;
184
a6abaadc
PW
185 if (!p->pbat) {
186 printf("%s is not a battery\n", p->name);
187 return CMD_RET_FAILURE;
188 }
189
7d19629f
ŁM
190 if (strcmp(argv[3], "state") == 0)
191 p->fg->fg_battery_check(p->pbat->fg, p);
192
193 if (strcmp(argv[3], "charge") == 0) {
a6abaadc
PW
194 printf("BAT: %s charging (ctrl+c to break)\n",
195 p->name);
196 if (p->low_power_mode)
197 p->low_power_mode();
198 if (p->pbat->battery_charge)
199 p->pbat->battery_charge(p);
7d19629f
ŁM
200 }
201
202 return CMD_RET_SUCCESS;
203 }
204
e542b7f0 205 /* No subcommand found */
c7336815 206 return CMD_RET_SUCCESS;
e542b7f0
ŁM
207}
208
209U_BOOT_CMD(
210 pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
211 "PMIC",
c7336815 212 "list - list available PMICs\n"
7d19629f 213 "pmic name dump - dump named PMIC registers\n"
c7336815 214 "pmic name read <reg> - read register\n"
7d19629f
ŁM
215 "pmic name write <reg> <value> - write register\n"
216 "pmic name bat state - write register\n"
217 "pmic name bat charge - write register\n"
e542b7f0 218);
8c0bb858 219#endif