2 * MAXIM MAX77620 GPIO driver
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
11 #include <linux/gpio/driver.h>
12 #include <linux/interrupt.h>
13 #include <linux/mfd/max77620.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
18 #define GPIO_REG_ADDR(offset) (MAX77620_REG_GPIO0 + offset)
20 struct max77620_gpio
{
21 struct gpio_chip gpio_chip
;
29 static const struct regmap_irq max77620_gpio_irqs
[] = {
30 REGMAP_IRQ_REG(0, 0, MAX77620_IRQ_LVL2_GPIO_EDGE0
),
31 REGMAP_IRQ_REG(1, 0, MAX77620_IRQ_LVL2_GPIO_EDGE1
),
32 REGMAP_IRQ_REG(2, 0, MAX77620_IRQ_LVL2_GPIO_EDGE2
),
33 REGMAP_IRQ_REG(3, 0, MAX77620_IRQ_LVL2_GPIO_EDGE3
),
34 REGMAP_IRQ_REG(4, 0, MAX77620_IRQ_LVL2_GPIO_EDGE4
),
35 REGMAP_IRQ_REG(5, 0, MAX77620_IRQ_LVL2_GPIO_EDGE5
),
36 REGMAP_IRQ_REG(6, 0, MAX77620_IRQ_LVL2_GPIO_EDGE6
),
37 REGMAP_IRQ_REG(7, 0, MAX77620_IRQ_LVL2_GPIO_EDGE7
),
40 static struct regmap_irq_chip max77620_gpio_irq_chip
= {
41 .name
= "max77620-gpio",
42 .irqs
= max77620_gpio_irqs
,
43 .num_irqs
= ARRAY_SIZE(max77620_gpio_irqs
),
46 .status_base
= MAX77620_REG_IRQ_LVL2_GPIO
,
49 static int max77620_gpio_dir_input(struct gpio_chip
*gc
, unsigned int offset
)
51 struct max77620_gpio
*mgpio
= gpiochip_get_data(gc
);
54 ret
= regmap_update_bits(mgpio
->rmap
, GPIO_REG_ADDR(offset
),
55 MAX77620_CNFG_GPIO_DIR_MASK
,
56 MAX77620_CNFG_GPIO_DIR_INPUT
);
58 dev_err(mgpio
->dev
, "CNFG_GPIOx dir update failed: %d\n", ret
);
63 static int max77620_gpio_get(struct gpio_chip
*gc
, unsigned int offset
)
65 struct max77620_gpio
*mgpio
= gpiochip_get_data(gc
);
69 ret
= regmap_read(mgpio
->rmap
, GPIO_REG_ADDR(offset
), &val
);
71 dev_err(mgpio
->dev
, "CNFG_GPIOx read failed: %d\n", ret
);
75 return !!(val
& MAX77620_CNFG_GPIO_INPUT_VAL_MASK
);
78 static int max77620_gpio_dir_output(struct gpio_chip
*gc
, unsigned int offset
,
81 struct max77620_gpio
*mgpio
= gpiochip_get_data(gc
);
85 val
= (value
) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH
:
86 MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW
;
88 ret
= regmap_update_bits(mgpio
->rmap
, GPIO_REG_ADDR(offset
),
89 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK
, val
);
91 dev_err(mgpio
->dev
, "CNFG_GPIOx val update failed: %d\n", ret
);
95 ret
= regmap_update_bits(mgpio
->rmap
, GPIO_REG_ADDR(offset
),
96 MAX77620_CNFG_GPIO_DIR_MASK
,
97 MAX77620_CNFG_GPIO_DIR_OUTPUT
);
99 dev_err(mgpio
->dev
, "CNFG_GPIOx dir update failed: %d\n", ret
);
104 static int max77620_gpio_set_debounce(struct gpio_chip
*gc
,
106 unsigned int debounce
)
108 struct max77620_gpio
*mgpio
= gpiochip_get_data(gc
);
114 val
= MAX77620_CNFG_GPIO_DBNC_None
;
117 val
= MAX77620_CNFG_GPIO_DBNC_8ms
;
120 val
= MAX77620_CNFG_GPIO_DBNC_16ms
;
123 val
= MAX77620_CNFG_GPIO_DBNC_32ms
;
126 dev_err(mgpio
->dev
, "Illegal value %u\n", debounce
);
130 ret
= regmap_update_bits(mgpio
->rmap
, GPIO_REG_ADDR(offset
),
131 MAX77620_CNFG_GPIO_DBNC_MASK
, val
);
133 dev_err(mgpio
->dev
, "CNFG_GPIOx_DBNC update failed: %d\n", ret
);
138 static void max77620_gpio_set(struct gpio_chip
*gc
, unsigned int offset
,
141 struct max77620_gpio
*mgpio
= gpiochip_get_data(gc
);
145 val
= (value
) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH
:
146 MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW
;
148 ret
= regmap_update_bits(mgpio
->rmap
, GPIO_REG_ADDR(offset
),
149 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK
, val
);
151 dev_err(mgpio
->dev
, "CNFG_GPIO_OUT update failed: %d\n", ret
);
154 static int max77620_gpio_to_irq(struct gpio_chip
*gc
, unsigned int offset
)
156 struct max77620_gpio
*mgpio
= gpiochip_get_data(gc
);
157 struct max77620_chip
*chip
= dev_get_drvdata(mgpio
->dev
->parent
);
159 return regmap_irq_get_virq(chip
->gpio_irq_data
, offset
);
162 static int max77620_gpio_probe(struct platform_device
*pdev
)
164 struct max77620_chip
*chip
= dev_get_drvdata(pdev
->dev
.parent
);
165 struct max77620_gpio
*mgpio
;
169 gpio_irq
= platform_get_irq(pdev
, 0);
171 dev_err(&pdev
->dev
, "GPIO irq not available %d\n", gpio_irq
);
175 mgpio
= devm_kzalloc(&pdev
->dev
, sizeof(*mgpio
), GFP_KERNEL
);
179 mgpio
->rmap
= chip
->rmap
;
180 mgpio
->dev
= &pdev
->dev
;
181 mgpio
->gpio_irq
= gpio_irq
;
183 mgpio
->gpio_chip
.label
= pdev
->name
;
184 mgpio
->gpio_chip
.parent
= &pdev
->dev
;
185 mgpio
->gpio_chip
.direction_input
= max77620_gpio_dir_input
;
186 mgpio
->gpio_chip
.get
= max77620_gpio_get
;
187 mgpio
->gpio_chip
.direction_output
= max77620_gpio_dir_output
;
188 mgpio
->gpio_chip
.set_debounce
= max77620_gpio_set_debounce
;
189 mgpio
->gpio_chip
.set
= max77620_gpio_set
;
190 mgpio
->gpio_chip
.to_irq
= max77620_gpio_to_irq
;
191 mgpio
->gpio_chip
.ngpio
= MAX77620_GPIO_NR
;
192 mgpio
->gpio_chip
.can_sleep
= 1;
193 mgpio
->gpio_chip
.base
= -1;
194 mgpio
->irq_base
= -1;
195 #ifdef CONFIG_OF_GPIO
196 mgpio
->gpio_chip
.of_node
= pdev
->dev
.parent
->of_node
;
199 platform_set_drvdata(pdev
, mgpio
);
201 ret
= devm_gpiochip_add_data(&pdev
->dev
, &mgpio
->gpio_chip
, mgpio
);
203 dev_err(&pdev
->dev
, "gpio_init: Failed to add max77620_gpio\n");
207 mgpio
->gpio_base
= mgpio
->gpio_chip
.base
;
208 ret
= devm_regmap_add_irq_chip(&pdev
->dev
, chip
->rmap
, mgpio
->gpio_irq
,
209 IRQF_ONESHOT
, mgpio
->irq_base
,
210 &max77620_gpio_irq_chip
,
211 &chip
->gpio_irq_data
);
213 dev_err(&pdev
->dev
, "Failed to add gpio irq_chip %d\n", ret
);
220 static const struct platform_device_id max77620_gpio_devtype
[] = {
221 { .name
= "max77620-gpio", },
224 MODULE_DEVICE_TABLE(platform
, max77620_gpio_devtype
);
226 static struct platform_driver max77620_gpio_driver
= {
227 .driver
.name
= "max77620-gpio",
228 .probe
= max77620_gpio_probe
,
229 .id_table
= max77620_gpio_devtype
,
232 module_platform_driver(max77620_gpio_driver
);
234 MODULE_DESCRIPTION("GPIO interface for MAX77620 and MAX20024 PMIC");
235 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
236 MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
237 MODULE_ALIAS("platform:max77620-gpio");
238 MODULE_LICENSE("GPL v2");