xref: /OK3568_Linux_fs/kernel/drivers/gpio/gpio-bd9571mwv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * ROHM BD9571MWV-M GPIO driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
7*4882a593Smuzhiyun  * modify it under the terms of the GNU General Public License version 2 as
8*4882a593Smuzhiyun  * published by the Free Software Foundation.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11*4882a593Smuzhiyun  * kind, whether expressed or implied; without even the implied warranty
12*4882a593Smuzhiyun  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*4882a593Smuzhiyun  * GNU General Public License version 2 for more details.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * Based on the TPS65086 driver
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * NOTE: Interrupts are not supported yet.
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <linux/gpio/driver.h>
21*4882a593Smuzhiyun #include <linux/module.h>
22*4882a593Smuzhiyun #include <linux/platform_device.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <linux/mfd/bd9571mwv.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun struct bd9571mwv_gpio {
27*4882a593Smuzhiyun 	struct gpio_chip chip;
28*4882a593Smuzhiyun 	struct bd9571mwv *bd;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun 
bd9571mwv_gpio_get_direction(struct gpio_chip * chip,unsigned int offset)31*4882a593Smuzhiyun static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip,
32*4882a593Smuzhiyun 				       unsigned int offset)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
35*4882a593Smuzhiyun 	int ret, val;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val);
38*4882a593Smuzhiyun 	if (ret < 0)
39*4882a593Smuzhiyun 		return ret;
40*4882a593Smuzhiyun 	if (val & BIT(offset))
41*4882a593Smuzhiyun 		return GPIO_LINE_DIRECTION_IN;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	return GPIO_LINE_DIRECTION_OUT;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
bd9571mwv_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)46*4882a593Smuzhiyun static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip,
47*4882a593Smuzhiyun 					 unsigned int offset)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR,
52*4882a593Smuzhiyun 			   BIT(offset), 0);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	return 0;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
bd9571mwv_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)57*4882a593Smuzhiyun static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip,
58*4882a593Smuzhiyun 					  unsigned int offset, int value)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	/* Set the initial value */
63*4882a593Smuzhiyun 	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT,
64*4882a593Smuzhiyun 			   BIT(offset), value ? BIT(offset) : 0);
65*4882a593Smuzhiyun 	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR,
66*4882a593Smuzhiyun 			   BIT(offset), BIT(offset));
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
bd9571mwv_gpio_get(struct gpio_chip * chip,unsigned int offset)71*4882a593Smuzhiyun static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
74*4882a593Smuzhiyun 	int ret, val;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val);
77*4882a593Smuzhiyun 	if (ret < 0)
78*4882a593Smuzhiyun 		return ret;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return val & BIT(offset);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
bd9571mwv_gpio_set(struct gpio_chip * chip,unsigned int offset,int value)83*4882a593Smuzhiyun static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset,
84*4882a593Smuzhiyun 			      int value)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT,
89*4882a593Smuzhiyun 			   BIT(offset), value ? BIT(offset) : 0);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static const struct gpio_chip template_chip = {
93*4882a593Smuzhiyun 	.label			= "bd9571mwv-gpio",
94*4882a593Smuzhiyun 	.owner			= THIS_MODULE,
95*4882a593Smuzhiyun 	.get_direction		= bd9571mwv_gpio_get_direction,
96*4882a593Smuzhiyun 	.direction_input	= bd9571mwv_gpio_direction_input,
97*4882a593Smuzhiyun 	.direction_output	= bd9571mwv_gpio_direction_output,
98*4882a593Smuzhiyun 	.get			= bd9571mwv_gpio_get,
99*4882a593Smuzhiyun 	.set			= bd9571mwv_gpio_set,
100*4882a593Smuzhiyun 	.base			= -1,
101*4882a593Smuzhiyun 	.ngpio			= 2,
102*4882a593Smuzhiyun 	.can_sleep		= true,
103*4882a593Smuzhiyun };
104*4882a593Smuzhiyun 
bd9571mwv_gpio_probe(struct platform_device * pdev)105*4882a593Smuzhiyun static int bd9571mwv_gpio_probe(struct platform_device *pdev)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	struct bd9571mwv_gpio *gpio;
108*4882a593Smuzhiyun 	int ret;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
111*4882a593Smuzhiyun 	if (!gpio)
112*4882a593Smuzhiyun 		return -ENOMEM;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	platform_set_drvdata(pdev, gpio);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	gpio->bd = dev_get_drvdata(pdev->dev.parent);
117*4882a593Smuzhiyun 	gpio->chip = template_chip;
118*4882a593Smuzhiyun 	gpio->chip.parent = gpio->bd->dev;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
121*4882a593Smuzhiyun 	if (ret < 0) {
122*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
123*4882a593Smuzhiyun 		return ret;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	return 0;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun static const struct platform_device_id bd9571mwv_gpio_id_table[] = {
130*4882a593Smuzhiyun 	{ "bd9571mwv-gpio", },
131*4882a593Smuzhiyun 	{ /* sentinel */ }
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static struct platform_driver bd9571mwv_gpio_driver = {
136*4882a593Smuzhiyun 	.driver = {
137*4882a593Smuzhiyun 		.name = "bd9571mwv-gpio",
138*4882a593Smuzhiyun 	},
139*4882a593Smuzhiyun 	.probe = bd9571mwv_gpio_probe,
140*4882a593Smuzhiyun 	.id_table = bd9571mwv_gpio_id_table,
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun module_platform_driver(bd9571mwv_gpio_driver);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
145*4882a593Smuzhiyun MODULE_DESCRIPTION("BD9571MWV GPIO driver");
146*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
147