]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - cmd/spmi.c
fd80b3a7d8cbe19503f35f8d41f1e50d4703b96f
[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;
58         int ret;
59         struct udevice *dev;
60
61         if (argc != 4)
62                 return cmd_usage(cmdtp);
63
64         ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
65         if (ret) {
66                 printf("Failed to get SPMI bus: %d\n", ret);
67                 return CMD_RET_FAILURE;
68         }
69
70         /*
71          * SPMI chip address
72          */
73         sid = simple_strtoul(argv[1], NULL, 16);
74
75         /*
76          * SPMI data address within the chip.  This can be 1 or
77          * 2 bytes long.  Some day it might be 3 bytes long :-).
78          */
79         pid = simple_strtoul(argv[2], NULL, 16);
80         reg = simple_strtoul(argv[3], NULL, 16);
81
82         ret = spmi_reg_read(dev, sid, pid, reg);
83         if (ret < 0)
84                 return spmi_report_err(ret, SPMI_ERR_READ);
85
86         printf("%02x\n", ret);
87         return CMD_RET_SUCCESS;
88 }
89
90 static int do_spmi_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
91 {
92         uint sid, pid, reg;
93         uint val;
94         int ret;
95         struct udevice *dev;
96
97         if (argc != 5)
98                 return cmd_usage(cmdtp);
99
100         ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
101         if (ret) {
102                 printf("Failed to get SPMI bus: %d\n", ret);
103                 return CMD_RET_FAILURE;
104         }
105
106         /*
107          * SPMI chip address
108          */
109         sid = simple_strtoul(argv[1], NULL, 16);
110         pid = simple_strtoul(argv[2], NULL, 16);
111         reg = simple_strtoul(argv[3], NULL, 16);
112         val = simple_strtoul(argv[4], NULL, 16);
113         if (val > 255) {
114                 printf("Value %08x out of range [0..255]\n", val);
115                 return CMD_RET_FAILURE;
116         }
117
118         ret = spmi_reg_write(dev, sid, pid, reg, val);
119         if (ret)
120                 return spmi_report_err(ret, SPMI_ERR_WRITE);
121
122         return CMD_RET_SUCCESS;
123 }
124
125 static cmd_tbl_t cmd_spmi_sub[] = {
126         U_BOOT_CMD_MKENT(read, 4, 1, do_spmi_read, "", ""),
127         U_BOOT_CMD_MKENT(write, 5, 0, do_spmi_write, "", ""),
128 };
129
130 static __maybe_unused void spmi_reloc(void)
131 {
132         static int relocated;
133
134         if (!relocated) {
135                 fixup_cmdtable(cmd_spmi_sub, ARRAY_SIZE(cmd_spmi_sub));
136                 relocated = 1;
137         };
138 }
139
140 /**
141  * do_spmi() - Handle the "spmi" command-line command
142  * @cmdtp:      Command data struct pointer
143  * @flag:       Command flag
144  * @argc:       Command-line argument count
145  * @argv:       Array of command-line arguments
146  *
147  * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
148  * on error.
149  */
150 static int do_spmi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
151 {
152         cmd_tbl_t *c;
153
154 #ifdef CONFIG_NEEDS_MANUAL_RELOC
155         spmi_reloc();
156 #endif
157
158         if (argc < 2)
159                 return CMD_RET_USAGE;
160
161         /* Strip off leading 'spmi' command argument */
162         argc--;
163         argv++;
164
165         c = find_cmd_tbl(argv[0], cmd_spmi_sub, ARRAY_SIZE(cmd_spmi_sub));
166
167         if (c)
168                 return c->cmd(cmdtp, flag, argc, argv);
169         else
170                 printf("subcommand '%s' not found\n", argv[0]);
171         return CMD_RET_USAGE;
172 }
173
174 #ifdef CONFIG_SYS_LONGHELP
175 static char spmi_help_text[] =
176         "\tspmi read <sid> <pid> <reg>         - read register <reg> of peripheral <pid> on slave <sid>\n"
177         "\tspmi write <sid> <pid> <reg> <val>  - write <val> to register <reg> of peripheral <pid> on slave <sid>\n"
178         ;
179 #endif
180
181 U_BOOT_CMD(
182         spmi, 6, 1, do_spmi,
183         "SPMI sub-system",
184         spmi_help_text
185 );