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