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