]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - cmd/spmi.c
cmd: pmic: use base 16 for command arguments
[karo-tx-uboot.git] / cmd / spmi.c
1 /*
2  * (C) Copyright 2017 Lothar Waßmann <LW@KARO-electronics.de>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  *
6  * based on: cmd/i2c.c
7  *   (C) Copyright 2009
8  *   Sergey Kubushyn, himself, ksi@koi8.net
9  *
10  *   (C) Copyright 2001
11  *   Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
12  */
13
14 #include <common.h>
15 #include <cli.h>
16 #include <command.h>
17 #include <console.h>
18 #include <dm.h>
19 #include <environment.h>
20 #include <errno.h>
21 #include <malloc.h>
22 #include <asm/byteorder.h>
23 #include <linux/compiler.h>
24 #include <spmi/spmi.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 enum spmi_err_op {
29         SPMI_ERR_READ,
30         SPMI_ERR_WRITE,
31 };
32
33 static int spmi_report_err(int ret, enum spmi_err_op op)
34 {
35         printf("Error %s the chip: %d\n",
36                op == SPMI_ERR_READ ? "reading" : "writing", ret);
37
38         return CMD_RET_FAILURE;
39 }
40
41 /**
42  * do_spmi_read() - Handle the "spmi read" command-line command
43  * @cmdtp:      Command data struct pointer
44  * @flag:       Command flag
45  * @argc:       Command-line argument count
46  * @argv:       Array of command-line arguments
47  *
48  * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
49  * on error.
50  *
51  * Syntax:
52  *      spmi read {spmi_chip} {devaddr}{.0, .1, .2} {len} {memaddr}
53  */
54 static int do_spmi_read(cmd_tbl_t *cmdtp, int flag, int argc,
55                         char *const argv[])
56 {
57         uint sid, pid, reg, cnt = 1;
58         uint8_t buf[8];
59         int ret;
60         int i;
61         struct udevice *dev;
62
63         if (argc < 4 || argc > 5)
64                 return cmd_usage(cmdtp);
65
66         ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
67         if (ret) {
68                 printf("Failed to get SPMI bus: %d\n", ret);
69                 return CMD_RET_FAILURE;
70         }
71
72         /* SPMI slave ID */
73         sid = simple_strtoul(argv[1], NULL, 16);
74         if (sid > 5) {
75                 printf("SID %02x out of range 0..5\n", sid);
76                 return CMD_RET_FAILURE;
77         }
78
79         /* SPMI peripheral ID */
80         pid = simple_strtoul(argv[2], NULL, 16);
81         if (pid > 255) {
82                 printf("PID %02x out of range 0x00..0xff\n", pid);
83                 return CMD_RET_FAILURE;
84         }
85
86         /* SPMI register offset */
87         reg = simple_strtoul(argv[3], NULL, 16);
88         if (reg > 255) {
89                 printf("REG offset %02x out of range 0x00..0xff\n", reg);
90                 return CMD_RET_FAILURE;
91         }
92
93         /* SPMI byte count */
94         if (argc > 4) {
95                 cnt = simple_strtoul(argv[4], NULL, 16);
96                 if (cnt == 0 || cnt > sizeof(buf)) {
97                         printf("Byte count %u out of range 1..%lu\n",
98                                 cnt, sizeof(buf));
99                         return CMD_RET_FAILURE;
100                 }
101         }
102
103         debug("%s@%d: Reading SID %02x PID %02x REG %02x\n", __func__, __LINE__,
104                 sid, pid, reg);
105         ret = spmi_read(dev, buf, sid, pid, reg, cnt);
106         if (ret < 0)
107                 return spmi_report_err(ret, SPMI_ERR_READ);
108
109         for (i = 0; i < cnt; i++)
110                 printf("%02x\n", buf[i]);
111
112         return CMD_RET_SUCCESS;
113 }
114
115 static int do_spmi_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
116 {
117         uint sid, pid, reg;
118         uint val;
119         int ret;
120         struct udevice *dev;
121
122         if (argc != 5)
123                 return cmd_usage(cmdtp);
124
125         ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
126         if (ret) {
127                 printf("Failed to get SPMI bus: %d\n", ret);
128                 return CMD_RET_FAILURE;
129         }
130
131         /*
132          * SPMI chip address
133          */
134         sid = simple_strtoul(argv[1], NULL, 16);
135         pid = simple_strtoul(argv[2], NULL, 16);
136         reg = simple_strtoul(argv[3], NULL, 16);
137         val = simple_strtoul(argv[4], NULL, 16);
138         if (val > 255) {
139                 printf("Value %08x out of range [0..255]\n", val);
140                 return CMD_RET_FAILURE;
141         }
142
143         debug("%s@%d: Writing SID %02x PID %02x REG %02x value %02x\n",
144                 __func__, __LINE__, sid, pid, reg, val);
145         ret = spmi_reg_write(dev, sid, pid, reg, val);
146         if (ret)
147                 return spmi_report_err(ret, SPMI_ERR_WRITE);
148
149         return CMD_RET_SUCCESS;
150 }
151
152 static cmd_tbl_t cmd_spmi_sub[] = {
153         U_BOOT_CMD_MKENT(read, 4, 1, do_spmi_read, "", ""),
154         U_BOOT_CMD_MKENT(write, 5, 0, do_spmi_write, "", ""),
155 };
156
157 static __maybe_unused void spmi_reloc(void)
158 {
159         static int relocated;
160
161         if (!relocated) {
162                 fixup_cmdtable(cmd_spmi_sub, ARRAY_SIZE(cmd_spmi_sub));
163                 relocated = 1;
164         };
165 }
166
167 /**
168  * do_spmi() - Handle the "spmi" command-line command
169  * @cmdtp:      Command data struct pointer
170  * @flag:       Command flag
171  * @argc:       Command-line argument count
172  * @argv:       Array of command-line arguments
173  *
174  * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
175  * on error.
176  */
177 static int do_spmi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
178 {
179         cmd_tbl_t *c;
180
181 #ifdef CONFIG_NEEDS_MANUAL_RELOC
182         spmi_reloc();
183 #endif
184
185         if (argc < 2)
186                 return CMD_RET_USAGE;
187
188         /* Strip off leading 'spmi' command argument */
189         argc--;
190         argv++;
191
192         c = find_cmd_tbl(argv[0], cmd_spmi_sub, ARRAY_SIZE(cmd_spmi_sub));
193
194         if (c)
195                 return c->cmd(cmdtp, flag, argc, argv);
196         else
197                 printf("subcommand '%s' not found\n", argv[0]);
198         return CMD_RET_USAGE;
199 }
200
201 #ifdef CONFIG_SYS_LONGHELP
202 static char spmi_help_text[] =
203         "\tspmi read <sid> <pid> <reg>         - read register <reg> of peripheral <pid> on slave <sid>\n"
204         "\tspmi write <sid> <pid> <reg> <val>  - write <val> to register <reg> of peripheral <pid> on slave <sid>\n"
205         ;
206 #endif
207
208 U_BOOT_CMD(
209         spmi, 6, 1, do_spmi,
210         "SPMI sub-system",
211         spmi_help_text
212 );