1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014-2015 Samsung Electronics
4  * Przemyslaw Marczak <p.marczak@samsung.com>
5  */
6 #include <command.h>
7 #include <errno.h>
8 #include <dm.h>
9 #include <dm/uclass-internal.h>
10 #include <power/pmic.h>
11 
12 #define LIMIT_DEV	32
13 #define LIMIT_PARENT	20
14 
15 static struct udevice *currdev;
16 
failure(int ret)17 static int failure(int ret)
18 {
19 	printf("Error: %d (%s)\n", ret, errno_str(ret));
20 
21 	return CMD_RET_FAILURE;
22 }
23 
do_dev(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])24 static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
25 {
26 	char *name;
27 	int ret = -ENODEV;
28 
29 	switch (argc) {
30 	case 2:
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 		}
37 		fallthrough;
38 	case 1:
39 		if (!currdev) {
40 			printf("PMIC device is not set!\n\n");
41 			return CMD_RET_USAGE;
42 		}
43 
44 		printf("dev: %d @ %s\n", dev_seq(currdev), currdev->name);
45 	}
46 
47 	return CMD_RET_SUCCESS;
48 }
49 
do_list(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])50 static int do_list(struct cmd_tbl *cmdtp, int flag, int argc,
51 		   char *const argv[])
52 {
53 	struct udevice *dev;
54 	int ret, err = 0;
55 
56 	printf("| %-*.*s| %-*.*s| %s @ %s\n",
57 	       LIMIT_DEV, LIMIT_DEV, "Name",
58 	       LIMIT_PARENT, LIMIT_PARENT, "Parent name",
59 	       "Parent uclass", "seq");
60 
61 	for (ret = uclass_first_device_check(UCLASS_PMIC, &dev); dev;
62 	     ret = uclass_next_device_check(&dev)) {
63 		if (ret)
64 			err = ret;
65 
66 		printf("| %-*.*s| %-*.*s| %s @ %d | status: %i\n",
67 		       LIMIT_DEV, LIMIT_DEV, dev->name,
68 		       LIMIT_PARENT, LIMIT_PARENT, dev->parent->name,
69 		       dev_get_uclass_name(dev->parent), dev_seq(dev->parent),
70 		       ret);
71 	}
72 
73 	if (err)
74 		return CMD_RET_FAILURE;
75 
76 	return CMD_RET_SUCCESS;
77 }
78 
do_dump(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])79 static int do_dump(struct cmd_tbl *cmdtp, int flag, int argc,
80 		   char *const argv[])
81 {
82 	struct uc_pmic_priv *priv;
83 	struct udevice *dev;
84 	char fmt[16];
85 	uint reg;
86 	int ret;
87 
88 	if (!currdev) {
89 		printf("First, set the PMIC device!\n");
90 		return CMD_RET_USAGE;
91 	}
92 
93 	dev = currdev;
94 	priv = dev_get_uclass_priv(dev);
95 	printf("Dump pmic: %s registers\n", dev->name);
96 
97 	sprintf(fmt, "%%%d.%dx ", priv->trans_len * 2,
98 		priv->trans_len * 2);
99 
100 	for (reg = 0; reg < pmic_reg_count(dev); reg++) {
101 		ret = pmic_reg_read(dev, reg);
102 		if (ret < 0 && ret != -ENODATA) {
103 			printf("Can't read register: %d\n", reg);
104 			return failure(ret);
105 		}
106 
107 		if (!(reg % 16))
108 			printf("\n0x%02x: ", reg);
109 
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 		}
119 	}
120 	printf("\n");
121 
122 	return CMD_RET_SUCCESS;
123 }
124 
do_read(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])125 static int do_read(struct cmd_tbl *cmdtp, int flag, int argc,
126 		   char *const argv[])
127 {
128 	struct uc_pmic_priv *priv;
129 	struct udevice *dev;
130 	int regs, ret;
131 	char fmt[24];
132 	uint reg;
133 
134 	if (!currdev) {
135 		printf("First, set the PMIC device!\n");
136 		return CMD_RET_USAGE;
137 	}
138 
139 	dev = currdev;
140 	priv = dev_get_uclass_priv(dev);
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) {
148 		printf("PMIC max reg: %d\n", regs);
149 		return failure(-EFAULT);
150 	}
151 
152 	ret = pmic_reg_read(dev, reg);
153 	if (ret < 0) {
154 		printf("Can't read PMIC register: %d!\n", reg);
155 		return failure(ret);
156 	}
157 
158 	sprintf(fmt, "0x%%02x: 0x%%%d.%dx\n", priv->trans_len * 2,
159 		priv->trans_len * 2);
160 	printf(fmt, reg, ret);
161 
162 	return CMD_RET_SUCCESS;
163 }
164 
do_write(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])165 static int do_write(struct cmd_tbl *cmdtp, int flag, int argc,
166 		    char *const argv[])
167 {
168 	struct udevice *dev;
169 	uint reg, value;
170 	int regs, ret;
171 
172 	if (!currdev) {
173 		printf("First, set the PMIC device!\n");
174 		return CMD_RET_USAGE;
175 	}
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) {
185 		printf("PMIC max reg: %d\n", regs);
186 		return failure(-EFAULT);
187 	}
188 
189 	value = simple_strtoul(argv[2], NULL, 0);
190 
191 	ret = pmic_reg_write(dev, reg, value);
192 	if (ret) {
193 		printf("Can't write PMIC register: %d!\n", reg);
194 		return failure(ret);
195 	}
196 
197 	return CMD_RET_SUCCESS;
198 }
199 
200 static struct cmd_tbl subcmd[] = {
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 
do_pmic(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])208 static int do_pmic(struct cmd_tbl *cmdtp, int flag, int argc,
209 		   char *const argv[])
210 {
211 	struct cmd_tbl *cmd;
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,
224 	"PMIC sub-system",
225 	"list          - list pmic devices\n"
226 	"pmic dev [name]    - show or [set] operating PMIC device\n"
227 	"pmic dump          - dump registers\n"
228 	"pmic read <reg>    - read byte of 'reg' register\n"
229 	"pmic write <reg> <byte> - write 'byte' byte to 'reg' register\n"
230 );
231