usb: kbd: Prevent out of bound access
[platform/kernel/u-boot.git] / common / cmd_pmic.c
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_DEV       32
14 #define LIMIT_PARENT    20
15
16 static struct udevice *currdev;
17
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
25 static int do_dev(cmd_tbl_t *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", currdev->seq, currdev->name);
45         }
46
47         return CMD_RET_SUCCESS;
48 }
49
50 static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
51 {
52         struct udevice *dev;
53         int ret;
54
55         printf("| %-*.*s| %-*.*s| %s @ %s\n",
56                LIMIT_DEV, LIMIT_DEV, "Name",
57                LIMIT_PARENT, LIMIT_PARENT, "Parent name",
58                "Parent uclass", "seq");
59
60         for (ret = uclass_first_device(UCLASS_PMIC, &dev); dev;
61              ret = uclass_next_device(&dev)) {
62                 if (ret)
63                         continue;
64
65                 printf("| %-*.*s| %-*.*s| %s @ %d\n",
66                        LIMIT_DEV, LIMIT_DEV, dev->name,
67                        LIMIT_PARENT, LIMIT_PARENT, dev->parent->name,
68                        dev_get_uclass_name(dev->parent), dev->parent->seq);
69         }
70
71         if (ret)
72                 return CMD_RET_FAILURE;
73
74         return CMD_RET_SUCCESS;
75 }
76
77 static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
78 {
79         struct udevice *dev;
80         uint8_t value;
81         uint reg;
82         int ret;
83
84         if (!currdev) {
85                 printf("First, set the PMIC device!\n");
86                 return CMD_RET_USAGE;
87         }
88
89         dev = currdev;
90
91         printf("Dump pmic: %s registers\n", dev->name);
92
93         for (reg = 0; reg < pmic_reg_count(dev); reg++) {
94                 ret = pmic_read(dev, reg, &value, 1);
95                 if (ret) {
96                         printf("Can't read register: %d\n", reg);
97                         return failure(ret);
98                 }
99
100                 if (!(reg % 16))
101                         printf("\n0x%02x: ", reg);
102
103                 printf("%2.2x ", value);
104         }
105         printf("\n");
106
107         return CMD_RET_SUCCESS;
108 }
109
110 static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
111 {
112         struct udevice *dev;
113         int regs, ret;
114         uint8_t value;
115         uint reg;
116
117         if (!currdev) {
118                 printf("First, set the PMIC device!\n");
119                 return CMD_RET_USAGE;
120         }
121
122         dev = currdev;
123
124         if (argc != 2)
125                 return CMD_RET_USAGE;
126
127         reg = simple_strtoul(argv[1], NULL, 0);
128         regs = pmic_reg_count(dev);
129         if (reg > regs) {
130                 printf("PMIC max reg: %d\n", regs);
131                 return failure(-EFAULT);
132         }
133
134         ret = pmic_read(dev, reg, &value, 1);
135         if (ret) {
136                 printf("Can't read PMIC register: %d!\n", reg);
137                 return failure(ret);
138         }
139
140         printf("0x%02x: 0x%2.2x\n", reg, value);
141
142         return CMD_RET_SUCCESS;
143 }
144
145 static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
146 {
147         struct udevice *dev;
148         int regs, ret;
149         uint8_t value;
150         uint reg;
151
152         if (!currdev) {
153                 printf("First, set the PMIC device!\n");
154                 return CMD_RET_USAGE;
155         }
156
157         dev = currdev;
158
159         if (argc != 3)
160                 return CMD_RET_USAGE;
161
162         reg = simple_strtoul(argv[1], NULL, 0);
163         regs = pmic_reg_count(dev);
164         if (reg > regs) {
165                 printf("PMIC max reg: %d\n", regs);
166                 return failure(-EFAULT);
167         }
168
169         value = simple_strtoul(argv[2], NULL, 0);
170
171         ret = pmic_write(dev, reg, &value, 1);
172         if (ret) {
173                 printf("Can't write PMIC register: %d!\n", reg);
174                 return failure(ret);
175         }
176
177         return CMD_RET_SUCCESS;
178 }
179
180 static cmd_tbl_t subcmd[] = {
181         U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
182         U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
183         U_BOOT_CMD_MKENT(dump, 1, 1, do_dump, "", ""),
184         U_BOOT_CMD_MKENT(read, 2, 1, do_read, "", ""),
185         U_BOOT_CMD_MKENT(write, 3, 1, do_write, "", ""),
186 };
187
188 static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc,
189                         char * const argv[])
190 {
191         cmd_tbl_t *cmd;
192
193         argc--;
194         argv++;
195
196         cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd));
197         if (cmd == NULL || argc > cmd->maxargs)
198                 return CMD_RET_USAGE;
199
200         return cmd->cmd(cmdtp, flag, argc, argv);
201 }
202
203 U_BOOT_CMD(pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
204         " operations",
205         "list          - list pmic devices\n"
206         "pmic dev [name]    - show or [set] operating PMIC device\n"
207         "pmic dump          - dump registers\n"
208         "pmic read address  - read byte of register at address\n"
209         "pmic write address - write byte to register at address\n"
210 );