blob: ef2657e74d0f9a6605efa40e2ff60f8fce89979e [file] [log] [blame]
Michael Bohan0ba63b82012-02-06 13:42:34 -08001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Michael Bohane25e15f2012-04-12 17:28:26 -070013#define pr_fmt(fmt) "%s: " fmt, __func__
14
Michael Bohan0ba63b82012-02-06 13:42:34 -080015#include <linux/interrupt.h>
16#include <linux/types.h>
17#include <linux/spmi.h>
18#include <linux/platform_device.h>
Michael Bohana19dced2012-04-24 13:14:50 -070019#include <linux/debugfs.h>
Michael Bohan0ba63b82012-02-06 13:42:34 -080020#include <linux/gpio.h>
21#include <linux/slab.h>
22#include <linux/of.h>
23#include <linux/of_gpio.h>
24#include <linux/of_irq.h>
Michael Bohan0b24fb12012-06-01 10:30:12 -070025#include <linux/export.h>
26#include <linux/module.h>
Michael Bohan0ba63b82012-02-06 13:42:34 -080027#include <linux/qpnp/gpio.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070028#include <linux/export.h>
Michael Bohan0ba63b82012-02-06 13:42:34 -080029
Michael Bohan0ba63b82012-02-06 13:42:34 -080030#define Q_REG_ADDR(q_spec, reg_index) \
31 ((q_spec)->offset + reg_index)
32
33#define Q_REG_STATUS1 0x8
Michael Bohane25e15f2012-04-12 17:28:26 -070034#define Q_NUM_CTL_REGS 7
35
36/* type registers base address offsets */
37#define Q_REG_TYPE 0x10
38#define Q_REG_SUBTYPE 0x11
39
40/* gpio peripheral type and subtype values */
41#define Q_GPIO_TYPE 0x10
42#define Q_GPIO_SUBTYPE_GPIO_4CH 0x1
43#define Q_GPIO_SUBTYPE_GPIOC_4CH 0x5
44#define Q_GPIO_SUBTYPE_GPIO_8CH 0x9
45#define Q_GPIO_SUBTYPE_GPIOC_8CH 0xD
Michael Bohan0ba63b82012-02-06 13:42:34 -080046
47/* control register base address offsets */
Michael Bohane25e15f2012-04-12 17:28:26 -070048#define Q_REG_MODE_CTL 0x40
49#define Q_REG_DIG_PULL_CTL 0x42
50#define Q_REG_DIG_IN_CTL 0x43
51#define Q_REG_DIG_VIN_CTL 0x44
52#define Q_REG_DIG_OUT_CTL 0x45
53#define Q_REG_EN_CTL 0x46
Michael Bohan0ba63b82012-02-06 13:42:34 -080054
55/* control register regs array indices */
Michael Bohane25e15f2012-04-12 17:28:26 -070056#define Q_REG_I_MODE_CTL 0
57#define Q_REG_I_DIG_PULL_CTL 2
58#define Q_REG_I_DIG_IN_CTL 3
59#define Q_REG_I_DIG_VIN_CTL 4
60#define Q_REG_I_DIG_OUT_CTL 5
61#define Q_REG_I_EN_CTL 6
Michael Bohan0ba63b82012-02-06 13:42:34 -080062
Michael Bohane25e15f2012-04-12 17:28:26 -070063/* control reg: mode */
Michael Bohan0ba63b82012-02-06 13:42:34 -080064#define Q_REG_OUT_INVERT_SHIFT 0
65#define Q_REG_OUT_INVERT_MASK 0x1
66#define Q_REG_SRC_SEL_SHIFT 1
67#define Q_REG_SRC_SEL_MASK 0xE
Michael Bohane25e15f2012-04-12 17:28:26 -070068#define Q_REG_MODE_SEL_SHIFT 4
69#define Q_REG_MODE_SEL_MASK 0x70
70
71/* control reg: dig_vin */
72#define Q_REG_VIN_SHIFT 0
73#define Q_REG_VIN_MASK 0x7
74
75/* control reg: dig_pull */
76#define Q_REG_PULL_SHIFT 0
77#define Q_REG_PULL_MASK 0x7
78
79/* control reg: dig_out */
80#define Q_REG_OUT_STRENGTH_SHIFT 0
81#define Q_REG_OUT_STRENGTH_MASK 0x3
82#define Q_REG_OUT_TYPE_SHIFT 4
83#define Q_REG_OUT_TYPE_MASK 0x30
84
85/* control reg: en */
Michael Bohan0ba63b82012-02-06 13:42:34 -080086#define Q_REG_MASTER_EN_SHIFT 7
87#define Q_REG_MASTER_EN_MASK 0x80
88
Michael Bohana19dced2012-04-24 13:14:50 -070089enum qpnp_gpio_param_type {
90 Q_GPIO_CFG_DIRECTION,
91 Q_GPIO_CFG_OUTPUT_TYPE,
92 Q_GPIO_CFG_INVERT,
93 Q_GPIO_CFG_PULL,
94 Q_GPIO_CFG_VIN_SEL,
95 Q_GPIO_CFG_OUT_STRENGTH,
96 Q_GPIO_CFG_SRC_SELECT,
97 Q_GPIO_CFG_MASTER_EN,
98 Q_GPIO_CFG_INVALID,
99};
100
101#define Q_NUM_PARAMS Q_GPIO_CFG_INVALID
102
Michael Bohane25e15f2012-04-12 17:28:26 -0700103/* param error checking */
104#define QPNP_GPIO_DIR_INVALID 3
105#define QPNP_GPIO_INVERT_INVALID 2
106#define QPNP_GPIO_OUT_BUF_INVALID 3
107#define QPNP_GPIO_VIN_INVALID 8
108#define QPNP_GPIO_PULL_INVALID 6
109#define QPNP_GPIO_OUT_STRENGTH_INVALID 4
110#define QPNP_GPIO_SRC_INVALID 8
111#define QPNP_GPIO_MASTER_INVALID 2
Michael Bohan0ba63b82012-02-06 13:42:34 -0800112
113struct qpnp_gpio_spec {
114 uint8_t slave; /* 0-15 */
115 uint16_t offset; /* 0-255 */
116 uint32_t gpio_chip_idx; /* offset from gpio_chip base */
Michael Bohane25e15f2012-04-12 17:28:26 -0700117 uint32_t pmic_gpio; /* PMIC gpio number */
Michael Bohan0ba63b82012-02-06 13:42:34 -0800118 int irq; /* logical IRQ number */
119 u8 regs[Q_NUM_CTL_REGS]; /* Control regs */
Michael Bohane25e15f2012-04-12 17:28:26 -0700120 u8 type; /* peripheral type */
121 u8 subtype; /* peripheral subtype */
Michael Bohande3942a2012-04-17 15:28:01 -0700122 struct device_node *node;
Michael Bohana19dced2012-04-24 13:14:50 -0700123 enum qpnp_gpio_param_type params[Q_NUM_PARAMS];
124 struct qpnp_gpio_chip *q_chip;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800125};
126
127struct qpnp_gpio_chip {
128 struct gpio_chip gpio_chip;
129 struct spmi_device *spmi;
130 struct qpnp_gpio_spec **pmic_gpios;
131 struct qpnp_gpio_spec **chip_gpios;
132 uint32_t pmic_gpio_lowest;
133 uint32_t pmic_gpio_highest;
134 struct device_node *int_ctrl;
135 struct list_head chip_list;
Michael Bohana19dced2012-04-24 13:14:50 -0700136 struct dentry *dfs_dir;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800137};
138
139static LIST_HEAD(qpnp_gpio_chips);
140static DEFINE_MUTEX(qpnp_gpio_chips_lock);
141
142static inline void qpnp_pmic_gpio_set_spec(struct qpnp_gpio_chip *q_chip,
143 uint32_t pmic_gpio,
144 struct qpnp_gpio_spec *spec)
145{
146 q_chip->pmic_gpios[pmic_gpio - q_chip->pmic_gpio_lowest] = spec;
147}
148
149static inline struct qpnp_gpio_spec *qpnp_pmic_gpio_get_spec(
150 struct qpnp_gpio_chip *q_chip,
151 uint32_t pmic_gpio)
152{
153 if (pmic_gpio < q_chip->pmic_gpio_lowest ||
154 pmic_gpio > q_chip->pmic_gpio_highest)
155 return NULL;
156
157 return q_chip->pmic_gpios[pmic_gpio - q_chip->pmic_gpio_lowest];
158}
159
160static inline struct qpnp_gpio_spec *qpnp_chip_gpio_get_spec(
161 struct qpnp_gpio_chip *q_chip,
162 uint32_t chip_gpio)
163{
164 if (chip_gpio > q_chip->gpio_chip.ngpio)
165 return NULL;
166
167 return q_chip->chip_gpios[chip_gpio];
168}
169
170static inline void qpnp_chip_gpio_set_spec(struct qpnp_gpio_chip *q_chip,
171 uint32_t chip_gpio,
172 struct qpnp_gpio_spec *spec)
173{
174 q_chip->chip_gpios[chip_gpio] = spec;
175}
176
Michael Bohane25e15f2012-04-12 17:28:26 -0700177static int qpnp_gpio_check_config(struct qpnp_gpio_spec *q_spec,
178 struct qpnp_gpio_cfg *param)
179{
180 int gpio = q_spec->pmic_gpio;
181
182 if (param->direction >= QPNP_GPIO_DIR_INVALID)
183 pr_err("invalid direction for gpio %d\n", gpio);
184 else if (param->invert >= QPNP_GPIO_INVERT_INVALID)
185 pr_err("invalid invert polarity for gpio %d\n", gpio);
186 else if (param->src_select >= QPNP_GPIO_SRC_INVALID)
187 pr_err("invalid source select for gpio %d\n", gpio);
188 else if (param->out_strength >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
189 param->out_strength == 0)
190 pr_err("invalid out strength for gpio %d\n", gpio);
191 else if (param->output_type >= QPNP_GPIO_OUT_BUF_INVALID)
192 pr_err("invalid out type for gpio %d\n", gpio);
193 else if ((param->output_type == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
194 param->output_type == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
195 (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
196 (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH)))
197 pr_err("invalid out type for gpio %d\n"
198 "gpioc does not support open-drain\n", gpio);
199 else if (param->vin_sel >= QPNP_GPIO_VIN_INVALID)
200 pr_err("invalid vin select value for gpio %d\n", gpio);
201 else if (param->pull >= QPNP_GPIO_PULL_INVALID)
202 pr_err("invalid pull value for gpio %d\n", gpio);
203 else if (param->master_en >= QPNP_GPIO_MASTER_INVALID)
204 pr_err("invalid master_en value for gpio %d\n", gpio);
205 else
206 return 0;
207
208 return -EINVAL;
209}
210
Michael Bohande3942a2012-04-17 15:28:01 -0700211static inline u8 q_reg_get(u8 *reg, int shift, int mask)
212{
213 return (*reg & mask) >> shift;
214}
215
Michael Bohane25e15f2012-04-12 17:28:26 -0700216static inline void q_reg_set(u8 *reg, int shift, int mask, int value)
217{
218 *reg |= (value << shift) & mask;
219}
220
221static inline void q_reg_clr_set(u8 *reg, int shift, int mask, int value)
222{
223 *reg &= ~mask;
224 *reg |= (value << shift) & mask;
225}
226
Michael Bohande3942a2012-04-17 15:28:01 -0700227static int qpnp_gpio_cache_regs(struct qpnp_gpio_chip *q_chip,
228 struct qpnp_gpio_spec *q_spec)
229{
230 int rc;
231 struct device *dev = &q_chip->spmi->dev;
232
233 rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
234 Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
235 &q_spec->regs[Q_REG_I_MODE_CTL],
236 Q_NUM_CTL_REGS);
237 if (rc)
238 dev_err(dev, "%s: unable to read control regs\n", __func__);
239
240 return rc;
241}
242
Michael Bohane25e15f2012-04-12 17:28:26 -0700243static int _qpnp_gpio_config(struct qpnp_gpio_chip *q_chip,
244 struct qpnp_gpio_spec *q_spec,
245 struct qpnp_gpio_cfg *param)
246{
247 struct device *dev = &q_chip->spmi->dev;
248 int rc;
249
250 rc = qpnp_gpio_check_config(q_spec, param);
251 if (rc)
252 goto gpio_cfg;
253
254 /* set direction */
255 q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
256 Q_REG_MODE_SEL_SHIFT, Q_REG_MODE_SEL_MASK,
257 param->direction);
258
259 /* output specific configuration */
260 q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
261 Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK,
262 param->invert);
263 q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
264 Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK,
265 param->src_select);
266 q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
267 Q_REG_OUT_STRENGTH_SHIFT, Q_REG_OUT_STRENGTH_MASK,
268 param->out_strength);
269 q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
270 Q_REG_OUT_TYPE_SHIFT, Q_REG_OUT_TYPE_MASK,
271 param->output_type);
272
273 /* config applicable for both input / output */
274 q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
275 Q_REG_VIN_SHIFT, Q_REG_VIN_MASK,
276 param->vin_sel);
277 q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_PULL_CTL],
278 Q_REG_PULL_SHIFT, Q_REG_PULL_MASK,
279 param->pull);
280 q_reg_clr_set(&q_spec->regs[Q_REG_I_EN_CTL],
281 Q_REG_MASTER_EN_SHIFT, Q_REG_MASTER_EN_MASK,
282 param->master_en);
283
284 rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
285 Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
286 &q_spec->regs[Q_REG_I_MODE_CTL], Q_NUM_CTL_REGS);
287 if (rc) {
288 dev_err(&q_chip->spmi->dev, "%s: unable to write master"
289 " enable\n", __func__);
290 goto gpio_cfg;
291 }
292
293 return 0;
294
295gpio_cfg:
296 dev_err(dev, "%s: unable to set default config for"
297 " pmic gpio %d\n", __func__, q_spec->pmic_gpio);
298
299 return rc;
300}
301
Michael Bohan0ba63b82012-02-06 13:42:34 -0800302int qpnp_gpio_config(int gpio, struct qpnp_gpio_cfg *param)
303{
304 int rc, chip_offset;
305 struct qpnp_gpio_chip *q_chip;
306 struct qpnp_gpio_spec *q_spec = NULL;
307 struct gpio_chip *gpio_chip;
308
309 if (param == NULL)
310 return -EINVAL;
311
312 mutex_lock(&qpnp_gpio_chips_lock);
313 list_for_each_entry(q_chip, &qpnp_gpio_chips, chip_list) {
314 gpio_chip = &q_chip->gpio_chip;
315 if (gpio >= gpio_chip->base
316 && gpio < gpio_chip->base + gpio_chip->ngpio) {
317 chip_offset = gpio - gpio_chip->base;
318 q_spec = qpnp_chip_gpio_get_spec(q_chip, chip_offset);
319 if (WARN_ON(!q_spec)) {
320 mutex_unlock(&qpnp_gpio_chips_lock);
321 return -ENODEV;
322 }
323 break;
324 }
325 }
326 mutex_unlock(&qpnp_gpio_chips_lock);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800327
Michael Bohane25e15f2012-04-12 17:28:26 -0700328 rc = _qpnp_gpio_config(q_chip, q_spec, param);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800329
330 return rc;
331}
332EXPORT_SYMBOL(qpnp_gpio_config);
333
334int qpnp_gpio_map_gpio(uint16_t slave_id, uint32_t pmic_gpio)
335{
336 struct qpnp_gpio_chip *q_chip;
337 struct qpnp_gpio_spec *q_spec = NULL;
338
339 mutex_lock(&qpnp_gpio_chips_lock);
340 list_for_each_entry(q_chip, &qpnp_gpio_chips, chip_list) {
341 if (q_chip->spmi->sid != slave_id)
342 continue;
343 if (q_chip->pmic_gpio_lowest <= pmic_gpio &&
344 q_chip->pmic_gpio_highest >= pmic_gpio) {
345 q_spec = qpnp_pmic_gpio_get_spec(q_chip, pmic_gpio);
346 mutex_unlock(&qpnp_gpio_chips_lock);
347 if (WARN_ON(!q_spec))
348 return -ENODEV;
349 return q_chip->gpio_chip.base + q_spec->gpio_chip_idx;
350 }
351 }
352 mutex_unlock(&qpnp_gpio_chips_lock);
353 return -EINVAL;
354}
355EXPORT_SYMBOL(qpnp_gpio_map_gpio);
356
357static int qpnp_gpio_to_irq(struct gpio_chip *gpio_chip, unsigned offset)
358{
359 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
360 struct qpnp_gpio_spec *q_spec;
361
362 q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
363 if (!q_spec)
364 return -EINVAL;
365
366 return q_spec->irq;
367}
368
369static int qpnp_gpio_get(struct gpio_chip *gpio_chip, unsigned offset)
370{
371 int rc, ret_val;
372 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
373 struct qpnp_gpio_spec *q_spec = NULL;
374 u8 buf[1];
375
376 if (WARN_ON(!q_chip))
377 return -ENODEV;
378
379 q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
380 if (WARN_ON(!q_spec))
381 return -ENODEV;
382
383 /* gpio val is from RT status iff input is enabled */
Michael Bohane25e15f2012-04-12 17:28:26 -0700384 if ((q_spec->regs[Q_REG_I_MODE_CTL] & Q_REG_MODE_SEL_MASK)
385 == QPNP_GPIO_DIR_IN) {
Michael Bohan0ba63b82012-02-06 13:42:34 -0800386 /* INT_RT_STS */
387 rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
388 Q_REG_ADDR(q_spec, Q_REG_STATUS1),
389 &buf[0], 1);
390 return buf[0];
391
392 } else {
Michael Bohane25e15f2012-04-12 17:28:26 -0700393 ret_val = (q_spec->regs[Q_REG_I_MODE_CTL] &
Michael Bohan0ba63b82012-02-06 13:42:34 -0800394 Q_REG_OUT_INVERT_MASK) >> Q_REG_OUT_INVERT_SHIFT;
395 return ret_val;
396 }
397
398 return 0;
399}
400
401static int __qpnp_gpio_set(struct qpnp_gpio_chip *q_chip,
402 struct qpnp_gpio_spec *q_spec, int value)
403{
404 int rc;
405
406 if (!q_chip || !q_spec)
407 return -EINVAL;
408
Michael Bohan0ba63b82012-02-06 13:42:34 -0800409 if (value)
Michael Bohane25e15f2012-04-12 17:28:26 -0700410 q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
411 Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK, 1);
412 else
413 q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
414 Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK, 0);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800415
416 rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
Michael Bohane25e15f2012-04-12 17:28:26 -0700417 Q_REG_ADDR(q_spec, Q_REG_I_MODE_CTL),
418 &q_spec->regs[Q_REG_I_MODE_CTL], 1);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800419 if (rc)
420 dev_err(&q_chip->spmi->dev, "%s: spmi write failed\n",
421 __func__);
422 return rc;
423}
424
425
426static void qpnp_gpio_set(struct gpio_chip *gpio_chip,
427 unsigned offset, int value)
428{
429 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
430 struct qpnp_gpio_spec *q_spec;
431
432 if (WARN_ON(!q_chip))
433 return;
434
435 q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
436 if (WARN_ON(!q_spec))
437 return;
438
439 __qpnp_gpio_set(q_chip, q_spec, value);
440}
441
442static int qpnp_gpio_set_direction(struct qpnp_gpio_chip *q_chip,
443 struct qpnp_gpio_spec *q_spec, int direction)
444{
445 int rc;
446
447 if (!q_chip || !q_spec)
448 return -EINVAL;
449
Michael Bohane25e15f2012-04-12 17:28:26 -0700450 if (direction >= QPNP_GPIO_DIR_INVALID) {
451 pr_err("invalid direction specification %d\n", direction);
452 return -EINVAL;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800453 }
454
Michael Bohane25e15f2012-04-12 17:28:26 -0700455 q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
456 Q_REG_MODE_SEL_SHIFT,
457 Q_REG_MODE_SEL_MASK,
458 direction);
459
Michael Bohan0ba63b82012-02-06 13:42:34 -0800460 rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
Michael Bohane25e15f2012-04-12 17:28:26 -0700461 Q_REG_ADDR(q_spec, Q_REG_I_MODE_CTL),
462 &q_spec->regs[Q_REG_I_MODE_CTL], 1);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800463 return rc;
464}
465
466static int qpnp_gpio_direction_input(struct gpio_chip *gpio_chip,
467 unsigned offset)
468{
469 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
470 struct qpnp_gpio_spec *q_spec;
471
472 if (WARN_ON(!q_chip))
473 return -ENODEV;
474
475 q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
476 if (WARN_ON(!q_spec))
477 return -ENODEV;
478
479 return qpnp_gpio_set_direction(q_chip, q_spec, QPNP_GPIO_DIR_IN);
480}
481
482static int qpnp_gpio_direction_output(struct gpio_chip *gpio_chip,
483 unsigned offset,
484 int val)
485{
486 int rc;
487 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
488 struct qpnp_gpio_spec *q_spec;
489
490 if (WARN_ON(!q_chip))
491 return -ENODEV;
492
493 q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
494 if (WARN_ON(!q_spec))
495 return -ENODEV;
496
497 rc = __qpnp_gpio_set(q_chip, q_spec, val);
498 if (rc)
499 return rc;
500
501 rc = qpnp_gpio_set_direction(q_chip, q_spec, QPNP_GPIO_DIR_OUT);
502
503 return rc;
504}
505
506static int qpnp_gpio_of_gpio_xlate(struct gpio_chip *gpio_chip,
Michael Bohan0b24fb12012-06-01 10:30:12 -0700507 const struct of_phandle_args *gpio_spec,
508 u32 *flags)
Michael Bohan0ba63b82012-02-06 13:42:34 -0800509{
510 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
511 struct qpnp_gpio_spec *q_spec;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800512
513 if (WARN_ON(gpio_chip->of_gpio_n_cells < 2)) {
Michael Bohane25e15f2012-04-12 17:28:26 -0700514 pr_err("of_gpio_n_cells < 2\n");
Michael Bohan0ba63b82012-02-06 13:42:34 -0800515 return -EINVAL;
516 }
517
Michael Bohan0b24fb12012-06-01 10:30:12 -0700518 q_spec = qpnp_pmic_gpio_get_spec(q_chip, gpio_spec->args[0]);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800519 if (!q_spec) {
Michael Bohan0b24fb12012-06-01 10:30:12 -0700520 pr_err("no such PMIC gpio %u in device topology\n",
521 gpio_spec->args[0]);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800522 return -EINVAL;
523 }
524
525 if (flags)
Michael Bohan0b24fb12012-06-01 10:30:12 -0700526 *flags = gpio_spec->args[1];
Michael Bohan0ba63b82012-02-06 13:42:34 -0800527
528 return q_spec->gpio_chip_idx;
529}
530
Michael Bohande3942a2012-04-17 15:28:01 -0700531static int qpnp_gpio_apply_config(struct qpnp_gpio_chip *q_chip,
532 struct qpnp_gpio_spec *q_spec)
Michael Bohan0ba63b82012-02-06 13:42:34 -0800533{
534 struct qpnp_gpio_cfg param;
Michael Bohande3942a2012-04-17 15:28:01 -0700535 struct device_node *node = q_spec->node;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800536 int rc;
537
Michael Bohande3942a2012-04-17 15:28:01 -0700538 param.direction = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
539 Q_REG_MODE_SEL_SHIFT,
540 Q_REG_MODE_SEL_MASK);
541 param.output_type = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
542 Q_REG_OUT_TYPE_SHIFT,
543 Q_REG_OUT_TYPE_MASK);
544 param.invert = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
545 Q_REG_OUT_INVERT_MASK,
546 Q_REG_OUT_INVERT_MASK);
547 param.pull = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
548 Q_REG_PULL_SHIFT, Q_REG_PULL_MASK);
549 param.vin_sel = q_reg_get(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
550 Q_REG_VIN_SHIFT, Q_REG_VIN_MASK);
551 param.out_strength = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
552 Q_REG_OUT_STRENGTH_SHIFT,
553 Q_REG_OUT_STRENGTH_MASK);
554 param.src_select = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
555 Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK);
556 param.master_en = q_reg_get(&q_spec->regs[Q_REG_I_EN_CTL],
557 Q_REG_MASTER_EN_SHIFT,
558 Q_REG_MASTER_EN_MASK);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800559
Michael Bohande3942a2012-04-17 15:28:01 -0700560 of_property_read_u32(node, "qcom,direction",
561 &param.direction);
562 of_property_read_u32(node, "qcom,output-type",
563 &param.output_type);
564 of_property_read_u32(node, "qcom,invert",
565 &param.invert);
566 of_property_read_u32(node, "qcom,pull",
567 &param.pull);
568 of_property_read_u32(node, "qcom,vin-sel",
569 &param.vin_sel);
570 of_property_read_u32(node, "qcom,out-strength",
571 &param.out_strength);
572 of_property_read_u32(node, "qcom,src-select",
573 &param.src_select);
574 rc = of_property_read_u32(node, "qcom,master-en",
575 &param.master_en);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800576
Michael Bohande3942a2012-04-17 15:28:01 -0700577 rc = _qpnp_gpio_config(q_chip, q_spec, &param);
578
Michael Bohan0ba63b82012-02-06 13:42:34 -0800579 return rc;
580}
581
582static int qpnp_gpio_free_chip(struct qpnp_gpio_chip *q_chip)
583{
584 struct spmi_device *spmi = q_chip->spmi;
585 int rc, i;
586
587 if (q_chip->chip_gpios)
588 for (i = 0; i < spmi->num_dev_node; i++)
589 kfree(q_chip->chip_gpios[i]);
590
591 mutex_lock(&qpnp_gpio_chips_lock);
592 list_del(&q_chip->chip_list);
593 mutex_unlock(&qpnp_gpio_chips_lock);
594 rc = gpiochip_remove(&q_chip->gpio_chip);
595 if (rc)
596 dev_err(&q_chip->spmi->dev, "%s: unable to remove gpio\n",
597 __func__);
598 kfree(q_chip->chip_gpios);
599 kfree(q_chip->pmic_gpios);
600 kfree(q_chip);
601 return rc;
602}
603
Michael Bohana19dced2012-04-24 13:14:50 -0700604#ifdef CONFIG_GPIO_QPNP_DEBUG
605struct qpnp_gpio_reg {
606 uint32_t addr;
607 uint32_t idx;
608 uint32_t shift;
609 uint32_t mask;
610};
611
612static struct dentry *driver_dfs_dir;
613
614static int qpnp_gpio_reg_attr(enum qpnp_gpio_param_type type,
615 struct qpnp_gpio_reg *cfg)
616{
617 switch (type) {
618 case Q_GPIO_CFG_DIRECTION:
619 cfg->addr = Q_REG_MODE_CTL;
620 cfg->idx = Q_REG_I_MODE_CTL;
621 cfg->shift = Q_REG_MODE_SEL_SHIFT;
622 cfg->mask = Q_REG_MODE_SEL_MASK;
623 break;
624 case Q_GPIO_CFG_OUTPUT_TYPE:
625 cfg->addr = Q_REG_DIG_OUT_CTL;
626 cfg->idx = Q_REG_I_DIG_OUT_CTL;
627 cfg->shift = Q_REG_OUT_TYPE_SHIFT;
628 cfg->mask = Q_REG_OUT_TYPE_MASK;
629 break;
630 case Q_GPIO_CFG_INVERT:
631 cfg->addr = Q_REG_MODE_CTL;
632 cfg->idx = Q_REG_I_MODE_CTL;
633 cfg->shift = Q_REG_OUT_INVERT_SHIFT;
634 cfg->mask = Q_REG_OUT_INVERT_MASK;
635 break;
636 case Q_GPIO_CFG_PULL:
637 cfg->addr = Q_REG_DIG_PULL_CTL;
638 cfg->idx = Q_REG_I_DIG_PULL_CTL;
639 cfg->shift = Q_REG_PULL_SHIFT;
640 cfg->mask = Q_REG_PULL_MASK;
641 break;
642 case Q_GPIO_CFG_VIN_SEL:
643 cfg->addr = Q_REG_DIG_VIN_CTL;
644 cfg->idx = Q_REG_I_DIG_VIN_CTL;
645 cfg->shift = Q_REG_VIN_SHIFT;
646 cfg->mask = Q_REG_VIN_MASK;
647 break;
648 case Q_GPIO_CFG_OUT_STRENGTH:
649 cfg->addr = Q_REG_DIG_OUT_CTL;
650 cfg->idx = Q_REG_I_DIG_OUT_CTL;
651 cfg->shift = Q_REG_OUT_STRENGTH_SHIFT;
652 cfg->mask = Q_REG_OUT_STRENGTH_MASK;
653 break;
654 case Q_GPIO_CFG_SRC_SELECT:
655 cfg->addr = Q_REG_MODE_CTL;
656 cfg->idx = Q_REG_I_MODE_CTL;
657 cfg->shift = Q_REG_SRC_SEL_SHIFT;
658 cfg->mask = Q_REG_SRC_SEL_MASK;
659 break;
660 case Q_GPIO_CFG_MASTER_EN:
661 cfg->addr = Q_REG_EN_CTL;
662 cfg->idx = Q_REG_I_EN_CTL;
663 cfg->shift = Q_REG_MASTER_EN_SHIFT;
664 cfg->mask = Q_REG_MASTER_EN_MASK;
665 break;
666 default:
667 return -EINVAL;
668 }
669
670 return 0;
671}
672
673static int qpnp_gpio_debugfs_get(void *data, u64 *val)
674{
675 enum qpnp_gpio_param_type *idx = data;
676 struct qpnp_gpio_spec *q_spec;
677 struct qpnp_gpio_reg cfg = {};
678 int rc;
679
680 rc = qpnp_gpio_reg_attr(*idx, &cfg);
681 if (rc)
682 return rc;
683 q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
684 *val = q_reg_get(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask);
685 return 0;
686}
687
688static int qpnp_gpio_check_reg_val(enum qpnp_gpio_param_type idx,
689 struct qpnp_gpio_spec *q_spec,
690 uint32_t val)
691{
692 switch (idx) {
693 case Q_GPIO_CFG_DIRECTION:
694 if (val >= QPNP_GPIO_DIR_INVALID)
695 return -EINVAL;
696 break;
697 case Q_GPIO_CFG_OUTPUT_TYPE:
698 if ((val >= QPNP_GPIO_OUT_BUF_INVALID) ||
699 ((val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
700 val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
701 (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
702 (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH))))
703 return -EINVAL;
704 break;
705 case Q_GPIO_CFG_INVERT:
706 if (val >= QPNP_GPIO_INVERT_INVALID)
707 return -EINVAL;
708 break;
709 case Q_GPIO_CFG_PULL:
710 if (val >= QPNP_GPIO_PULL_INVALID)
711 return -EINVAL;
712 break;
713 case Q_GPIO_CFG_VIN_SEL:
714 if (val >= QPNP_GPIO_VIN_INVALID)
715 return -EINVAL;
716 break;
717 case Q_GPIO_CFG_OUT_STRENGTH:
718 if (val >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
719 val == 0)
720 return -EINVAL;
721 break;
722 case Q_GPIO_CFG_SRC_SELECT:
723 if (val >= QPNP_GPIO_SRC_INVALID)
724 return -EINVAL;
725 break;
726 case Q_GPIO_CFG_MASTER_EN:
727 if (val >= QPNP_GPIO_MASTER_INVALID)
728 return -EINVAL;
729 break;
730 default:
731 pr_err("invalid param type %u specified\n", idx);
732 return -EINVAL;
733 }
734 return 0;
735}
736
737static int qpnp_gpio_debugfs_set(void *data, u64 val)
738{
739 enum qpnp_gpio_param_type *idx = data;
740 struct qpnp_gpio_spec *q_spec;
741 struct qpnp_gpio_chip *q_chip;
742 struct qpnp_gpio_reg cfg = {};
743 int rc;
744
745 q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
746 q_chip = q_spec->q_chip;
747
748 rc = qpnp_gpio_check_reg_val(*idx, q_spec, val);
749 if (rc)
750 return rc;
751
752 rc = qpnp_gpio_reg_attr(*idx, &cfg);
753 if (rc)
754 return rc;
755 q_reg_clr_set(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask, val);
756 rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
757 Q_REG_ADDR(q_spec, cfg.addr),
758 &q_spec->regs[cfg.idx], 1);
759
760 return rc;
761}
762DEFINE_SIMPLE_ATTRIBUTE(qpnp_gpio_fops, qpnp_gpio_debugfs_get,
763 qpnp_gpio_debugfs_set, "%llu\n");
764
765#define DEBUGFS_BUF_SIZE 11 /* supports 2^32 in decimal */
766
767struct qpnp_gpio_debugfs_args {
768 enum qpnp_gpio_param_type type;
769 const char *filename;
770};
771
772static struct qpnp_gpio_debugfs_args dfs_args[] = {
773 { Q_GPIO_CFG_DIRECTION, "direction" },
774 { Q_GPIO_CFG_OUTPUT_TYPE, "output_type" },
775 { Q_GPIO_CFG_INVERT, "invert" },
776 { Q_GPIO_CFG_PULL, "pull" },
777 { Q_GPIO_CFG_VIN_SEL, "vin_sel" },
778 { Q_GPIO_CFG_OUT_STRENGTH, "out_strength" },
779 { Q_GPIO_CFG_SRC_SELECT, "src_select" },
780 { Q_GPIO_CFG_MASTER_EN, "master_en" }
781};
782
783static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
784{
785 struct spmi_device *spmi = q_chip->spmi;
786 struct device *dev = &spmi->dev;
787 struct qpnp_gpio_spec *q_spec;
788 enum qpnp_gpio_param_type *params;
789 enum qpnp_gpio_param_type type;
790 char pmic_gpio[DEBUGFS_BUF_SIZE];
791 const char *filename;
792 struct dentry *dfs, *dfs_io_dir;
793 int i, j;
794
795 BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args));
796
797 q_chip->dfs_dir = debugfs_create_dir(dev->of_node->name,
798 driver_dfs_dir);
799 if (q_chip->dfs_dir == NULL) {
800 dev_err(dev, "%s: cannot register chip debugfs directory %s\n",
801 __func__, dev->of_node->name);
802 return -ENODEV;
803 }
804
805 for (i = 0; i < spmi->num_dev_node; i++) {
806 q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
807 params = q_spec->params;
808 snprintf(pmic_gpio, DEBUGFS_BUF_SIZE, "%u", q_spec->pmic_gpio);
809 dfs_io_dir = debugfs_create_dir(pmic_gpio,
810 q_chip->dfs_dir);
811 if (dfs_io_dir == NULL)
812 goto dfs_err;
813
814 for (j = 0; j < Q_NUM_PARAMS; j++) {
815 type = dfs_args[j].type;
816 filename = dfs_args[j].filename;
817
818 params[type] = type;
819 dfs = debugfs_create_file(
820 filename,
821 S_IRUGO | S_IWUSR,
822 dfs_io_dir,
823 &q_spec->params[type],
824 &qpnp_gpio_fops);
825 if (dfs == NULL)
826 goto dfs_err;
827 }
828 }
829 return 0;
830dfs_err:
831 dev_err(dev, "%s: cannot register debugfs for pmic gpio %u on"
832 " chip %s\n", __func__,
833 q_spec->pmic_gpio, dev->of_node->name);
834 debugfs_remove_recursive(q_chip->dfs_dir);
835 return -ENFILE;
836}
837#else
838static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
839{
840 return 0;
841}
842#endif
843
Michael Bohan0ba63b82012-02-06 13:42:34 -0800844static int qpnp_gpio_probe(struct spmi_device *spmi)
845{
846 struct qpnp_gpio_chip *q_chip;
847 struct resource *res;
848 struct qpnp_gpio_spec *q_spec;
Michael Bohan94e397b2012-04-25 15:21:55 -0700849 int i, rc;
850 int lowest_gpio = UINT_MAX, highest_gpio = 0;
851 u32 intspec[3], gpio;
Michael Bohane25e15f2012-04-12 17:28:26 -0700852 char buf[2];
Michael Bohan0ba63b82012-02-06 13:42:34 -0800853
854 q_chip = kzalloc(sizeof(*q_chip), GFP_KERNEL);
855 if (!q_chip) {
856 dev_err(&spmi->dev, "%s: Can't allocate gpio_chip\n",
857 __func__);
858 return -ENOMEM;
859 }
860 q_chip->spmi = spmi;
861 dev_set_drvdata(&spmi->dev, q_chip);
862
863 mutex_lock(&qpnp_gpio_chips_lock);
864 list_add(&q_chip->chip_list, &qpnp_gpio_chips);
865 mutex_unlock(&qpnp_gpio_chips_lock);
866
867 /* first scan through nodes to find the range required for allocation */
868 for (i = 0; i < spmi->num_dev_node; i++) {
Michael Bohan94e397b2012-04-25 15:21:55 -0700869 rc = of_property_read_u32(spmi->dev_node[i].of_node,
870 "qcom,gpio-num", &gpio);
871 if (rc) {
Michael Bohan0ba63b82012-02-06 13:42:34 -0800872 dev_err(&spmi->dev, "%s: unable to get"
Michael Bohande3942a2012-04-17 15:28:01 -0700873 " qcom,gpio-num property\n", __func__);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800874 goto err_probe;
875 }
876
Michael Bohan0ba63b82012-02-06 13:42:34 -0800877 if (gpio < lowest_gpio)
878 lowest_gpio = gpio;
879 if (gpio > highest_gpio)
880 highest_gpio = gpio;
881 }
882
883 if (highest_gpio < lowest_gpio) {
884 dev_err(&spmi->dev, "%s: no device nodes specified in"
885 " topology\n", __func__);
Michael Bohanfdcbed22012-04-23 17:44:27 -0700886 rc = -EINVAL;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800887 goto err_probe;
888 } else if (lowest_gpio == 0) {
889 dev_err(&spmi->dev, "%s: 0 is not a valid PMIC GPIO\n",
890 __func__);
Michael Bohanfdcbed22012-04-23 17:44:27 -0700891 rc = -EINVAL;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800892 goto err_probe;
893 }
894
895 q_chip->pmic_gpio_lowest = lowest_gpio;
896 q_chip->pmic_gpio_highest = highest_gpio;
897
898 /* allocate gpio lookup tables */
899 q_chip->pmic_gpios = kzalloc(sizeof(struct qpnp_gpio_spec *) *
900 highest_gpio - lowest_gpio + 1,
901 GFP_KERNEL);
902 q_chip->chip_gpios = kzalloc(sizeof(struct qpnp_gpio_spec *) *
903 spmi->num_dev_node, GFP_KERNEL);
904 if (!q_chip->pmic_gpios || !q_chip->chip_gpios) {
905 dev_err(&spmi->dev, "%s: unable to allocate memory\n",
906 __func__);
Michael Bohanfdcbed22012-04-23 17:44:27 -0700907 rc = -ENOMEM;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800908 goto err_probe;
909 }
910
911 /* get interrupt controller device_node */
912 q_chip->int_ctrl = of_irq_find_parent(spmi->dev.of_node);
913 if (!q_chip->int_ctrl) {
914 dev_err(&spmi->dev, "%s: Can't find interrupt parent\n",
915 __func__);
Michael Bohanfdcbed22012-04-23 17:44:27 -0700916 rc = -EINVAL;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800917 goto err_probe;
918 }
919
920 /* now scan through again and populate the lookup table */
921 for (i = 0; i < spmi->num_dev_node; i++) {
Michael Bohan08e1e902012-05-23 10:55:22 -0700922 res = spmi_get_resource(spmi, i, IORESOURCE_MEM, 0);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800923 if (!res) {
924 dev_err(&spmi->dev, "%s: node %s is missing has no"
925 " base address definition\n",
926 __func__, spmi->dev_node[i].of_node->full_name);
927 }
928
Michael Bohan94e397b2012-04-25 15:21:55 -0700929 rc = of_property_read_u32(spmi->dev_node[i].of_node,
930 "qcom,gpio-num", &gpio);
931 if (rc) {
Michael Bohan0ba63b82012-02-06 13:42:34 -0800932 dev_err(&spmi->dev, "%s: unable to get"
Michael Bohande3942a2012-04-17 15:28:01 -0700933 " qcom,gpio-num property\n", __func__);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800934 goto err_probe;
935 }
Michael Bohan0ba63b82012-02-06 13:42:34 -0800936
937 q_spec = kzalloc(sizeof(struct qpnp_gpio_spec),
938 GFP_KERNEL);
939 if (!q_spec) {
940 dev_err(&spmi->dev, "%s: unable to allocate"
941 " memory\n",
942 __func__);
Michael Bohanfdcbed22012-04-23 17:44:27 -0700943 rc = -ENOMEM;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800944 goto err_probe;
945 }
946
947 q_spec->slave = spmi->sid;
948 q_spec->offset = res->start;
949 q_spec->gpio_chip_idx = i;
Michael Bohane25e15f2012-04-12 17:28:26 -0700950 q_spec->pmic_gpio = gpio;
Michael Bohande3942a2012-04-17 15:28:01 -0700951 q_spec->node = spmi->dev_node[i].of_node;
Michael Bohana19dced2012-04-24 13:14:50 -0700952 q_spec->q_chip = q_chip;
Michael Bohane25e15f2012-04-12 17:28:26 -0700953
954 rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
955 Q_REG_ADDR(q_spec, Q_REG_TYPE), &buf[0], 2);
956 if (rc) {
957 dev_err(&spmi->dev, "%s: unable to read type regs\n",
958 __func__);
Michael Bohane25e15f2012-04-12 17:28:26 -0700959 goto err_probe;
960 }
961 q_spec->type = buf[0];
962 q_spec->subtype = buf[1];
Michael Bohan0ba63b82012-02-06 13:42:34 -0800963
964 /* call into irq_domain to get irq mapping */
965 intspec[0] = q_chip->spmi->sid;
966 intspec[1] = (q_spec->offset >> 8) & 0xFF;
967 intspec[2] = 0;
968 q_spec->irq = irq_create_of_mapping(q_chip->int_ctrl,
969 intspec, 3);
970 if (!q_spec->irq) {
971 dev_err(&spmi->dev, "%s: invalid irq for gpio"
972 " %u\n", __func__, gpio);
Michael Bohanfdcbed22012-04-23 17:44:27 -0700973 rc = -EINVAL;
Michael Bohan0ba63b82012-02-06 13:42:34 -0800974 goto err_probe;
975 }
Michael Bohana19dced2012-04-24 13:14:50 -0700976 /* initialize lookup table params */
Michael Bohan0ba63b82012-02-06 13:42:34 -0800977 qpnp_pmic_gpio_set_spec(q_chip, gpio, q_spec);
978 qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
979 }
980
981 q_chip->gpio_chip.base = -1;
982 q_chip->gpio_chip.ngpio = spmi->num_dev_node;
983 q_chip->gpio_chip.label = "qpnp-gpio";
984 q_chip->gpio_chip.direction_input = qpnp_gpio_direction_input;
985 q_chip->gpio_chip.direction_output = qpnp_gpio_direction_output;
986 q_chip->gpio_chip.to_irq = qpnp_gpio_to_irq;
987 q_chip->gpio_chip.get = qpnp_gpio_get;
988 q_chip->gpio_chip.set = qpnp_gpio_set;
989 q_chip->gpio_chip.dev = &spmi->dev;
990 q_chip->gpio_chip.of_xlate = qpnp_gpio_of_gpio_xlate;
991 q_chip->gpio_chip.of_gpio_n_cells = 2;
992 q_chip->gpio_chip.can_sleep = 0;
993
994 rc = gpiochip_add(&q_chip->gpio_chip);
995 if (rc) {
996 dev_err(&spmi->dev, "%s: Can't add gpio chip, rc = %d\n",
997 __func__, rc);
Michael Bohan0ba63b82012-02-06 13:42:34 -0800998 goto err_probe;
999 }
1000
Michael Bohande3942a2012-04-17 15:28:01 -07001001 /* now configure gpio config defaults if they exist */
Michael Bohan0ba63b82012-02-06 13:42:34 -08001002 for (i = 0; i < spmi->num_dev_node; i++) {
1003 q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
Michael Bohanfdcbed22012-04-23 17:44:27 -07001004 if (WARN_ON(!q_spec)) {
1005 rc = -ENODEV;
1006 goto err_probe;
1007 }
Michael Bohan0ba63b82012-02-06 13:42:34 -08001008
Michael Bohande3942a2012-04-17 15:28:01 -07001009 rc = qpnp_gpio_cache_regs(q_chip, q_spec);
Michael Bohanfdcbed22012-04-23 17:44:27 -07001010 if (rc)
Michael Bohan0ba63b82012-02-06 13:42:34 -08001011 goto err_probe;
Michael Bohande3942a2012-04-17 15:28:01 -07001012
1013 rc = qpnp_gpio_apply_config(q_chip, q_spec);
Michael Bohanfdcbed22012-04-23 17:44:27 -07001014 if (rc)
Michael Bohande3942a2012-04-17 15:28:01 -07001015 goto err_probe;
Michael Bohan0ba63b82012-02-06 13:42:34 -08001016 }
1017
1018 dev_dbg(&spmi->dev, "%s: gpio_chip registered between %d-%u\n",
1019 __func__, q_chip->gpio_chip.base,
1020 (q_chip->gpio_chip.base + q_chip->gpio_chip.ngpio) - 1);
Michael Bohana19dced2012-04-24 13:14:50 -07001021
1022 rc = qpnp_gpio_debugfs_create(q_chip);
1023 if (rc) {
1024 dev_err(&spmi->dev, "%s: debugfs creation failed\n", __func__);
1025 goto err_probe;
1026 }
1027
Michael Bohan0ba63b82012-02-06 13:42:34 -08001028 return 0;
1029
1030err_probe:
1031 qpnp_gpio_free_chip(q_chip);
Michael Bohanfdcbed22012-04-23 17:44:27 -07001032 return rc;
Michael Bohan0ba63b82012-02-06 13:42:34 -08001033}
1034
1035static int qpnp_gpio_remove(struct spmi_device *spmi)
1036{
1037 struct qpnp_gpio_chip *q_chip = dev_get_drvdata(&spmi->dev);
1038
Michael Bohana19dced2012-04-24 13:14:50 -07001039 debugfs_remove_recursive(q_chip->dfs_dir);
1040
Michael Bohan0ba63b82012-02-06 13:42:34 -08001041 return qpnp_gpio_free_chip(q_chip);
1042}
1043
1044static struct of_device_id spmi_match_table[] = {
1045 { .compatible = "qcom,qpnp-gpio",
1046 },
1047 {}
1048};
1049
1050static const struct spmi_device_id qpnp_gpio_id[] = {
1051 { "qcom,qpnp-gpio", 0 },
1052 { }
1053};
1054MODULE_DEVICE_TABLE(spmi, qpnp_gpio_id);
1055
1056static struct spmi_driver qpnp_gpio_driver = {
1057 .driver = {
1058 .name = "qcom,qpnp-gpio",
1059 .of_match_table = spmi_match_table,
1060 },
1061 .probe = qpnp_gpio_probe,
1062 .remove = qpnp_gpio_remove,
1063 .id_table = qpnp_gpio_id,
1064};
1065
1066static int __init qpnp_gpio_init(void)
1067{
Michael Bohana19dced2012-04-24 13:14:50 -07001068#ifdef CONFIG_GPIO_QPNP_DEBUG
1069 driver_dfs_dir = debugfs_create_dir("qpnp_gpio", NULL);
1070 if (driver_dfs_dir == NULL)
1071 pr_err("Cannot register top level debugfs directory\n");
1072#endif
1073
Michael Bohan0ba63b82012-02-06 13:42:34 -08001074 return spmi_driver_register(&qpnp_gpio_driver);
1075}
1076
1077static void __exit qpnp_gpio_exit(void)
1078{
Michael Bohana19dced2012-04-24 13:14:50 -07001079#ifdef CONFIG_GPIO_QPNP_DEBUG
1080 debugfs_remove_recursive(driver_dfs_dir);
1081#endif
Michael Bohand247d152012-05-02 11:15:09 -07001082 spmi_driver_unregister(&qpnp_gpio_driver);
Michael Bohan0ba63b82012-02-06 13:42:34 -08001083}
1084
Michael Bohan0ba63b82012-02-06 13:42:34 -08001085MODULE_DESCRIPTION("QPNP PMIC gpio driver");
Michael Bohan7f0cc9d2012-04-16 17:16:09 -07001086MODULE_LICENSE("GPL v2");
Michael Bohan0ba63b82012-02-06 13:42:34 -08001087
1088module_init(qpnp_gpio_init);
1089module_exit(qpnp_gpio_exit);