xref: /openbmc/u-boot/drivers/power/power_core.c (revision e3963c09)
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 
12 #include <common.h>
13 #include <malloc.h>
14 #include <linux/types.h>
15 #include <linux/list.h>
16 #include <power/pmic.h>
17 
18 static LIST_HEAD(pmic_list);
19 
20 int check_reg(struct pmic *p, u32 reg)
21 {
22 	if (reg >= p->number_of_regs) {
23 		printf("<reg num> = %d is invalid. Should be less than %d\n",
24 		       reg, p->number_of_regs);
25 		return -EINVAL;
26 	}
27 
28 	return 0;
29 }
30 
31 int 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))
36 		return -ENOTSUPP;
37 
38 	if (on)
39 		val |= out;
40 	else
41 		val &= ~out;
42 
43 	if (pmic_reg_write(p, reg, val))
44 		return -ENOTSUPP;
45 
46 	return 0;
47 }
48 
49 struct pmic *pmic_alloc(void)
50 {
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 
66 struct 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 
80 #ifndef CONFIG_SPL_BUILD
81 static 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 
106 static const char *power_get_interface(int interface)
107 {
108 	const char *power_interface[] = {"I2C", "SPI", "|+|-|"};
109 	return power_interface[interface];
110 }
111 
112 static 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) {
118 		printf("name: %s bus: %s_%d\n", p->name,
119 		       power_get_interface(p->interface), p->bus);
120 	}
121 }
122 
123 static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
124 {
125 	u32 ret, reg, val;
126 	char *cmd, *name;
127 	struct pmic *p;
128 
129 	/* at least two arguments please */
130 	if (argc < 2)
131 		return CMD_RET_USAGE;
132 
133 	if (strcmp(argv[1], "list") == 0) {
134 		pmic_list_names();
135 		return CMD_RET_SUCCESS;
136 	}
137 
138 	if (argc < 3)
139 		return CMD_RET_USAGE;
140 
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 
149 	if (strcmp(cmd, "dump") == 0) {
150 		if (pmic_dump(p))
151 			return CMD_RET_FAILURE;
152 		return CMD_RET_SUCCESS;
153 	}
154 
155 	if (strcmp(cmd, "read") == 0) {
156 		if (argc < 4)
157 			return CMD_RET_USAGE;
158 
159 		reg = simple_strtoul(argv[3], NULL, 16);
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 
167 		return CMD_RET_SUCCESS;
168 	}
169 
170 	if (strcmp(cmd, "write") == 0) {
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);
176 		pmic_reg_write(p, reg, val);
177 
178 		return CMD_RET_SUCCESS;
179 	}
180 
181 	if (strcmp(cmd, "bat") == 0) {
182 		if (argc < 4)
183 			return CMD_RET_USAGE;
184 
185 		if (!p->pbat) {
186 			printf("%s is not a battery\n", p->name);
187 			return CMD_RET_FAILURE;
188 		}
189 
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) {
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);
200 		}
201 
202 		return CMD_RET_SUCCESS;
203 	}
204 
205 	/* No subcommand found */
206 	return CMD_RET_SUCCESS;
207 }
208 
209 U_BOOT_CMD(
210 	pmic,	CONFIG_SYS_MAXARGS, 1, do_pmic,
211 	"PMIC",
212 	"list - list available PMICs\n"
213 	"pmic name dump - dump named PMIC registers\n"
214 	"pmic name read <reg> - read register\n"
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"
218 );
219 #endif
220