]>
Commit | Line | Data |
---|---|---|
d89fdcf9 PM |
1 | /* |
2 | * Copyright (C) 2014-2015 Samsung Electronics | |
3 | * Przemyslaw Marczak <p.marczak@samsung.com> | |
4 | * | |
5 | * SPDX-License-Identifier: GPL-2.0+ | |
6 | */ | |
7 | #include <common.h> | |
8 | #include <errno.h> | |
9 | #include <dm.h> | |
10 | #include <dm/uclass-internal.h> | |
11 | #include <power/pmic.h> | |
12 | ||
13 | #define LIMIT_SEQ 3 | |
14 | #define LIMIT_DEVNAME 20 | |
15 | ||
16 | static struct udevice *currdev; | |
17 | ||
18 | static int failed(const char *getset, const char *thing, | |
19 | const char *for_dev, int ret) | |
20 | { | |
21 | printf("Can't %s %s %s.\nError: %d (%s)\n", getset, thing, for_dev, | |
22 | ret, errno_str(ret)); | |
23 | return CMD_RET_FAILURE; | |
24 | } | |
25 | ||
26 | static int pmic_dev_get(bool list_only, int get_seq, struct udevice **devp) | |
27 | { | |
28 | struct udevice *dev; | |
29 | int ret; | |
30 | ||
31 | if (devp) | |
32 | *devp = NULL; | |
33 | ||
34 | for (ret = uclass_first_device(UCLASS_PMIC, &dev); dev; | |
35 | ret = uclass_next_device(&dev)) { | |
36 | if (list_only) { | |
37 | printf("|%*d | %-*.*s| %-*.*s| %s @ %d\n", | |
38 | LIMIT_SEQ, dev->seq, | |
39 | LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name, | |
40 | LIMIT_DEVNAME, LIMIT_DEVNAME, dev->parent->name, | |
41 | dev_get_uclass_name(dev->parent), | |
42 | dev->parent->seq); | |
43 | continue; | |
44 | } | |
45 | ||
46 | if (dev->seq == get_seq) { | |
47 | if (devp) | |
48 | *devp = dev; | |
49 | else | |
50 | return -EINVAL; | |
51 | ||
52 | return 0; | |
53 | } | |
54 | } | |
55 | ||
56 | if (list_only) | |
57 | return ret; | |
58 | ||
59 | return -ENODEV; | |
60 | } | |
61 | ||
62 | static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
63 | { | |
64 | int seq, ret = -ENODEV; | |
65 | ||
66 | switch (argc) { | |
67 | case 2: | |
68 | seq = simple_strtoul(argv[1], NULL, 0); | |
69 | ret = uclass_get_device_by_seq(UCLASS_PMIC, seq, &currdev); | |
70 | if (ret && (ret = pmic_dev_get(false, seq, &currdev))) | |
71 | goto failed; | |
72 | case 1: | |
73 | if (!currdev) | |
74 | goto failed; | |
75 | ||
76 | printf("dev: %d @ %s\n", currdev->seq, currdev->name); | |
77 | } | |
78 | ||
79 | return CMD_RET_SUCCESS; | |
80 | failed: | |
81 | return failed("get", "the", "device", ret); | |
82 | } | |
83 | ||
84 | static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
85 | { | |
86 | struct udevice *dev; | |
87 | int ret; | |
88 | ||
89 | printf("|%*s | %-*.*s| %-*.*s| %s @ %s\n", | |
90 | LIMIT_SEQ, "Seq", | |
91 | LIMIT_DEVNAME, LIMIT_DEVNAME, "Name", | |
92 | LIMIT_DEVNAME, LIMIT_DEVNAME, "Parent name", | |
93 | "Parent uclass", "seq"); | |
94 | ||
95 | for (ret = uclass_first_device(UCLASS_PMIC, &dev); dev; | |
96 | ret = uclass_next_device(&dev)) { | |
97 | printf("|%*d | %-*.*s| %-*.*s| %s @ %d\n", | |
98 | LIMIT_SEQ, dev->seq, | |
99 | LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name, | |
100 | LIMIT_DEVNAME, LIMIT_DEVNAME, dev->parent->name, | |
101 | dev_get_uclass_name(dev->parent), dev->parent->seq); | |
102 | } | |
103 | ||
104 | if (ret) | |
105 | return CMD_RET_FAILURE; | |
106 | ||
107 | return CMD_RET_SUCCESS; | |
108 | } | |
109 | ||
110 | static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
111 | { | |
112 | struct udevice *dev; | |
113 | uint8_t value; | |
114 | uint reg; | |
115 | int ret; | |
116 | ||
117 | if (!currdev) | |
118 | return failed("get", "current", "device", -ENODEV); | |
119 | ||
120 | dev = currdev; | |
121 | ||
122 | printf("Dump pmic: %s registers\n", dev->name); | |
123 | ||
124 | for (reg = 0; reg < pmic_reg_count(dev); reg++) { | |
125 | ret = pmic_read(dev, reg, &value, 1); | |
126 | if (ret) | |
127 | return failed("read", dev->name, "register", ret); | |
128 | ||
129 | if (!(reg % 16)) | |
130 | printf("\n0x%02x: ", reg); | |
131 | ||
132 | printf("%2.2x ", value); | |
133 | } | |
134 | printf("\n"); | |
135 | ||
136 | return CMD_RET_SUCCESS; | |
137 | } | |
138 | ||
139 | static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
140 | { | |
141 | struct udevice *dev; | |
142 | int regs, ret; | |
143 | uint8_t value; | |
144 | uint reg; | |
145 | ||
146 | if (!currdev) | |
147 | return failed("get", "current", "device", -ENODEV); | |
148 | ||
149 | dev = currdev; | |
150 | ||
151 | if (argc != 2) | |
152 | return CMD_RET_USAGE; | |
153 | ||
154 | reg = simple_strtoul(argv[1], NULL, 0); | |
155 | regs = pmic_reg_count(dev); | |
156 | if (reg > regs) { | |
157 | printf("Pmic max reg: %d\n", regs); | |
158 | return failed("read", "given", "address", -EFAULT); | |
159 | } | |
160 | ||
161 | ret = pmic_read(dev, reg, &value, 1); | |
162 | if (ret) | |
163 | return failed("read", dev->name, "register", ret); | |
164 | ||
165 | printf("0x%02x: 0x%2.2x\n", reg, value); | |
166 | ||
167 | return CMD_RET_SUCCESS; | |
168 | } | |
169 | ||
170 | static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
171 | { | |
172 | struct udevice *dev; | |
173 | int regs, ret; | |
174 | uint8_t value; | |
175 | uint reg; | |
176 | ||
177 | if (!currdev) | |
178 | return failed("get", "current", "device", -ENODEV); | |
179 | ||
180 | dev = currdev; | |
181 | ||
182 | if (argc != 3) | |
183 | return CMD_RET_USAGE; | |
184 | ||
185 | reg = simple_strtoul(argv[1], NULL, 0); | |
186 | regs = pmic_reg_count(dev); | |
187 | if (reg > regs) { | |
188 | printf("Pmic max reg: %d\n", regs); | |
189 | return failed("write", "given", "address", -EFAULT); | |
190 | } | |
191 | ||
192 | value = simple_strtoul(argv[2], NULL, 0); | |
193 | ||
194 | ret = pmic_write(dev, reg, &value, 1); | |
195 | if (ret) | |
196 | return failed("write", dev->name, "register", ret); | |
197 | ||
198 | return CMD_RET_SUCCESS; | |
199 | } | |
200 | ||
201 | static cmd_tbl_t subcmd[] = { | |
202 | U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), | |
203 | U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), | |
204 | U_BOOT_CMD_MKENT(dump, 1, 1, do_dump, "", ""), | |
205 | U_BOOT_CMD_MKENT(read, 2, 1, do_read, "", ""), | |
206 | U_BOOT_CMD_MKENT(write, 3, 1, do_write, "", ""), | |
207 | }; | |
208 | ||
209 | static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, | |
210 | char * const argv[]) | |
211 | { | |
212 | cmd_tbl_t *cmd; | |
213 | ||
214 | argc--; | |
215 | argv++; | |
216 | ||
217 | cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd)); | |
218 | if (cmd == NULL || argc > cmd->maxargs) | |
219 | return CMD_RET_USAGE; | |
220 | ||
221 | return cmd->cmd(cmdtp, flag, argc, argv); | |
222 | } | |
223 | ||
224 | U_BOOT_CMD(pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, | |
225 | " operations", | |
226 | "list - list pmic devices\n" | |
227 | "pmic dev [id] - show or [set] operating pmic device\n" | |
228 | "pmic dump - dump registers\n" | |
229 | "pmic read address - read byte of register at address\n" | |
230 | "pmic write address - write byte to register at address\n" | |
231 | ); |