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 <common.h>
7 #include <command.h>
8 #include <errno.h>
9 #include <dm.h>
10 #include <dm/uclass-internal.h>
11 #include <power/pmic.h>
12 
13 #define LIMIT_DEV	32
14 #define LIMIT_PARENT	20
15 
16 static struct udevice *currdev;
17 
failure(int ret)18 static int failure(int ret)
19 {
20 	printf("Error: %d (%s)\n", ret, errno_str(ret));
21 
22 	return CMD_RET_FAILURE;
23 }
24 
do_dev(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])25 static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
26 {
27 	char *name;
28 	int ret = -ENODEV;
29 
30 	switch (argc) {
31 	case 2:
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 		}
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;
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(UCLASS_PMIC, &dev); dev;
62 	     ret = uclass_next_device(&dev)) {
63 		if (ret)
64 			continue;
65 
66 		printf("| %-*.*s| %-*.*s| %s @ %d\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 	}
71 
72 	if (ret)
73 		return CMD_RET_FAILURE;
74 
75 	return CMD_RET_SUCCESS;
76 }
77 
do_dump(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])78 static int do_dump(struct cmd_tbl *cmdtp, int flag, int argc,
79 		   char *const argv[])
80 {
81 	struct uc_pmic_priv *priv;
82 	struct udevice *dev;
83 	char fmt[16];
84 	uint reg;
85 	int ret;
86 
87 	if (!currdev) {
88 		printf("First, set the PMIC device!\n");
89 		return CMD_RET_USAGE;
90 	}
91 
92 	dev = currdev;
93 	priv = dev_get_uclass_priv(dev);
94 	printf("Dump pmic: %s registers\n", dev->name);
95 
96 	sprintf(fmt, "%%%d.%dx ", priv->trans_len * 2,
97 		priv->trans_len * 2);
98 
99 	for (reg = 0; reg < pmic_reg_count(dev); reg++) {
100 		ret = pmic_reg_read(dev, reg);
101 		if (ret < 0 && ret != -ENODATA) {
102 			printf("Can't read register: %d\n", reg);
103 			return failure(ret);
104 		}
105 
106 		if (!(reg % 16))
107 			printf("\n0x%02x: ", reg);
108 
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 		}
118 	}
119 	printf("\n");
120 
121 	return CMD_RET_SUCCESS;
122 }
123 
do_read(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])124 static int do_read(struct cmd_tbl *cmdtp, int flag, int argc,
125 		   char *const argv[])
126 {
127 	struct uc_pmic_priv *priv;
128 	struct udevice *dev;
129 	int regs, ret;
130 	char fmt[24];
131 	uint reg;
132 
133 	if (!currdev) {
134 		printf("First, set the PMIC device!\n");
135 		return CMD_RET_USAGE;
136 	}
137 
138 	dev = currdev;
139 	priv = dev_get_uclass_priv(dev);
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) {
147 		printf("PMIC max reg: %d\n", regs);
148 		return failure(-EFAULT);
149 	}
150 
151 	ret = pmic_reg_read(dev, reg);
152 	if (ret < 0) {
153 		printf("Can't read PMIC register: %d!\n", reg);
154 		return failure(ret);
155 	}
156 
157 	sprintf(fmt, "0x%%02x: 0x%%%d.%dx\n", priv->trans_len * 2,
158 		priv->trans_len * 2);
159 	printf(fmt, reg, ret);
160 
161 	return CMD_RET_SUCCESS;
162 }
163 
do_write(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])164 static int do_write(struct cmd_tbl *cmdtp, int flag, int argc,
165 		    char *const argv[])
166 {
167 	struct udevice *dev;
168 	uint reg, value;
169 	int regs, ret;
170 
171 	if (!currdev) {
172 		printf("First, set the PMIC device!\n");
173 		return CMD_RET_USAGE;
174 	}
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) {
184 		printf("PMIC max reg: %d\n", regs);
185 		return failure(-EFAULT);
186 	}
187 
188 	value = simple_strtoul(argv[2], NULL, 0);
189 
190 	ret = pmic_reg_write(dev, reg, value);
191 	if (ret) {
192 		printf("Can't write PMIC register: %d!\n", reg);
193 		return failure(ret);
194 	}
195 
196 	return CMD_RET_SUCCESS;
197 }
198 
199 static struct cmd_tbl subcmd[] = {
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 
do_pmic(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])207 static int do_pmic(struct cmd_tbl *cmdtp, int flag, int argc,
208 		   char *const argv[])
209 {
210 	struct cmd_tbl *cmd;
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,
223 	"PMIC sub-system",
224 	"list          - list pmic devices\n"
225 	"pmic dev [name]    - show or [set] operating PMIC device\n"
226 	"pmic dump          - dump registers\n"
227 	"pmic read address  - read byte of register at address\n"
228 	"pmic write address - write byte to register at address\n"
229 );
230