File Index
Files and directories
Sign in
FILE

gpio-da9055.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpio-da9055.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * GPIO Driver for Dialog DA9055 PMICs.
  4 *
  5 * Copyright(c) 2012 Dialog Semiconductor Ltd.
  6 *
  7 * Author: David Dajun Chen <dchen@diasemi.com>
  8 */
  9#include <linux/module.h>
 10#include <linux/platform_device.h>
 11#include <linux/gpio/driver.h>
 12
 13#include <linux/mfd/da9055/core.h>
 14#include <linux/mfd/da9055/reg.h>
 15#include <linux/mfd/da9055/pdata.h>
 16
 17#define DA9055_VDD_IO			0x0
 18#define DA9055_PUSH_PULL		0x3
 19#define DA9055_ACT_LOW			0x0
 20#define DA9055_GPI			0x1
 21#define DA9055_PORT_MASK		0x3
 22#define DA9055_PORT_SHIFT(offset)	(4 * (offset % 2))
 23
 24#define DA9055_INPUT			DA9055_GPI
 25#define DA9055_OUTPUT			DA9055_PUSH_PULL
 26#define DA9055_IRQ_GPI0			3
 27
 28struct da9055_gpio {
 29	struct da9055 *da9055;
 30	struct gpio_chip gp;
 31};
 32
 33static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
 34{
 35	struct da9055_gpio *gpio = gpiochip_get_data(gc);
 36	int gpio_direction = 0;
 37	int ret;
 38
 39	/* Get GPIO direction */
 40	ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
 41	if (ret < 0)
 42		return ret;
 43
 44	gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
 45	gpio_direction >>= DA9055_PORT_SHIFT(offset);
 46	switch (gpio_direction) {
 47	case DA9055_INPUT:
 48		ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
 49		if (ret < 0)
 50			return ret;
 51		break;
 52	case DA9055_OUTPUT:
 53		ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
 54		if (ret < 0)
 55			return ret;
 56	}
 57
 58	return ret & (1 << offset);
 59
 60}
 61
 62static int da9055_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
 63{
 64	struct da9055_gpio *gpio = gpiochip_get_data(gc);
 65
 66	return da9055_reg_update(gpio->da9055, DA9055_REG_GPIO_MODE0_2,
 67				 1 << offset, value << offset);
 68}
 69
 70static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
 71{
 72	struct da9055_gpio *gpio = gpiochip_get_data(gc);
 73	unsigned char reg_byte;
 74
 75	reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
 76				<< DA9055_PORT_SHIFT(offset);
 77
 78	return da9055_reg_update(gpio->da9055, (offset >> 1) +
 79				DA9055_REG_GPIO0_1,
 80				DA9055_PORT_MASK <<
 81				DA9055_PORT_SHIFT(offset),
 82				reg_byte);
 83}
 84
 85static int da9055_gpio_direction_output(struct gpio_chip *gc,
 86					unsigned offset, int value)
 87{
 88	struct da9055_gpio *gpio = gpiochip_get_data(gc);
 89	unsigned char reg_byte;
 90	int ret;
 91
 92	reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
 93					<< DA9055_PORT_SHIFT(offset);
 94
 95	ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
 96				DA9055_REG_GPIO0_1,
 97				DA9055_PORT_MASK <<
 98				DA9055_PORT_SHIFT(offset),
 99				reg_byte);
100	if (ret < 0)
101		return ret;
102
103	return da9055_gpio_set(gc, offset, value);
104}
105
106static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
107{
108	struct da9055_gpio *gpio = gpiochip_get_data(gc);
109	struct da9055 *da9055 = gpio->da9055;
110
111	return regmap_irq_get_virq(da9055->irq_data,
112				  DA9055_IRQ_GPI0 + offset);
113}
114
115static const struct gpio_chip reference_gp = {
116	.label = "da9055-gpio",
117	.owner = THIS_MODULE,
118	.get = da9055_gpio_get,
119	.set = da9055_gpio_set,
120	.direction_input = da9055_gpio_direction_input,
121	.direction_output = da9055_gpio_direction_output,
122	.to_irq = da9055_gpio_to_irq,
123	.can_sleep = true,
124	.ngpio = 3,
125	.base = -1,
126};
127
128static int da9055_gpio_probe(struct platform_device *pdev)
129{
130	struct da9055_gpio *gpio;
131	struct da9055_pdata *pdata;
132
133	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
134	if (!gpio)
135		return -ENOMEM;
136
137	gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
138	pdata = dev_get_platdata(gpio->da9055->dev);
139
140	gpio->gp = reference_gp;
141	if (pdata && pdata->gpio_base)
142		gpio->gp.base = pdata->gpio_base;
143
144	return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
145}
146
147static struct platform_driver da9055_gpio_driver = {
148	.probe = da9055_gpio_probe,
149	.driver = {
150		.name	= "da9055-gpio",
151	},
152};
153
154static int __init da9055_gpio_init(void)
155{
156	return platform_driver_register(&da9055_gpio_driver);
157}
158subsys_initcall(da9055_gpio_init);
159
160static void __exit da9055_gpio_exit(void)
161{
162	platform_driver_unregister(&da9055_gpio_driver);
163}
164module_exit(da9055_gpio_exit);
165
166MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
167MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
168MODULE_LICENSE("GPL");
169MODULE_ALIAS("platform:da9055-gpio");
~/ Read-only file preview.