Merge branch 'master' of git://git.denx.de/u-boot-fsl-qoriq
[platform/kernel/u-boot.git] / drivers / gpio / sx151x.c
1 /*
2  * (C) Copyright 2013
3  * Viktar Palstsiuk, Promwad, viktar.palstsiuk@promwad.com
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * Driver for Semtech SX151x SPI GPIO Expanders
10  */
11
12 #include <common.h>
13 #include <spi.h>
14 #include <sx151x.h>
15
16 #ifndef CONFIG_SX151X_SPI_BUS
17 #define CONFIG_SX151X_SPI_BUS 0
18 #endif
19
20 /*
21  * The SX151x registers
22  */
23
24 #ifdef CONFIG_SX151X_GPIO_COUNT_8
25 /* 8bit: SX1511 */
26 #define SX151X_REG_DIR          0x07
27 #define SX151X_REG_DATA         0x08
28 #else
29 /* 16bit: SX1512 */
30 #define SX151X_REG_DIR          0x0F
31 #define SX151X_REG_DATA         0x11
32 #endif
33 #define SX151X_REG_RESET        0x7D
34
35 static int sx151x_spi_write(int chip, unsigned char reg, unsigned char val)
36 {
37         struct spi_slave *slave;
38         unsigned char buf[2];
39         int ret;
40
41         slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
42                                 SPI_MODE_0);
43         if (!slave)
44                 return 0;
45
46         spi_claim_bus(slave);
47
48         buf[0] = reg;
49         buf[1] = val;
50
51         ret = spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
52         if (ret < 0)
53                 printf("spi%d.%d write fail: can't write %02x to %02x: %d\n",
54                         CONFIG_SX151X_SPI_BUS, chip, val, reg, ret);
55         else
56                 printf("spi%d.%d write 0x%02x to register 0x%02x\n",
57                        CONFIG_SX151X_SPI_BUS, chip, val, reg);
58         spi_release_bus(slave);
59         spi_free_slave(slave);
60
61         return ret;
62 }
63
64 static int sx151x_spi_read(int chip, unsigned char reg)
65 {
66         struct spi_slave *slave;
67         int ret;
68
69         slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
70                                 SPI_MODE_0);
71         if (!slave)
72                 return 0;
73
74         spi_claim_bus(slave);
75
76         ret = spi_w8r8(slave, reg | 0x80);
77         if (ret < 0)
78                 printf("spi%d.%d read fail: can't read %02x: %d\n",
79                         CONFIG_SX151X_SPI_BUS, chip, reg, ret);
80         else
81                 printf("spi%d.%d read register 0x%02x: 0x%02x\n",
82                        CONFIG_SX151X_SPI_BUS, chip, reg, ret);
83
84         spi_release_bus(slave);
85         spi_free_slave(slave);
86
87         return ret;
88 }
89
90 static inline void sx151x_find_cfg(int gpio, unsigned char *reg, unsigned char *mask)
91 {
92         *reg   -= gpio / 8;
93         *mask   = 1 << (gpio % 8);
94 }
95
96 static int sx151x_write_cfg(int chip, unsigned char gpio, unsigned char reg, int val)
97 {
98         unsigned char  mask;
99         unsigned char  data;
100         int ret;
101
102         sx151x_find_cfg(gpio, &reg, &mask);
103         ret = sx151x_spi_read(chip, reg);
104         if (ret < 0)
105                 return ret;
106         else
107                 data = ret;
108         data &= ~mask;
109         data |= (val << (gpio % 8)) & mask;
110         return sx151x_spi_write(chip, reg, data);
111 }
112
113 int sx151x_get_value(int chip, int gpio)
114 {
115         unsigned char  reg = SX151X_REG_DATA;
116         unsigned char  mask;
117         int ret;
118
119         sx151x_find_cfg(gpio, &reg, &mask);
120         ret = sx151x_spi_read(chip, reg);
121         if (ret >= 0)
122                 ret = (ret & mask) != 0 ? 1 : 0;
123
124         return ret;
125 }
126
127 int sx151x_set_value(int chip, int gpio, int val)
128 {
129         return sx151x_write_cfg(chip, gpio, SX151X_REG_DATA, (val ? 1 : 0));
130 }
131
132 int sx151x_direction_input(int chip, int gpio)
133 {
134         return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 1);
135 }
136
137 int sx151x_direction_output(int chip, int gpio)
138 {
139         return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 0);
140 }
141
142 int sx151x_reset(int chip)
143 {
144         int err;
145
146         err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x12);
147         if (err < 0)
148                 return err;
149
150         err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x34);
151         return err;
152 }
153
154 #ifdef CONFIG_CMD_SX151X
155
156 int do_sx151x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
157 {
158         int ret = CMD_RET_USAGE, chip = 0, gpio = 0, val = 0;
159
160         if (argc < 3)
161                 return CMD_RET_USAGE;
162
163         /* arg2 used as chip number */
164         chip = simple_strtoul(argv[2], NULL, 10);
165
166         if (strcmp(argv[1], "reset") == 0) {
167                 ret = sx151x_reset(chip);
168                 if (!ret) {
169                         printf("Device at spi%d.%d was reset\n",
170                                CONFIG_SX151X_SPI_BUS, chip);
171                 }
172                 return ret;
173         }
174
175         if (argc < 4)
176                 return CMD_RET_USAGE;
177
178         /* arg3 used as gpio number */
179         gpio = simple_strtoul(argv[3], NULL, 10);
180
181         if (strcmp(argv[1], "get") == 0) {
182                 ret = sx151x_get_value(chip, gpio);
183                 if (ret < 0)
184                         printf("Failed to get value at spi%d.%d gpio %d\n",
185                                CONFIG_SX151X_SPI_BUS, chip, gpio);
186                 else {
187                         printf("Value at spi%d.%d gpio %d is %d\n",
188                                CONFIG_SX151X_SPI_BUS, chip, gpio, ret);
189                         ret = 0;
190                 }
191                 return ret;
192         }
193
194         if (argc < 5)
195                 return CMD_RET_USAGE;
196
197         /* arg4 used as value or direction */
198         val = simple_strtoul(argv[4], NULL, 10);
199
200         if (strcmp(argv[1], "set") == 0) {
201                 ret = sx151x_set_value(chip, gpio, val);
202                 if (ret < 0)
203                         printf("Failed to set value at spi%d.%d gpio %d\n",
204                                CONFIG_SX151X_SPI_BUS, chip, gpio);
205                 else
206                         printf("New value at spi%d.%d gpio %d is %d\n",
207                                CONFIG_SX151X_SPI_BUS, chip, gpio, val);
208                 return ret;
209         } else if (strcmp(argv[1], "dir") == 0) {
210                 if (val == 0)
211                         ret = sx151x_direction_output(chip, gpio);
212                 else
213                         ret = sx151x_direction_input(chip, gpio);
214
215                 if (ret < 0)
216                         printf("Failed to set direction of spi%d.%d gpio %d\n",
217                                CONFIG_SX151X_SPI_BUS, chip, gpio);
218                 else
219                         printf("New direction of spi%d.%d gpio %d is %d\n",
220                                CONFIG_SX151X_SPI_BUS, chip, gpio, val);
221                 return ret;
222         }
223
224         printf("Please see usage\n");
225
226         return ret;
227 }
228
229 U_BOOT_CMD(
230         sx151x, 5,      1,      do_sx151x,
231         "sx151x gpio access",
232         "dir chip gpio 0|1\n"
233         "       - set gpio direction (0 for output, 1 for input)\n"
234         "sx151x get chip gpio\n"
235         "       - get gpio value\n"
236         "sx151x set chip gpio 0|1\n"
237         "       - set gpio value\n"
238         "sx151x reset chip\n"
239         "       - reset chip"
240 );
241
242 #endif /* CONFIG_CMD_SX151X */