Commit 9a42a8a458c76c4583fcb5f8eaa336fd8157be20
Committed by
Greg Kroah-Hartman
1 parent
64f2260ea2
gpio: mcp23s08: handle default gpio base
commit b184c388f773f30b6c707d3d4599b2db80f4390c upstream. Create default gpio base if neither device node nor platform data is defined. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Tested-by: Antonio Fiol <antonio@fiol.es> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 10 additions and 7 deletions Inline Diff
drivers/gpio/gpio-mcp23s08.c
1 | /* | 1 | /* |
2 | * MCP23S08 SPI/I2C GPIO gpio expander driver | 2 | * MCP23S08 SPI/I2C GPIO gpio expander driver |
3 | * | 3 | * |
4 | * The inputs and outputs of the mcp23s08, mcp23s17, mcp23008 and mcp23017 are | 4 | * The inputs and outputs of the mcp23s08, mcp23s17, mcp23008 and mcp23017 are |
5 | * supported. | 5 | * supported. |
6 | * For the I2C versions of the chips (mcp23008 and mcp23017) generation of | 6 | * For the I2C versions of the chips (mcp23008 and mcp23017) generation of |
7 | * interrupts is also supported. | 7 | * interrupts is also supported. |
8 | * The hardware of the SPI versions of the chips (mcp23s08 and mcp23s17) is | 8 | * The hardware of the SPI versions of the chips (mcp23s08 and mcp23s17) is |
9 | * also capable of generating interrupts, but the linux driver does not | 9 | * also capable of generating interrupts, but the linux driver does not |
10 | * support that yet. | 10 | * support that yet. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/spi/mcp23s08.h> | 20 | #include <linux/spi/mcp23s08.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/byteorder.h> | 22 | #include <asm/byteorder.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
25 | #include <linux/of_device.h> | 25 | #include <linux/of_device.h> |
26 | 26 | ||
27 | /** | 27 | /** |
28 | * MCP types supported by driver | 28 | * MCP types supported by driver |
29 | */ | 29 | */ |
30 | #define MCP_TYPE_S08 0 | 30 | #define MCP_TYPE_S08 0 |
31 | #define MCP_TYPE_S17 1 | 31 | #define MCP_TYPE_S17 1 |
32 | #define MCP_TYPE_008 2 | 32 | #define MCP_TYPE_008 2 |
33 | #define MCP_TYPE_017 3 | 33 | #define MCP_TYPE_017 3 |
34 | 34 | ||
35 | /* Registers are all 8 bits wide. | 35 | /* Registers are all 8 bits wide. |
36 | * | 36 | * |
37 | * The mcp23s17 has twice as many bits, and can be configured to work | 37 | * The mcp23s17 has twice as many bits, and can be configured to work |
38 | * with either 16 bit registers or with two adjacent 8 bit banks. | 38 | * with either 16 bit registers or with two adjacent 8 bit banks. |
39 | */ | 39 | */ |
40 | #define MCP_IODIR 0x00 /* init/reset: all ones */ | 40 | #define MCP_IODIR 0x00 /* init/reset: all ones */ |
41 | #define MCP_IPOL 0x01 | 41 | #define MCP_IPOL 0x01 |
42 | #define MCP_GPINTEN 0x02 | 42 | #define MCP_GPINTEN 0x02 |
43 | #define MCP_DEFVAL 0x03 | 43 | #define MCP_DEFVAL 0x03 |
44 | #define MCP_INTCON 0x04 | 44 | #define MCP_INTCON 0x04 |
45 | #define MCP_IOCON 0x05 | 45 | #define MCP_IOCON 0x05 |
46 | # define IOCON_MIRROR (1 << 6) | 46 | # define IOCON_MIRROR (1 << 6) |
47 | # define IOCON_SEQOP (1 << 5) | 47 | # define IOCON_SEQOP (1 << 5) |
48 | # define IOCON_HAEN (1 << 3) | 48 | # define IOCON_HAEN (1 << 3) |
49 | # define IOCON_ODR (1 << 2) | 49 | # define IOCON_ODR (1 << 2) |
50 | # define IOCON_INTPOL (1 << 1) | 50 | # define IOCON_INTPOL (1 << 1) |
51 | #define MCP_GPPU 0x06 | 51 | #define MCP_GPPU 0x06 |
52 | #define MCP_INTF 0x07 | 52 | #define MCP_INTF 0x07 |
53 | #define MCP_INTCAP 0x08 | 53 | #define MCP_INTCAP 0x08 |
54 | #define MCP_GPIO 0x09 | 54 | #define MCP_GPIO 0x09 |
55 | #define MCP_OLAT 0x0a | 55 | #define MCP_OLAT 0x0a |
56 | 56 | ||
57 | struct mcp23s08; | 57 | struct mcp23s08; |
58 | 58 | ||
59 | struct mcp23s08_ops { | 59 | struct mcp23s08_ops { |
60 | int (*read)(struct mcp23s08 *mcp, unsigned reg); | 60 | int (*read)(struct mcp23s08 *mcp, unsigned reg); |
61 | int (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val); | 61 | int (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val); |
62 | int (*read_regs)(struct mcp23s08 *mcp, unsigned reg, | 62 | int (*read_regs)(struct mcp23s08 *mcp, unsigned reg, |
63 | u16 *vals, unsigned n); | 63 | u16 *vals, unsigned n); |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct mcp23s08 { | 66 | struct mcp23s08 { |
67 | u8 addr; | 67 | u8 addr; |
68 | 68 | ||
69 | u16 cache[11]; | 69 | u16 cache[11]; |
70 | u16 irq_rise; | 70 | u16 irq_rise; |
71 | u16 irq_fall; | 71 | u16 irq_fall; |
72 | int irq; | 72 | int irq; |
73 | bool irq_controller; | 73 | bool irq_controller; |
74 | /* lock protects the cached values */ | 74 | /* lock protects the cached values */ |
75 | struct mutex lock; | 75 | struct mutex lock; |
76 | struct mutex irq_lock; | 76 | struct mutex irq_lock; |
77 | struct irq_domain *irq_domain; | 77 | struct irq_domain *irq_domain; |
78 | 78 | ||
79 | struct gpio_chip chip; | 79 | struct gpio_chip chip; |
80 | 80 | ||
81 | const struct mcp23s08_ops *ops; | 81 | const struct mcp23s08_ops *ops; |
82 | void *data; /* ops specific data */ | 82 | void *data; /* ops specific data */ |
83 | }; | 83 | }; |
84 | 84 | ||
85 | /* A given spi_device can represent up to eight mcp23sxx chips | 85 | /* A given spi_device can represent up to eight mcp23sxx chips |
86 | * sharing the same chipselect but using different addresses | 86 | * sharing the same chipselect but using different addresses |
87 | * (e.g. chips #0 and #3 might be populated, but not #1 or $2). | 87 | * (e.g. chips #0 and #3 might be populated, but not #1 or $2). |
88 | * Driver data holds all the per-chip data. | 88 | * Driver data holds all the per-chip data. |
89 | */ | 89 | */ |
90 | struct mcp23s08_driver_data { | 90 | struct mcp23s08_driver_data { |
91 | unsigned ngpio; | 91 | unsigned ngpio; |
92 | struct mcp23s08 *mcp[8]; | 92 | struct mcp23s08 *mcp[8]; |
93 | struct mcp23s08 chip[]; | 93 | struct mcp23s08 chip[]; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /* This lock class tells lockdep that GPIO irqs are in a different | 96 | /* This lock class tells lockdep that GPIO irqs are in a different |
97 | * category than their parents, so it won't report false recursion. | 97 | * category than their parents, so it won't report false recursion. |
98 | */ | 98 | */ |
99 | static struct lock_class_key gpio_lock_class; | 99 | static struct lock_class_key gpio_lock_class; |
100 | 100 | ||
101 | /*----------------------------------------------------------------------*/ | 101 | /*----------------------------------------------------------------------*/ |
102 | 102 | ||
103 | #if IS_ENABLED(CONFIG_I2C) | 103 | #if IS_ENABLED(CONFIG_I2C) |
104 | 104 | ||
105 | static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) | 105 | static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) |
106 | { | 106 | { |
107 | return i2c_smbus_read_byte_data(mcp->data, reg); | 107 | return i2c_smbus_read_byte_data(mcp->data, reg); |
108 | } | 108 | } |
109 | 109 | ||
110 | static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | 110 | static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) |
111 | { | 111 | { |
112 | return i2c_smbus_write_byte_data(mcp->data, reg, val); | 112 | return i2c_smbus_write_byte_data(mcp->data, reg, val); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int | 115 | static int |
116 | mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | 116 | mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) |
117 | { | 117 | { |
118 | while (n--) { | 118 | while (n--) { |
119 | int ret = mcp23008_read(mcp, reg++); | 119 | int ret = mcp23008_read(mcp, reg++); |
120 | if (ret < 0) | 120 | if (ret < 0) |
121 | return ret; | 121 | return ret; |
122 | *vals++ = ret; | 122 | *vals++ = ret; |
123 | } | 123 | } |
124 | 124 | ||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg) | 128 | static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg) |
129 | { | 129 | { |
130 | return i2c_smbus_read_word_data(mcp->data, reg << 1); | 130 | return i2c_smbus_read_word_data(mcp->data, reg << 1); |
131 | } | 131 | } |
132 | 132 | ||
133 | static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | 133 | static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) |
134 | { | 134 | { |
135 | return i2c_smbus_write_word_data(mcp->data, reg << 1, val); | 135 | return i2c_smbus_write_word_data(mcp->data, reg << 1, val); |
136 | } | 136 | } |
137 | 137 | ||
138 | static int | 138 | static int |
139 | mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | 139 | mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) |
140 | { | 140 | { |
141 | while (n--) { | 141 | while (n--) { |
142 | int ret = mcp23017_read(mcp, reg++); | 142 | int ret = mcp23017_read(mcp, reg++); |
143 | if (ret < 0) | 143 | if (ret < 0) |
144 | return ret; | 144 | return ret; |
145 | *vals++ = ret; | 145 | *vals++ = ret; |
146 | } | 146 | } |
147 | 147 | ||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | static const struct mcp23s08_ops mcp23008_ops = { | 151 | static const struct mcp23s08_ops mcp23008_ops = { |
152 | .read = mcp23008_read, | 152 | .read = mcp23008_read, |
153 | .write = mcp23008_write, | 153 | .write = mcp23008_write, |
154 | .read_regs = mcp23008_read_regs, | 154 | .read_regs = mcp23008_read_regs, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static const struct mcp23s08_ops mcp23017_ops = { | 157 | static const struct mcp23s08_ops mcp23017_ops = { |
158 | .read = mcp23017_read, | 158 | .read = mcp23017_read, |
159 | .write = mcp23017_write, | 159 | .write = mcp23017_write, |
160 | .read_regs = mcp23017_read_regs, | 160 | .read_regs = mcp23017_read_regs, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | #endif /* CONFIG_I2C */ | 163 | #endif /* CONFIG_I2C */ |
164 | 164 | ||
165 | /*----------------------------------------------------------------------*/ | 165 | /*----------------------------------------------------------------------*/ |
166 | 166 | ||
167 | #ifdef CONFIG_SPI_MASTER | 167 | #ifdef CONFIG_SPI_MASTER |
168 | 168 | ||
169 | static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) | 169 | static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) |
170 | { | 170 | { |
171 | u8 tx[2], rx[1]; | 171 | u8 tx[2], rx[1]; |
172 | int status; | 172 | int status; |
173 | 173 | ||
174 | tx[0] = mcp->addr | 0x01; | 174 | tx[0] = mcp->addr | 0x01; |
175 | tx[1] = reg; | 175 | tx[1] = reg; |
176 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), rx, sizeof(rx)); | 176 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), rx, sizeof(rx)); |
177 | return (status < 0) ? status : rx[0]; | 177 | return (status < 0) ? status : rx[0]; |
178 | } | 178 | } |
179 | 179 | ||
180 | static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | 180 | static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) |
181 | { | 181 | { |
182 | u8 tx[3]; | 182 | u8 tx[3]; |
183 | 183 | ||
184 | tx[0] = mcp->addr; | 184 | tx[0] = mcp->addr; |
185 | tx[1] = reg; | 185 | tx[1] = reg; |
186 | tx[2] = val; | 186 | tx[2] = val; |
187 | return spi_write_then_read(mcp->data, tx, sizeof(tx), NULL, 0); | 187 | return spi_write_then_read(mcp->data, tx, sizeof(tx), NULL, 0); |
188 | } | 188 | } |
189 | 189 | ||
190 | static int | 190 | static int |
191 | mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | 191 | mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) |
192 | { | 192 | { |
193 | u8 tx[2], *tmp; | 193 | u8 tx[2], *tmp; |
194 | int status; | 194 | int status; |
195 | 195 | ||
196 | if ((n + reg) > sizeof(mcp->cache)) | 196 | if ((n + reg) > sizeof(mcp->cache)) |
197 | return -EINVAL; | 197 | return -EINVAL; |
198 | tx[0] = mcp->addr | 0x01; | 198 | tx[0] = mcp->addr | 0x01; |
199 | tx[1] = reg; | 199 | tx[1] = reg; |
200 | 200 | ||
201 | tmp = (u8 *)vals; | 201 | tmp = (u8 *)vals; |
202 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), tmp, n); | 202 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), tmp, n); |
203 | if (status >= 0) { | 203 | if (status >= 0) { |
204 | while (n--) | 204 | while (n--) |
205 | vals[n] = tmp[n]; /* expand to 16bit */ | 205 | vals[n] = tmp[n]; /* expand to 16bit */ |
206 | } | 206 | } |
207 | return status; | 207 | return status; |
208 | } | 208 | } |
209 | 209 | ||
210 | static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) | 210 | static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) |
211 | { | 211 | { |
212 | u8 tx[2], rx[2]; | 212 | u8 tx[2], rx[2]; |
213 | int status; | 213 | int status; |
214 | 214 | ||
215 | tx[0] = mcp->addr | 0x01; | 215 | tx[0] = mcp->addr | 0x01; |
216 | tx[1] = reg << 1; | 216 | tx[1] = reg << 1; |
217 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), rx, sizeof(rx)); | 217 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), rx, sizeof(rx)); |
218 | return (status < 0) ? status : (rx[0] | (rx[1] << 8)); | 218 | return (status < 0) ? status : (rx[0] | (rx[1] << 8)); |
219 | } | 219 | } |
220 | 220 | ||
221 | static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | 221 | static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) |
222 | { | 222 | { |
223 | u8 tx[4]; | 223 | u8 tx[4]; |
224 | 224 | ||
225 | tx[0] = mcp->addr; | 225 | tx[0] = mcp->addr; |
226 | tx[1] = reg << 1; | 226 | tx[1] = reg << 1; |
227 | tx[2] = val; | 227 | tx[2] = val; |
228 | tx[3] = val >> 8; | 228 | tx[3] = val >> 8; |
229 | return spi_write_then_read(mcp->data, tx, sizeof(tx), NULL, 0); | 229 | return spi_write_then_read(mcp->data, tx, sizeof(tx), NULL, 0); |
230 | } | 230 | } |
231 | 231 | ||
232 | static int | 232 | static int |
233 | mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | 233 | mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) |
234 | { | 234 | { |
235 | u8 tx[2]; | 235 | u8 tx[2]; |
236 | int status; | 236 | int status; |
237 | 237 | ||
238 | if ((n + reg) > sizeof(mcp->cache)) | 238 | if ((n + reg) > sizeof(mcp->cache)) |
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | tx[0] = mcp->addr | 0x01; | 240 | tx[0] = mcp->addr | 0x01; |
241 | tx[1] = reg << 1; | 241 | tx[1] = reg << 1; |
242 | 242 | ||
243 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), | 243 | status = spi_write_then_read(mcp->data, tx, sizeof(tx), |
244 | (u8 *)vals, n * 2); | 244 | (u8 *)vals, n * 2); |
245 | if (status >= 0) { | 245 | if (status >= 0) { |
246 | while (n--) | 246 | while (n--) |
247 | vals[n] = __le16_to_cpu((__le16)vals[n]); | 247 | vals[n] = __le16_to_cpu((__le16)vals[n]); |
248 | } | 248 | } |
249 | 249 | ||
250 | return status; | 250 | return status; |
251 | } | 251 | } |
252 | 252 | ||
253 | static const struct mcp23s08_ops mcp23s08_ops = { | 253 | static const struct mcp23s08_ops mcp23s08_ops = { |
254 | .read = mcp23s08_read, | 254 | .read = mcp23s08_read, |
255 | .write = mcp23s08_write, | 255 | .write = mcp23s08_write, |
256 | .read_regs = mcp23s08_read_regs, | 256 | .read_regs = mcp23s08_read_regs, |
257 | }; | 257 | }; |
258 | 258 | ||
259 | static const struct mcp23s08_ops mcp23s17_ops = { | 259 | static const struct mcp23s08_ops mcp23s17_ops = { |
260 | .read = mcp23s17_read, | 260 | .read = mcp23s17_read, |
261 | .write = mcp23s17_write, | 261 | .write = mcp23s17_write, |
262 | .read_regs = mcp23s17_read_regs, | 262 | .read_regs = mcp23s17_read_regs, |
263 | }; | 263 | }; |
264 | 264 | ||
265 | #endif /* CONFIG_SPI_MASTER */ | 265 | #endif /* CONFIG_SPI_MASTER */ |
266 | 266 | ||
267 | /*----------------------------------------------------------------------*/ | 267 | /*----------------------------------------------------------------------*/ |
268 | 268 | ||
269 | static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset) | 269 | static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset) |
270 | { | 270 | { |
271 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 271 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
272 | int status; | 272 | int status; |
273 | 273 | ||
274 | mutex_lock(&mcp->lock); | 274 | mutex_lock(&mcp->lock); |
275 | mcp->cache[MCP_IODIR] |= (1 << offset); | 275 | mcp->cache[MCP_IODIR] |= (1 << offset); |
276 | status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); | 276 | status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); |
277 | mutex_unlock(&mcp->lock); | 277 | mutex_unlock(&mcp->lock); |
278 | return status; | 278 | return status; |
279 | } | 279 | } |
280 | 280 | ||
281 | static int mcp23s08_get(struct gpio_chip *chip, unsigned offset) | 281 | static int mcp23s08_get(struct gpio_chip *chip, unsigned offset) |
282 | { | 282 | { |
283 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 283 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
284 | int status; | 284 | int status; |
285 | 285 | ||
286 | mutex_lock(&mcp->lock); | 286 | mutex_lock(&mcp->lock); |
287 | 287 | ||
288 | /* REVISIT reading this clears any IRQ ... */ | 288 | /* REVISIT reading this clears any IRQ ... */ |
289 | status = mcp->ops->read(mcp, MCP_GPIO); | 289 | status = mcp->ops->read(mcp, MCP_GPIO); |
290 | if (status < 0) | 290 | if (status < 0) |
291 | status = 0; | 291 | status = 0; |
292 | else { | 292 | else { |
293 | mcp->cache[MCP_GPIO] = status; | 293 | mcp->cache[MCP_GPIO] = status; |
294 | status = !!(status & (1 << offset)); | 294 | status = !!(status & (1 << offset)); |
295 | } | 295 | } |
296 | mutex_unlock(&mcp->lock); | 296 | mutex_unlock(&mcp->lock); |
297 | return status; | 297 | return status; |
298 | } | 298 | } |
299 | 299 | ||
300 | static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value) | 300 | static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value) |
301 | { | 301 | { |
302 | unsigned olat = mcp->cache[MCP_OLAT]; | 302 | unsigned olat = mcp->cache[MCP_OLAT]; |
303 | 303 | ||
304 | if (value) | 304 | if (value) |
305 | olat |= mask; | 305 | olat |= mask; |
306 | else | 306 | else |
307 | olat &= ~mask; | 307 | olat &= ~mask; |
308 | mcp->cache[MCP_OLAT] = olat; | 308 | mcp->cache[MCP_OLAT] = olat; |
309 | return mcp->ops->write(mcp, MCP_OLAT, olat); | 309 | return mcp->ops->write(mcp, MCP_OLAT, olat); |
310 | } | 310 | } |
311 | 311 | ||
312 | static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value) | 312 | static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value) |
313 | { | 313 | { |
314 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 314 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
315 | unsigned mask = 1 << offset; | 315 | unsigned mask = 1 << offset; |
316 | 316 | ||
317 | mutex_lock(&mcp->lock); | 317 | mutex_lock(&mcp->lock); |
318 | __mcp23s08_set(mcp, mask, value); | 318 | __mcp23s08_set(mcp, mask, value); |
319 | mutex_unlock(&mcp->lock); | 319 | mutex_unlock(&mcp->lock); |
320 | } | 320 | } |
321 | 321 | ||
322 | static int | 322 | static int |
323 | mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value) | 323 | mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value) |
324 | { | 324 | { |
325 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 325 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
326 | unsigned mask = 1 << offset; | 326 | unsigned mask = 1 << offset; |
327 | int status; | 327 | int status; |
328 | 328 | ||
329 | mutex_lock(&mcp->lock); | 329 | mutex_lock(&mcp->lock); |
330 | status = __mcp23s08_set(mcp, mask, value); | 330 | status = __mcp23s08_set(mcp, mask, value); |
331 | if (status == 0) { | 331 | if (status == 0) { |
332 | mcp->cache[MCP_IODIR] &= ~mask; | 332 | mcp->cache[MCP_IODIR] &= ~mask; |
333 | status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); | 333 | status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); |
334 | } | 334 | } |
335 | mutex_unlock(&mcp->lock); | 335 | mutex_unlock(&mcp->lock); |
336 | return status; | 336 | return status; |
337 | } | 337 | } |
338 | 338 | ||
339 | /*----------------------------------------------------------------------*/ | 339 | /*----------------------------------------------------------------------*/ |
340 | static irqreturn_t mcp23s08_irq(int irq, void *data) | 340 | static irqreturn_t mcp23s08_irq(int irq, void *data) |
341 | { | 341 | { |
342 | struct mcp23s08 *mcp = data; | 342 | struct mcp23s08 *mcp = data; |
343 | int intcap, intf, i; | 343 | int intcap, intf, i; |
344 | unsigned int child_irq; | 344 | unsigned int child_irq; |
345 | 345 | ||
346 | mutex_lock(&mcp->lock); | 346 | mutex_lock(&mcp->lock); |
347 | intf = mcp->ops->read(mcp, MCP_INTF); | 347 | intf = mcp->ops->read(mcp, MCP_INTF); |
348 | if (intf < 0) { | 348 | if (intf < 0) { |
349 | mutex_unlock(&mcp->lock); | 349 | mutex_unlock(&mcp->lock); |
350 | return IRQ_HANDLED; | 350 | return IRQ_HANDLED; |
351 | } | 351 | } |
352 | 352 | ||
353 | mcp->cache[MCP_INTF] = intf; | 353 | mcp->cache[MCP_INTF] = intf; |
354 | 354 | ||
355 | intcap = mcp->ops->read(mcp, MCP_INTCAP); | 355 | intcap = mcp->ops->read(mcp, MCP_INTCAP); |
356 | if (intcap < 0) { | 356 | if (intcap < 0) { |
357 | mutex_unlock(&mcp->lock); | 357 | mutex_unlock(&mcp->lock); |
358 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
359 | } | 359 | } |
360 | 360 | ||
361 | mcp->cache[MCP_INTCAP] = intcap; | 361 | mcp->cache[MCP_INTCAP] = intcap; |
362 | mutex_unlock(&mcp->lock); | 362 | mutex_unlock(&mcp->lock); |
363 | 363 | ||
364 | 364 | ||
365 | for (i = 0; i < mcp->chip.ngpio; i++) { | 365 | for (i = 0; i < mcp->chip.ngpio; i++) { |
366 | if ((BIT(i) & mcp->cache[MCP_INTF]) && | 366 | if ((BIT(i) & mcp->cache[MCP_INTF]) && |
367 | ((BIT(i) & intcap & mcp->irq_rise) || | 367 | ((BIT(i) & intcap & mcp->irq_rise) || |
368 | (mcp->irq_fall & ~intcap & BIT(i)))) { | 368 | (mcp->irq_fall & ~intcap & BIT(i)))) { |
369 | child_irq = irq_find_mapping(mcp->irq_domain, i); | 369 | child_irq = irq_find_mapping(mcp->irq_domain, i); |
370 | handle_nested_irq(child_irq); | 370 | handle_nested_irq(child_irq); |
371 | } | 371 | } |
372 | } | 372 | } |
373 | 373 | ||
374 | return IRQ_HANDLED; | 374 | return IRQ_HANDLED; |
375 | } | 375 | } |
376 | 376 | ||
377 | static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | 377 | static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) |
378 | { | 378 | { |
379 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 379 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
380 | 380 | ||
381 | return irq_find_mapping(mcp->irq_domain, offset); | 381 | return irq_find_mapping(mcp->irq_domain, offset); |
382 | } | 382 | } |
383 | 383 | ||
384 | static void mcp23s08_irq_mask(struct irq_data *data) | 384 | static void mcp23s08_irq_mask(struct irq_data *data) |
385 | { | 385 | { |
386 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 386 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
387 | unsigned int pos = data->hwirq; | 387 | unsigned int pos = data->hwirq; |
388 | 388 | ||
389 | mcp->cache[MCP_GPINTEN] &= ~BIT(pos); | 389 | mcp->cache[MCP_GPINTEN] &= ~BIT(pos); |
390 | } | 390 | } |
391 | 391 | ||
392 | static void mcp23s08_irq_unmask(struct irq_data *data) | 392 | static void mcp23s08_irq_unmask(struct irq_data *data) |
393 | { | 393 | { |
394 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 394 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
395 | unsigned int pos = data->hwirq; | 395 | unsigned int pos = data->hwirq; |
396 | 396 | ||
397 | mcp->cache[MCP_GPINTEN] |= BIT(pos); | 397 | mcp->cache[MCP_GPINTEN] |= BIT(pos); |
398 | } | 398 | } |
399 | 399 | ||
400 | static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) | 400 | static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) |
401 | { | 401 | { |
402 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 402 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
403 | unsigned int pos = data->hwirq; | 403 | unsigned int pos = data->hwirq; |
404 | int status = 0; | 404 | int status = 0; |
405 | 405 | ||
406 | if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { | 406 | if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { |
407 | mcp->cache[MCP_INTCON] &= ~BIT(pos); | 407 | mcp->cache[MCP_INTCON] &= ~BIT(pos); |
408 | mcp->irq_rise |= BIT(pos); | 408 | mcp->irq_rise |= BIT(pos); |
409 | mcp->irq_fall |= BIT(pos); | 409 | mcp->irq_fall |= BIT(pos); |
410 | } else if (type & IRQ_TYPE_EDGE_RISING) { | 410 | } else if (type & IRQ_TYPE_EDGE_RISING) { |
411 | mcp->cache[MCP_INTCON] &= ~BIT(pos); | 411 | mcp->cache[MCP_INTCON] &= ~BIT(pos); |
412 | mcp->irq_rise |= BIT(pos); | 412 | mcp->irq_rise |= BIT(pos); |
413 | mcp->irq_fall &= ~BIT(pos); | 413 | mcp->irq_fall &= ~BIT(pos); |
414 | } else if (type & IRQ_TYPE_EDGE_FALLING) { | 414 | } else if (type & IRQ_TYPE_EDGE_FALLING) { |
415 | mcp->cache[MCP_INTCON] &= ~BIT(pos); | 415 | mcp->cache[MCP_INTCON] &= ~BIT(pos); |
416 | mcp->irq_rise &= ~BIT(pos); | 416 | mcp->irq_rise &= ~BIT(pos); |
417 | mcp->irq_fall |= BIT(pos); | 417 | mcp->irq_fall |= BIT(pos); |
418 | } else | 418 | } else |
419 | return -EINVAL; | 419 | return -EINVAL; |
420 | 420 | ||
421 | return status; | 421 | return status; |
422 | } | 422 | } |
423 | 423 | ||
424 | static void mcp23s08_irq_bus_lock(struct irq_data *data) | 424 | static void mcp23s08_irq_bus_lock(struct irq_data *data) |
425 | { | 425 | { |
426 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 426 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
427 | 427 | ||
428 | mutex_lock(&mcp->irq_lock); | 428 | mutex_lock(&mcp->irq_lock); |
429 | } | 429 | } |
430 | 430 | ||
431 | static void mcp23s08_irq_bus_unlock(struct irq_data *data) | 431 | static void mcp23s08_irq_bus_unlock(struct irq_data *data) |
432 | { | 432 | { |
433 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 433 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
434 | 434 | ||
435 | mutex_lock(&mcp->lock); | 435 | mutex_lock(&mcp->lock); |
436 | mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); | 436 | mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); |
437 | mcp->ops->write(mcp, MCP_DEFVAL, mcp->cache[MCP_DEFVAL]); | 437 | mcp->ops->write(mcp, MCP_DEFVAL, mcp->cache[MCP_DEFVAL]); |
438 | mcp->ops->write(mcp, MCP_INTCON, mcp->cache[MCP_INTCON]); | 438 | mcp->ops->write(mcp, MCP_INTCON, mcp->cache[MCP_INTCON]); |
439 | mutex_unlock(&mcp->lock); | 439 | mutex_unlock(&mcp->lock); |
440 | mutex_unlock(&mcp->irq_lock); | 440 | mutex_unlock(&mcp->irq_lock); |
441 | } | 441 | } |
442 | 442 | ||
443 | static int mcp23s08_irq_reqres(struct irq_data *data) | 443 | static int mcp23s08_irq_reqres(struct irq_data *data) |
444 | { | 444 | { |
445 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 445 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
446 | 446 | ||
447 | if (gpio_lock_as_irq(&mcp->chip, data->hwirq)) { | 447 | if (gpio_lock_as_irq(&mcp->chip, data->hwirq)) { |
448 | dev_err(mcp->chip.dev, | 448 | dev_err(mcp->chip.dev, |
449 | "unable to lock HW IRQ %lu for IRQ usage\n", | 449 | "unable to lock HW IRQ %lu for IRQ usage\n", |
450 | data->hwirq); | 450 | data->hwirq); |
451 | return -EINVAL; | 451 | return -EINVAL; |
452 | } | 452 | } |
453 | 453 | ||
454 | return 0; | 454 | return 0; |
455 | } | 455 | } |
456 | 456 | ||
457 | static void mcp23s08_irq_relres(struct irq_data *data) | 457 | static void mcp23s08_irq_relres(struct irq_data *data) |
458 | { | 458 | { |
459 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); | 459 | struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); |
460 | 460 | ||
461 | gpio_unlock_as_irq(&mcp->chip, data->hwirq); | 461 | gpio_unlock_as_irq(&mcp->chip, data->hwirq); |
462 | } | 462 | } |
463 | 463 | ||
464 | static struct irq_chip mcp23s08_irq_chip = { | 464 | static struct irq_chip mcp23s08_irq_chip = { |
465 | .name = "gpio-mcp23xxx", | 465 | .name = "gpio-mcp23xxx", |
466 | .irq_mask = mcp23s08_irq_mask, | 466 | .irq_mask = mcp23s08_irq_mask, |
467 | .irq_unmask = mcp23s08_irq_unmask, | 467 | .irq_unmask = mcp23s08_irq_unmask, |
468 | .irq_set_type = mcp23s08_irq_set_type, | 468 | .irq_set_type = mcp23s08_irq_set_type, |
469 | .irq_bus_lock = mcp23s08_irq_bus_lock, | 469 | .irq_bus_lock = mcp23s08_irq_bus_lock, |
470 | .irq_bus_sync_unlock = mcp23s08_irq_bus_unlock, | 470 | .irq_bus_sync_unlock = mcp23s08_irq_bus_unlock, |
471 | .irq_request_resources = mcp23s08_irq_reqres, | 471 | .irq_request_resources = mcp23s08_irq_reqres, |
472 | .irq_release_resources = mcp23s08_irq_relres, | 472 | .irq_release_resources = mcp23s08_irq_relres, |
473 | }; | 473 | }; |
474 | 474 | ||
475 | static int mcp23s08_irq_setup(struct mcp23s08 *mcp) | 475 | static int mcp23s08_irq_setup(struct mcp23s08 *mcp) |
476 | { | 476 | { |
477 | struct gpio_chip *chip = &mcp->chip; | 477 | struct gpio_chip *chip = &mcp->chip; |
478 | int err, irq, j; | 478 | int err, irq, j; |
479 | 479 | ||
480 | mutex_init(&mcp->irq_lock); | 480 | mutex_init(&mcp->irq_lock); |
481 | 481 | ||
482 | mcp->irq_domain = irq_domain_add_linear(chip->dev->of_node, chip->ngpio, | 482 | mcp->irq_domain = irq_domain_add_linear(chip->dev->of_node, chip->ngpio, |
483 | &irq_domain_simple_ops, mcp); | 483 | &irq_domain_simple_ops, mcp); |
484 | if (!mcp->irq_domain) | 484 | if (!mcp->irq_domain) |
485 | return -ENODEV; | 485 | return -ENODEV; |
486 | 486 | ||
487 | err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, | 487 | err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, |
488 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 488 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
489 | dev_name(chip->dev), mcp); | 489 | dev_name(chip->dev), mcp); |
490 | if (err != 0) { | 490 | if (err != 0) { |
491 | dev_err(chip->dev, "unable to request IRQ#%d: %d\n", | 491 | dev_err(chip->dev, "unable to request IRQ#%d: %d\n", |
492 | mcp->irq, err); | 492 | mcp->irq, err); |
493 | return err; | 493 | return err; |
494 | } | 494 | } |
495 | 495 | ||
496 | chip->to_irq = mcp23s08_gpio_to_irq; | 496 | chip->to_irq = mcp23s08_gpio_to_irq; |
497 | 497 | ||
498 | for (j = 0; j < mcp->chip.ngpio; j++) { | 498 | for (j = 0; j < mcp->chip.ngpio; j++) { |
499 | irq = irq_create_mapping(mcp->irq_domain, j); | 499 | irq = irq_create_mapping(mcp->irq_domain, j); |
500 | irq_set_lockdep_class(irq, &gpio_lock_class); | 500 | irq_set_lockdep_class(irq, &gpio_lock_class); |
501 | irq_set_chip_data(irq, mcp); | 501 | irq_set_chip_data(irq, mcp); |
502 | irq_set_chip(irq, &mcp23s08_irq_chip); | 502 | irq_set_chip(irq, &mcp23s08_irq_chip); |
503 | irq_set_nested_thread(irq, true); | 503 | irq_set_nested_thread(irq, true); |
504 | #ifdef CONFIG_ARM | 504 | #ifdef CONFIG_ARM |
505 | set_irq_flags(irq, IRQF_VALID); | 505 | set_irq_flags(irq, IRQF_VALID); |
506 | #else | 506 | #else |
507 | irq_set_noprobe(irq); | 507 | irq_set_noprobe(irq); |
508 | #endif | 508 | #endif |
509 | } | 509 | } |
510 | return 0; | 510 | return 0; |
511 | } | 511 | } |
512 | 512 | ||
513 | static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) | 513 | static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) |
514 | { | 514 | { |
515 | unsigned int irq, i; | 515 | unsigned int irq, i; |
516 | 516 | ||
517 | free_irq(mcp->irq, mcp); | 517 | free_irq(mcp->irq, mcp); |
518 | 518 | ||
519 | for (i = 0; i < mcp->chip.ngpio; i++) { | 519 | for (i = 0; i < mcp->chip.ngpio; i++) { |
520 | irq = irq_find_mapping(mcp->irq_domain, i); | 520 | irq = irq_find_mapping(mcp->irq_domain, i); |
521 | if (irq > 0) | 521 | if (irq > 0) |
522 | irq_dispose_mapping(irq); | 522 | irq_dispose_mapping(irq); |
523 | } | 523 | } |
524 | 524 | ||
525 | irq_domain_remove(mcp->irq_domain); | 525 | irq_domain_remove(mcp->irq_domain); |
526 | } | 526 | } |
527 | 527 | ||
528 | /*----------------------------------------------------------------------*/ | 528 | /*----------------------------------------------------------------------*/ |
529 | 529 | ||
530 | #ifdef CONFIG_DEBUG_FS | 530 | #ifdef CONFIG_DEBUG_FS |
531 | 531 | ||
532 | #include <linux/seq_file.h> | 532 | #include <linux/seq_file.h> |
533 | 533 | ||
534 | /* | 534 | /* |
535 | * This shows more info than the generic gpio dump code: | 535 | * This shows more info than the generic gpio dump code: |
536 | * pullups, deglitching, open drain drive. | 536 | * pullups, deglitching, open drain drive. |
537 | */ | 537 | */ |
538 | static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 538 | static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
539 | { | 539 | { |
540 | struct mcp23s08 *mcp; | 540 | struct mcp23s08 *mcp; |
541 | char bank; | 541 | char bank; |
542 | int t; | 542 | int t; |
543 | unsigned mask; | 543 | unsigned mask; |
544 | 544 | ||
545 | mcp = container_of(chip, struct mcp23s08, chip); | 545 | mcp = container_of(chip, struct mcp23s08, chip); |
546 | 546 | ||
547 | /* NOTE: we only handle one bank for now ... */ | 547 | /* NOTE: we only handle one bank for now ... */ |
548 | bank = '0' + ((mcp->addr >> 1) & 0x7); | 548 | bank = '0' + ((mcp->addr >> 1) & 0x7); |
549 | 549 | ||
550 | mutex_lock(&mcp->lock); | 550 | mutex_lock(&mcp->lock); |
551 | t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); | 551 | t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); |
552 | if (t < 0) { | 552 | if (t < 0) { |
553 | seq_printf(s, " I/O ERROR %d\n", t); | 553 | seq_printf(s, " I/O ERROR %d\n", t); |
554 | goto done; | 554 | goto done; |
555 | } | 555 | } |
556 | 556 | ||
557 | for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) { | 557 | for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) { |
558 | const char *label; | 558 | const char *label; |
559 | 559 | ||
560 | label = gpiochip_is_requested(chip, t); | 560 | label = gpiochip_is_requested(chip, t); |
561 | if (!label) | 561 | if (!label) |
562 | continue; | 562 | continue; |
563 | 563 | ||
564 | seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s", | 564 | seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s", |
565 | chip->base + t, bank, t, label, | 565 | chip->base + t, bank, t, label, |
566 | (mcp->cache[MCP_IODIR] & mask) ? "in " : "out", | 566 | (mcp->cache[MCP_IODIR] & mask) ? "in " : "out", |
567 | (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo", | 567 | (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo", |
568 | (mcp->cache[MCP_GPPU] & mask) ? "up" : " "); | 568 | (mcp->cache[MCP_GPPU] & mask) ? "up" : " "); |
569 | /* NOTE: ignoring the irq-related registers */ | 569 | /* NOTE: ignoring the irq-related registers */ |
570 | seq_puts(s, "\n"); | 570 | seq_puts(s, "\n"); |
571 | } | 571 | } |
572 | done: | 572 | done: |
573 | mutex_unlock(&mcp->lock); | 573 | mutex_unlock(&mcp->lock); |
574 | } | 574 | } |
575 | 575 | ||
576 | #else | 576 | #else |
577 | #define mcp23s08_dbg_show NULL | 577 | #define mcp23s08_dbg_show NULL |
578 | #endif | 578 | #endif |
579 | 579 | ||
580 | /*----------------------------------------------------------------------*/ | 580 | /*----------------------------------------------------------------------*/ |
581 | 581 | ||
582 | static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | 582 | static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, |
583 | void *data, unsigned addr, unsigned type, | 583 | void *data, unsigned addr, unsigned type, |
584 | struct mcp23s08_platform_data *pdata, int cs) | 584 | struct mcp23s08_platform_data *pdata, int cs) |
585 | { | 585 | { |
586 | int status; | 586 | int status; |
587 | bool mirror = false; | 587 | bool mirror = false; |
588 | 588 | ||
589 | mutex_init(&mcp->lock); | 589 | mutex_init(&mcp->lock); |
590 | 590 | ||
591 | mcp->data = data; | 591 | mcp->data = data; |
592 | mcp->addr = addr; | 592 | mcp->addr = addr; |
593 | 593 | ||
594 | mcp->chip.direction_input = mcp23s08_direction_input; | 594 | mcp->chip.direction_input = mcp23s08_direction_input; |
595 | mcp->chip.get = mcp23s08_get; | 595 | mcp->chip.get = mcp23s08_get; |
596 | mcp->chip.direction_output = mcp23s08_direction_output; | 596 | mcp->chip.direction_output = mcp23s08_direction_output; |
597 | mcp->chip.set = mcp23s08_set; | 597 | mcp->chip.set = mcp23s08_set; |
598 | mcp->chip.dbg_show = mcp23s08_dbg_show; | 598 | mcp->chip.dbg_show = mcp23s08_dbg_show; |
599 | #ifdef CONFIG_OF | 599 | #ifdef CONFIG_OF |
600 | mcp->chip.of_gpio_n_cells = 2; | 600 | mcp->chip.of_gpio_n_cells = 2; |
601 | mcp->chip.of_node = dev->of_node; | 601 | mcp->chip.of_node = dev->of_node; |
602 | #endif | 602 | #endif |
603 | 603 | ||
604 | switch (type) { | 604 | switch (type) { |
605 | #ifdef CONFIG_SPI_MASTER | 605 | #ifdef CONFIG_SPI_MASTER |
606 | case MCP_TYPE_S08: | 606 | case MCP_TYPE_S08: |
607 | mcp->ops = &mcp23s08_ops; | 607 | mcp->ops = &mcp23s08_ops; |
608 | mcp->chip.ngpio = 8; | 608 | mcp->chip.ngpio = 8; |
609 | mcp->chip.label = "mcp23s08"; | 609 | mcp->chip.label = "mcp23s08"; |
610 | break; | 610 | break; |
611 | 611 | ||
612 | case MCP_TYPE_S17: | 612 | case MCP_TYPE_S17: |
613 | mcp->ops = &mcp23s17_ops; | 613 | mcp->ops = &mcp23s17_ops; |
614 | mcp->chip.ngpio = 16; | 614 | mcp->chip.ngpio = 16; |
615 | mcp->chip.label = "mcp23s17"; | 615 | mcp->chip.label = "mcp23s17"; |
616 | break; | 616 | break; |
617 | #endif /* CONFIG_SPI_MASTER */ | 617 | #endif /* CONFIG_SPI_MASTER */ |
618 | 618 | ||
619 | #if IS_ENABLED(CONFIG_I2C) | 619 | #if IS_ENABLED(CONFIG_I2C) |
620 | case MCP_TYPE_008: | 620 | case MCP_TYPE_008: |
621 | mcp->ops = &mcp23008_ops; | 621 | mcp->ops = &mcp23008_ops; |
622 | mcp->chip.ngpio = 8; | 622 | mcp->chip.ngpio = 8; |
623 | mcp->chip.label = "mcp23008"; | 623 | mcp->chip.label = "mcp23008"; |
624 | break; | 624 | break; |
625 | 625 | ||
626 | case MCP_TYPE_017: | 626 | case MCP_TYPE_017: |
627 | mcp->ops = &mcp23017_ops; | 627 | mcp->ops = &mcp23017_ops; |
628 | mcp->chip.ngpio = 16; | 628 | mcp->chip.ngpio = 16; |
629 | mcp->chip.label = "mcp23017"; | 629 | mcp->chip.label = "mcp23017"; |
630 | break; | 630 | break; |
631 | #endif /* CONFIG_I2C */ | 631 | #endif /* CONFIG_I2C */ |
632 | 632 | ||
633 | default: | 633 | default: |
634 | dev_err(dev, "invalid device type (%d)\n", type); | 634 | dev_err(dev, "invalid device type (%d)\n", type); |
635 | return -EINVAL; | 635 | return -EINVAL; |
636 | } | 636 | } |
637 | 637 | ||
638 | mcp->chip.base = pdata->base; | 638 | mcp->chip.base = pdata->base; |
639 | mcp->chip.can_sleep = true; | 639 | mcp->chip.can_sleep = true; |
640 | mcp->chip.dev = dev; | 640 | mcp->chip.dev = dev; |
641 | mcp->chip.owner = THIS_MODULE; | 641 | mcp->chip.owner = THIS_MODULE; |
642 | 642 | ||
643 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, | 643 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, |
644 | * and MCP_IOCON.HAEN = 1, so we work with all chips. | 644 | * and MCP_IOCON.HAEN = 1, so we work with all chips. |
645 | */ | 645 | */ |
646 | 646 | ||
647 | status = mcp->ops->read(mcp, MCP_IOCON); | 647 | status = mcp->ops->read(mcp, MCP_IOCON); |
648 | if (status < 0) | 648 | if (status < 0) |
649 | goto fail; | 649 | goto fail; |
650 | 650 | ||
651 | mcp->irq_controller = pdata->irq_controller; | 651 | mcp->irq_controller = pdata->irq_controller; |
652 | if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) | 652 | if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) |
653 | mirror = pdata->mirror; | 653 | mirror = pdata->mirror; |
654 | 654 | ||
655 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { | 655 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { |
656 | /* mcp23s17 has IOCON twice, make sure they are in sync */ | 656 | /* mcp23s17 has IOCON twice, make sure they are in sync */ |
657 | status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); | 657 | status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); |
658 | status |= IOCON_HAEN | (IOCON_HAEN << 8); | 658 | status |= IOCON_HAEN | (IOCON_HAEN << 8); |
659 | status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); | 659 | status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); |
660 | if (mirror) | 660 | if (mirror) |
661 | status |= IOCON_MIRROR | (IOCON_MIRROR << 8); | 661 | status |= IOCON_MIRROR | (IOCON_MIRROR << 8); |
662 | 662 | ||
663 | status = mcp->ops->write(mcp, MCP_IOCON, status); | 663 | status = mcp->ops->write(mcp, MCP_IOCON, status); |
664 | if (status < 0) | 664 | if (status < 0) |
665 | goto fail; | 665 | goto fail; |
666 | } | 666 | } |
667 | 667 | ||
668 | /* configure ~100K pullups */ | 668 | /* configure ~100K pullups */ |
669 | status = mcp->ops->write(mcp, MCP_GPPU, pdata->chip[cs].pullups); | 669 | status = mcp->ops->write(mcp, MCP_GPPU, pdata->chip[cs].pullups); |
670 | if (status < 0) | 670 | if (status < 0) |
671 | goto fail; | 671 | goto fail; |
672 | 672 | ||
673 | status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); | 673 | status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); |
674 | if (status < 0) | 674 | if (status < 0) |
675 | goto fail; | 675 | goto fail; |
676 | 676 | ||
677 | /* disable inverter on input */ | 677 | /* disable inverter on input */ |
678 | if (mcp->cache[MCP_IPOL] != 0) { | 678 | if (mcp->cache[MCP_IPOL] != 0) { |
679 | mcp->cache[MCP_IPOL] = 0; | 679 | mcp->cache[MCP_IPOL] = 0; |
680 | status = mcp->ops->write(mcp, MCP_IPOL, 0); | 680 | status = mcp->ops->write(mcp, MCP_IPOL, 0); |
681 | if (status < 0) | 681 | if (status < 0) |
682 | goto fail; | 682 | goto fail; |
683 | } | 683 | } |
684 | 684 | ||
685 | /* disable irqs */ | 685 | /* disable irqs */ |
686 | if (mcp->cache[MCP_GPINTEN] != 0) { | 686 | if (mcp->cache[MCP_GPINTEN] != 0) { |
687 | mcp->cache[MCP_GPINTEN] = 0; | 687 | mcp->cache[MCP_GPINTEN] = 0; |
688 | status = mcp->ops->write(mcp, MCP_GPINTEN, 0); | 688 | status = mcp->ops->write(mcp, MCP_GPINTEN, 0); |
689 | if (status < 0) | 689 | if (status < 0) |
690 | goto fail; | 690 | goto fail; |
691 | } | 691 | } |
692 | 692 | ||
693 | status = gpiochip_add(&mcp->chip); | 693 | status = gpiochip_add(&mcp->chip); |
694 | if (status < 0) | 694 | if (status < 0) |
695 | goto fail; | 695 | goto fail; |
696 | 696 | ||
697 | if (mcp->irq && mcp->irq_controller) { | 697 | if (mcp->irq && mcp->irq_controller) { |
698 | status = mcp23s08_irq_setup(mcp); | 698 | status = mcp23s08_irq_setup(mcp); |
699 | if (status) { | 699 | if (status) { |
700 | mcp23s08_irq_teardown(mcp); | 700 | mcp23s08_irq_teardown(mcp); |
701 | goto fail; | 701 | goto fail; |
702 | } | 702 | } |
703 | } | 703 | } |
704 | fail: | 704 | fail: |
705 | if (status < 0) | 705 | if (status < 0) |
706 | dev_dbg(dev, "can't setup chip %d, --> %d\n", | 706 | dev_dbg(dev, "can't setup chip %d, --> %d\n", |
707 | addr, status); | 707 | addr, status); |
708 | return status; | 708 | return status; |
709 | } | 709 | } |
710 | 710 | ||
711 | /*----------------------------------------------------------------------*/ | 711 | /*----------------------------------------------------------------------*/ |
712 | 712 | ||
713 | #ifdef CONFIG_OF | 713 | #ifdef CONFIG_OF |
714 | #ifdef CONFIG_SPI_MASTER | 714 | #ifdef CONFIG_SPI_MASTER |
715 | static const struct of_device_id mcp23s08_spi_of_match[] = { | 715 | static const struct of_device_id mcp23s08_spi_of_match[] = { |
716 | { | 716 | { |
717 | .compatible = "microchip,mcp23s08", | 717 | .compatible = "microchip,mcp23s08", |
718 | .data = (void *) MCP_TYPE_S08, | 718 | .data = (void *) MCP_TYPE_S08, |
719 | }, | 719 | }, |
720 | { | 720 | { |
721 | .compatible = "microchip,mcp23s17", | 721 | .compatible = "microchip,mcp23s17", |
722 | .data = (void *) MCP_TYPE_S17, | 722 | .data = (void *) MCP_TYPE_S17, |
723 | }, | 723 | }, |
724 | /* NOTE: The use of the mcp prefix is deprecated and will be removed. */ | 724 | /* NOTE: The use of the mcp prefix is deprecated and will be removed. */ |
725 | { | 725 | { |
726 | .compatible = "mcp,mcp23s08", | 726 | .compatible = "mcp,mcp23s08", |
727 | .data = (void *) MCP_TYPE_S08, | 727 | .data = (void *) MCP_TYPE_S08, |
728 | }, | 728 | }, |
729 | { | 729 | { |
730 | .compatible = "mcp,mcp23s17", | 730 | .compatible = "mcp,mcp23s17", |
731 | .data = (void *) MCP_TYPE_S17, | 731 | .data = (void *) MCP_TYPE_S17, |
732 | }, | 732 | }, |
733 | { }, | 733 | { }, |
734 | }; | 734 | }; |
735 | MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match); | 735 | MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match); |
736 | #endif | 736 | #endif |
737 | 737 | ||
738 | #if IS_ENABLED(CONFIG_I2C) | 738 | #if IS_ENABLED(CONFIG_I2C) |
739 | static const struct of_device_id mcp23s08_i2c_of_match[] = { | 739 | static const struct of_device_id mcp23s08_i2c_of_match[] = { |
740 | { | 740 | { |
741 | .compatible = "microchip,mcp23008", | 741 | .compatible = "microchip,mcp23008", |
742 | .data = (void *) MCP_TYPE_008, | 742 | .data = (void *) MCP_TYPE_008, |
743 | }, | 743 | }, |
744 | { | 744 | { |
745 | .compatible = "microchip,mcp23017", | 745 | .compatible = "microchip,mcp23017", |
746 | .data = (void *) MCP_TYPE_017, | 746 | .data = (void *) MCP_TYPE_017, |
747 | }, | 747 | }, |
748 | /* NOTE: The use of the mcp prefix is deprecated and will be removed. */ | 748 | /* NOTE: The use of the mcp prefix is deprecated and will be removed. */ |
749 | { | 749 | { |
750 | .compatible = "mcp,mcp23008", | 750 | .compatible = "mcp,mcp23008", |
751 | .data = (void *) MCP_TYPE_008, | 751 | .data = (void *) MCP_TYPE_008, |
752 | }, | 752 | }, |
753 | { | 753 | { |
754 | .compatible = "mcp,mcp23017", | 754 | .compatible = "mcp,mcp23017", |
755 | .data = (void *) MCP_TYPE_017, | 755 | .data = (void *) MCP_TYPE_017, |
756 | }, | 756 | }, |
757 | { }, | 757 | { }, |
758 | }; | 758 | }; |
759 | MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match); | 759 | MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match); |
760 | #endif | 760 | #endif |
761 | #endif /* CONFIG_OF */ | 761 | #endif /* CONFIG_OF */ |
762 | 762 | ||
763 | 763 | ||
764 | #if IS_ENABLED(CONFIG_I2C) | 764 | #if IS_ENABLED(CONFIG_I2C) |
765 | 765 | ||
766 | static int mcp230xx_probe(struct i2c_client *client, | 766 | static int mcp230xx_probe(struct i2c_client *client, |
767 | const struct i2c_device_id *id) | 767 | const struct i2c_device_id *id) |
768 | { | 768 | { |
769 | struct mcp23s08_platform_data *pdata, local_pdata; | 769 | struct mcp23s08_platform_data *pdata, local_pdata; |
770 | struct mcp23s08 *mcp; | 770 | struct mcp23s08 *mcp; |
771 | int status; | 771 | int status; |
772 | const struct of_device_id *match; | 772 | const struct of_device_id *match; |
773 | 773 | ||
774 | match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match), | 774 | match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match), |
775 | &client->dev); | 775 | &client->dev); |
776 | if (match) { | 776 | if (match) { |
777 | pdata = &local_pdata; | 777 | pdata = &local_pdata; |
778 | pdata->base = -1; | 778 | pdata->base = -1; |
779 | pdata->chip[0].pullups = 0; | 779 | pdata->chip[0].pullups = 0; |
780 | pdata->irq_controller = of_property_read_bool( | 780 | pdata->irq_controller = of_property_read_bool( |
781 | client->dev.of_node, | 781 | client->dev.of_node, |
782 | "interrupt-controller"); | 782 | "interrupt-controller"); |
783 | pdata->mirror = of_property_read_bool(client->dev.of_node, | 783 | pdata->mirror = of_property_read_bool(client->dev.of_node, |
784 | "microchip,irq-mirror"); | 784 | "microchip,irq-mirror"); |
785 | client->irq = irq_of_parse_and_map(client->dev.of_node, 0); | 785 | client->irq = irq_of_parse_and_map(client->dev.of_node, 0); |
786 | } else { | 786 | } else { |
787 | pdata = dev_get_platdata(&client->dev); | 787 | pdata = dev_get_platdata(&client->dev); |
788 | if (!pdata || !gpio_is_valid(pdata->base)) { | 788 | if (!pdata) { |
789 | dev_dbg(&client->dev, "invalid platform data\n"); | 789 | pdata = devm_kzalloc(&client->dev, |
790 | return -EINVAL; | 790 | sizeof(struct mcp23s08_platform_data), |
791 | GFP_KERNEL); | ||
792 | pdata->base = -1; | ||
791 | } | 793 | } |
792 | } | 794 | } |
793 | 795 | ||
794 | mcp = kzalloc(sizeof(*mcp), GFP_KERNEL); | 796 | mcp = kzalloc(sizeof(*mcp), GFP_KERNEL); |
795 | if (!mcp) | 797 | if (!mcp) |
796 | return -ENOMEM; | 798 | return -ENOMEM; |
797 | 799 | ||
798 | mcp->irq = client->irq; | 800 | mcp->irq = client->irq; |
799 | status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, | 801 | status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, |
800 | id->driver_data, pdata, 0); | 802 | id->driver_data, pdata, 0); |
801 | if (status) | 803 | if (status) |
802 | goto fail; | 804 | goto fail; |
803 | 805 | ||
804 | i2c_set_clientdata(client, mcp); | 806 | i2c_set_clientdata(client, mcp); |
805 | 807 | ||
806 | return 0; | 808 | return 0; |
807 | 809 | ||
808 | fail: | 810 | fail: |
809 | kfree(mcp); | 811 | kfree(mcp); |
810 | 812 | ||
811 | return status; | 813 | return status; |
812 | } | 814 | } |
813 | 815 | ||
814 | static int mcp230xx_remove(struct i2c_client *client) | 816 | static int mcp230xx_remove(struct i2c_client *client) |
815 | { | 817 | { |
816 | struct mcp23s08 *mcp = i2c_get_clientdata(client); | 818 | struct mcp23s08 *mcp = i2c_get_clientdata(client); |
817 | 819 | ||
818 | if (client->irq && mcp->irq_controller) | 820 | if (client->irq && mcp->irq_controller) |
819 | mcp23s08_irq_teardown(mcp); | 821 | mcp23s08_irq_teardown(mcp); |
820 | 822 | ||
821 | gpiochip_remove(&mcp->chip); | 823 | gpiochip_remove(&mcp->chip); |
822 | kfree(mcp); | 824 | kfree(mcp); |
823 | 825 | ||
824 | return 0; | 826 | return 0; |
825 | } | 827 | } |
826 | 828 | ||
827 | static const struct i2c_device_id mcp230xx_id[] = { | 829 | static const struct i2c_device_id mcp230xx_id[] = { |
828 | { "mcp23008", MCP_TYPE_008 }, | 830 | { "mcp23008", MCP_TYPE_008 }, |
829 | { "mcp23017", MCP_TYPE_017 }, | 831 | { "mcp23017", MCP_TYPE_017 }, |
830 | { }, | 832 | { }, |
831 | }; | 833 | }; |
832 | MODULE_DEVICE_TABLE(i2c, mcp230xx_id); | 834 | MODULE_DEVICE_TABLE(i2c, mcp230xx_id); |
833 | 835 | ||
834 | static struct i2c_driver mcp230xx_driver = { | 836 | static struct i2c_driver mcp230xx_driver = { |
835 | .driver = { | 837 | .driver = { |
836 | .name = "mcp230xx", | 838 | .name = "mcp230xx", |
837 | .owner = THIS_MODULE, | 839 | .owner = THIS_MODULE, |
838 | .of_match_table = of_match_ptr(mcp23s08_i2c_of_match), | 840 | .of_match_table = of_match_ptr(mcp23s08_i2c_of_match), |
839 | }, | 841 | }, |
840 | .probe = mcp230xx_probe, | 842 | .probe = mcp230xx_probe, |
841 | .remove = mcp230xx_remove, | 843 | .remove = mcp230xx_remove, |
842 | .id_table = mcp230xx_id, | 844 | .id_table = mcp230xx_id, |
843 | }; | 845 | }; |
844 | 846 | ||
845 | static int __init mcp23s08_i2c_init(void) | 847 | static int __init mcp23s08_i2c_init(void) |
846 | { | 848 | { |
847 | return i2c_add_driver(&mcp230xx_driver); | 849 | return i2c_add_driver(&mcp230xx_driver); |
848 | } | 850 | } |
849 | 851 | ||
850 | static void mcp23s08_i2c_exit(void) | 852 | static void mcp23s08_i2c_exit(void) |
851 | { | 853 | { |
852 | i2c_del_driver(&mcp230xx_driver); | 854 | i2c_del_driver(&mcp230xx_driver); |
853 | } | 855 | } |
854 | 856 | ||
855 | #else | 857 | #else |
856 | 858 | ||
857 | static int __init mcp23s08_i2c_init(void) { return 0; } | 859 | static int __init mcp23s08_i2c_init(void) { return 0; } |
858 | static void mcp23s08_i2c_exit(void) { } | 860 | static void mcp23s08_i2c_exit(void) { } |
859 | 861 | ||
860 | #endif /* CONFIG_I2C */ | 862 | #endif /* CONFIG_I2C */ |
861 | 863 | ||
862 | /*----------------------------------------------------------------------*/ | 864 | /*----------------------------------------------------------------------*/ |
863 | 865 | ||
864 | #ifdef CONFIG_SPI_MASTER | 866 | #ifdef CONFIG_SPI_MASTER |
865 | 867 | ||
866 | static int mcp23s08_probe(struct spi_device *spi) | 868 | static int mcp23s08_probe(struct spi_device *spi) |
867 | { | 869 | { |
868 | struct mcp23s08_platform_data *pdata, local_pdata; | 870 | struct mcp23s08_platform_data *pdata, local_pdata; |
869 | unsigned addr; | 871 | unsigned addr; |
870 | int chips = 0; | 872 | int chips = 0; |
871 | struct mcp23s08_driver_data *data; | 873 | struct mcp23s08_driver_data *data; |
872 | int status, type; | 874 | int status, type; |
873 | unsigned ngpio = 0; | 875 | unsigned ngpio = 0; |
874 | const struct of_device_id *match; | 876 | const struct of_device_id *match; |
875 | u32 spi_present_mask = 0; | 877 | u32 spi_present_mask = 0; |
876 | 878 | ||
877 | match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev); | 879 | match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev); |
878 | if (match) { | 880 | if (match) { |
879 | type = (int)(uintptr_t)match->data; | 881 | type = (int)(uintptr_t)match->data; |
880 | status = of_property_read_u32(spi->dev.of_node, | 882 | status = of_property_read_u32(spi->dev.of_node, |
881 | "microchip,spi-present-mask", &spi_present_mask); | 883 | "microchip,spi-present-mask", &spi_present_mask); |
882 | if (status) { | 884 | if (status) { |
883 | status = of_property_read_u32(spi->dev.of_node, | 885 | status = of_property_read_u32(spi->dev.of_node, |
884 | "mcp,spi-present-mask", &spi_present_mask); | 886 | "mcp,spi-present-mask", &spi_present_mask); |
885 | if (status) { | 887 | if (status) { |
886 | dev_err(&spi->dev, | 888 | dev_err(&spi->dev, |
887 | "DT has no spi-present-mask\n"); | 889 | "DT has no spi-present-mask\n"); |
888 | return -ENODEV; | 890 | return -ENODEV; |
889 | } | 891 | } |
890 | } | 892 | } |
891 | if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) { | 893 | if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) { |
892 | dev_err(&spi->dev, "invalid spi-present-mask\n"); | 894 | dev_err(&spi->dev, "invalid spi-present-mask\n"); |
893 | return -ENODEV; | 895 | return -ENODEV; |
894 | } | 896 | } |
895 | 897 | ||
896 | pdata = &local_pdata; | 898 | pdata = &local_pdata; |
897 | pdata->base = -1; | 899 | pdata->base = -1; |
898 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { | 900 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
899 | pdata->chip[addr].pullups = 0; | 901 | pdata->chip[addr].pullups = 0; |
900 | if (spi_present_mask & (1 << addr)) | 902 | if (spi_present_mask & (1 << addr)) |
901 | chips++; | 903 | chips++; |
902 | } | 904 | } |
903 | pdata->irq_controller = of_property_read_bool( | 905 | pdata->irq_controller = of_property_read_bool( |
904 | spi->dev.of_node, | 906 | spi->dev.of_node, |
905 | "interrupt-controller"); | 907 | "interrupt-controller"); |
906 | pdata->mirror = of_property_read_bool(spi->dev.of_node, | 908 | pdata->mirror = of_property_read_bool(spi->dev.of_node, |
907 | "microchip,irq-mirror"); | 909 | "microchip,irq-mirror"); |
908 | } else { | 910 | } else { |
909 | type = spi_get_device_id(spi)->driver_data; | 911 | type = spi_get_device_id(spi)->driver_data; |
910 | pdata = dev_get_platdata(&spi->dev); | 912 | pdata = dev_get_platdata(&spi->dev); |
911 | if (!pdata || !gpio_is_valid(pdata->base)) { | 913 | if (!pdata) { |
912 | dev_dbg(&spi->dev, | 914 | pdata = devm_kzalloc(&spi->dev, |
913 | "invalid or missing platform data\n"); | 915 | sizeof(struct mcp23s08_platform_data), |
914 | return -EINVAL; | 916 | GFP_KERNEL); |
917 | pdata->base = -1; | ||
915 | } | 918 | } |
916 | 919 | ||
917 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { | 920 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
918 | if (!pdata->chip[addr].is_present) | 921 | if (!pdata->chip[addr].is_present) |
919 | continue; | 922 | continue; |
920 | chips++; | 923 | chips++; |
921 | if ((type == MCP_TYPE_S08) && (addr > 3)) { | 924 | if ((type == MCP_TYPE_S08) && (addr > 3)) { |
922 | dev_err(&spi->dev, | 925 | dev_err(&spi->dev, |
923 | "mcp23s08 only supports address 0..3\n"); | 926 | "mcp23s08 only supports address 0..3\n"); |
924 | return -EINVAL; | 927 | return -EINVAL; |
925 | } | 928 | } |
926 | spi_present_mask |= 1 << addr; | 929 | spi_present_mask |= 1 << addr; |
927 | } | 930 | } |
928 | } | 931 | } |
929 | 932 | ||
930 | if (!chips) | 933 | if (!chips) |
931 | return -ENODEV; | 934 | return -ENODEV; |
932 | 935 | ||
933 | data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08), | 936 | data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08), |
934 | GFP_KERNEL); | 937 | GFP_KERNEL); |
935 | if (!data) | 938 | if (!data) |
936 | return -ENOMEM; | 939 | return -ENOMEM; |
937 | spi_set_drvdata(spi, data); | 940 | spi_set_drvdata(spi, data); |
938 | 941 | ||
939 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { | 942 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
940 | if (!(spi_present_mask & (1 << addr))) | 943 | if (!(spi_present_mask & (1 << addr))) |
941 | continue; | 944 | continue; |
942 | chips--; | 945 | chips--; |
943 | data->mcp[addr] = &data->chip[chips]; | 946 | data->mcp[addr] = &data->chip[chips]; |
944 | status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, | 947 | status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, |
945 | 0x40 | (addr << 1), type, pdata, | 948 | 0x40 | (addr << 1), type, pdata, |
946 | addr); | 949 | addr); |
947 | if (status < 0) | 950 | if (status < 0) |
948 | goto fail; | 951 | goto fail; |
949 | 952 | ||
950 | if (pdata->base != -1) | 953 | if (pdata->base != -1) |
951 | pdata->base += (type == MCP_TYPE_S17) ? 16 : 8; | 954 | pdata->base += (type == MCP_TYPE_S17) ? 16 : 8; |
952 | ngpio += (type == MCP_TYPE_S17) ? 16 : 8; | 955 | ngpio += (type == MCP_TYPE_S17) ? 16 : 8; |
953 | } | 956 | } |
954 | data->ngpio = ngpio; | 957 | data->ngpio = ngpio; |
955 | 958 | ||
956 | /* NOTE: these chips have a relatively sane IRQ framework, with | 959 | /* NOTE: these chips have a relatively sane IRQ framework, with |
957 | * per-signal masking and level/edge triggering. It's not yet | 960 | * per-signal masking and level/edge triggering. It's not yet |
958 | * handled here... | 961 | * handled here... |
959 | */ | 962 | */ |
960 | 963 | ||
961 | return 0; | 964 | return 0; |
962 | 965 | ||
963 | fail: | 966 | fail: |
964 | for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { | 967 | for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { |
965 | 968 | ||
966 | if (!data->mcp[addr]) | 969 | if (!data->mcp[addr]) |
967 | continue; | 970 | continue; |
968 | gpiochip_remove(&data->mcp[addr]->chip); | 971 | gpiochip_remove(&data->mcp[addr]->chip); |
969 | } | 972 | } |
970 | kfree(data); | 973 | kfree(data); |
971 | return status; | 974 | return status; |
972 | } | 975 | } |
973 | 976 | ||
974 | static int mcp23s08_remove(struct spi_device *spi) | 977 | static int mcp23s08_remove(struct spi_device *spi) |
975 | { | 978 | { |
976 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); | 979 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); |
977 | unsigned addr; | 980 | unsigned addr; |
978 | 981 | ||
979 | for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { | 982 | for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { |
980 | 983 | ||
981 | if (!data->mcp[addr]) | 984 | if (!data->mcp[addr]) |
982 | continue; | 985 | continue; |
983 | 986 | ||
984 | gpiochip_remove(&data->mcp[addr]->chip); | 987 | gpiochip_remove(&data->mcp[addr]->chip); |
985 | } | 988 | } |
986 | kfree(data); | 989 | kfree(data); |
987 | return 0; | 990 | return 0; |
988 | } | 991 | } |
989 | 992 | ||
990 | static const struct spi_device_id mcp23s08_ids[] = { | 993 | static const struct spi_device_id mcp23s08_ids[] = { |
991 | { "mcp23s08", MCP_TYPE_S08 }, | 994 | { "mcp23s08", MCP_TYPE_S08 }, |
992 | { "mcp23s17", MCP_TYPE_S17 }, | 995 | { "mcp23s17", MCP_TYPE_S17 }, |
993 | { }, | 996 | { }, |
994 | }; | 997 | }; |
995 | MODULE_DEVICE_TABLE(spi, mcp23s08_ids); | 998 | MODULE_DEVICE_TABLE(spi, mcp23s08_ids); |
996 | 999 | ||
997 | static struct spi_driver mcp23s08_driver = { | 1000 | static struct spi_driver mcp23s08_driver = { |
998 | .probe = mcp23s08_probe, | 1001 | .probe = mcp23s08_probe, |
999 | .remove = mcp23s08_remove, | 1002 | .remove = mcp23s08_remove, |
1000 | .id_table = mcp23s08_ids, | 1003 | .id_table = mcp23s08_ids, |
1001 | .driver = { | 1004 | .driver = { |
1002 | .name = "mcp23s08", | 1005 | .name = "mcp23s08", |
1003 | .owner = THIS_MODULE, | 1006 | .owner = THIS_MODULE, |
1004 | .of_match_table = of_match_ptr(mcp23s08_spi_of_match), | 1007 | .of_match_table = of_match_ptr(mcp23s08_spi_of_match), |
1005 | }, | 1008 | }, |
1006 | }; | 1009 | }; |
1007 | 1010 | ||
1008 | static int __init mcp23s08_spi_init(void) | 1011 | static int __init mcp23s08_spi_init(void) |
1009 | { | 1012 | { |
1010 | return spi_register_driver(&mcp23s08_driver); | 1013 | return spi_register_driver(&mcp23s08_driver); |
1011 | } | 1014 | } |
1012 | 1015 | ||
1013 | static void mcp23s08_spi_exit(void) | 1016 | static void mcp23s08_spi_exit(void) |
1014 | { | 1017 | { |
1015 | spi_unregister_driver(&mcp23s08_driver); | 1018 | spi_unregister_driver(&mcp23s08_driver); |
1016 | } | 1019 | } |
1017 | 1020 | ||
1018 | #else | 1021 | #else |
1019 | 1022 | ||
1020 | static int __init mcp23s08_spi_init(void) { return 0; } | 1023 | static int __init mcp23s08_spi_init(void) { return 0; } |
1021 | static void mcp23s08_spi_exit(void) { } | 1024 | static void mcp23s08_spi_exit(void) { } |
1022 | 1025 | ||
1023 | #endif /* CONFIG_SPI_MASTER */ | 1026 | #endif /* CONFIG_SPI_MASTER */ |
1024 | 1027 | ||
1025 | /*----------------------------------------------------------------------*/ | 1028 | /*----------------------------------------------------------------------*/ |
1026 | 1029 | ||
1027 | static int __init mcp23s08_init(void) | 1030 | static int __init mcp23s08_init(void) |
1028 | { | 1031 | { |
1029 | int ret; | 1032 | int ret; |
1030 | 1033 | ||
1031 | ret = mcp23s08_spi_init(); | 1034 | ret = mcp23s08_spi_init(); |
1032 | if (ret) | 1035 | if (ret) |
1033 | goto spi_fail; | 1036 | goto spi_fail; |
1034 | 1037 | ||
1035 | ret = mcp23s08_i2c_init(); | 1038 | ret = mcp23s08_i2c_init(); |
1036 | if (ret) | 1039 | if (ret) |
1037 | goto i2c_fail; | 1040 | goto i2c_fail; |
1038 | 1041 | ||
1039 | return 0; | 1042 | return 0; |
1040 | 1043 | ||
1041 | i2c_fail: | 1044 | i2c_fail: |
1042 | mcp23s08_spi_exit(); | 1045 | mcp23s08_spi_exit(); |
1043 | spi_fail: | 1046 | spi_fail: |
1044 | return ret; | 1047 | return ret; |
1045 | } | 1048 | } |
1046 | /* register after spi/i2c postcore initcall and before | 1049 | /* register after spi/i2c postcore initcall and before |
1047 | * subsys initcalls that may rely on these GPIOs | 1050 | * subsys initcalls that may rely on these GPIOs |
1048 | */ | 1051 | */ |
1049 | subsys_initcall(mcp23s08_init); | 1052 | subsys_initcall(mcp23s08_init); |
1050 | 1053 | ||
1051 | static void __exit mcp23s08_exit(void) | 1054 | static void __exit mcp23s08_exit(void) |
1052 | { | 1055 | { |
1053 | mcp23s08_spi_exit(); | 1056 | mcp23s08_spi_exit(); |
1054 | mcp23s08_i2c_exit(); | 1057 | mcp23s08_i2c_exit(); |
1055 | } | 1058 | } |
1056 | module_exit(mcp23s08_exit); | 1059 | module_exit(mcp23s08_exit); |
1057 | 1060 | ||
1058 | MODULE_LICENSE("GPL"); | 1061 | MODULE_LICENSE("GPL"); |
1059 | 1062 |