brintos

brintos / linux-shallow public Read only

0
0
Text · 5.2 KiB · 28dba70 Raw
200 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI Palma series PMIC's GPIO driver.4 *5 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.6 *7 * Author: Laxman Dewangan <ldewangan@nvidia.com>8 */9 10#include <linux/gpio/driver.h>11#include <linux/kernel.h>12#include <linux/init.h>13#include <linux/mfd/palmas.h>14#include <linux/of.h>15#include <linux/platform_device.h>16 17struct palmas_gpio {18	struct gpio_chip gpio_chip;19	struct palmas *palmas;20};21 22struct palmas_device_data {23	int ngpio;24};25 26static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)27{28	struct palmas_gpio *pg = gpiochip_get_data(gc);29	struct palmas *palmas = pg->palmas;30	unsigned int val;31	int ret;32	unsigned int reg;33	int gpio16 = (offset/8);34 35	offset %= 8;36	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;37 38	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);39	if (ret < 0) {40		dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);41		return ret;42	}43 44	if (val & BIT(offset))45		reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;46	else47		reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;48 49	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);50	if (ret < 0) {51		dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);52		return ret;53	}54	return !!(val & BIT(offset));55}56 57static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,58			int value)59{60	struct palmas_gpio *pg = gpiochip_get_data(gc);61	struct palmas *palmas = pg->palmas;62	int ret;63	unsigned int reg;64	int gpio16 = (offset/8);65 66	offset %= 8;67	if (gpio16)68		reg = (value) ?69			PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;70	else71		reg = (value) ?72			PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;73 74	ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));75	if (ret < 0)76		dev_err(gc->parent, "Reg 0x%02x write failed, %d\n", reg, ret);77}78 79static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,80				int value)81{82	struct palmas_gpio *pg = gpiochip_get_data(gc);83	struct palmas *palmas = pg->palmas;84	int ret;85	unsigned int reg;86	int gpio16 = (offset/8);87 88	offset %= 8;89	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;90 91	/* Set the initial value */92	palmas_gpio_set(gc, offset, value);93 94	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,95				BIT(offset), BIT(offset));96	if (ret < 0)97		dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,98			ret);99	return ret;100}101 102static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)103{104	struct palmas_gpio *pg = gpiochip_get_data(gc);105	struct palmas *palmas = pg->palmas;106	int ret;107	unsigned int reg;108	int gpio16 = (offset/8);109 110	offset %= 8;111	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;112 113	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);114	if (ret < 0)115		dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,116			ret);117	return ret;118}119 120static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)121{122	struct palmas_gpio *pg = gpiochip_get_data(gc);123	struct palmas *palmas = pg->palmas;124 125	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);126}127 128static const struct palmas_device_data palmas_dev_data = {129	.ngpio = 8,130};131 132static const struct palmas_device_data tps80036_dev_data = {133	.ngpio = 16,134};135 136static const struct of_device_id of_palmas_gpio_match[] = {137	{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},138	{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},139	{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},140	{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},141	{ },142};143 144static int palmas_gpio_probe(struct platform_device *pdev)145{146	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);147	struct palmas_platform_data *palmas_pdata;148	struct palmas_gpio *palmas_gpio;149	int ret;150	const struct palmas_device_data *dev_data;151 152	dev_data = of_device_get_match_data(&pdev->dev);153	if (!dev_data)154		dev_data = &palmas_dev_data;155 156	palmas_gpio = devm_kzalloc(&pdev->dev,157				sizeof(*palmas_gpio), GFP_KERNEL);158	if (!palmas_gpio)159		return -ENOMEM;160 161	palmas_gpio->palmas = palmas;162	palmas_gpio->gpio_chip.owner = THIS_MODULE;163	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);164	palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;165	palmas_gpio->gpio_chip.can_sleep = true;166	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;167	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;168	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;169	palmas_gpio->gpio_chip.set	= palmas_gpio_set;170	palmas_gpio->gpio_chip.get	= palmas_gpio_get;171	palmas_gpio->gpio_chip.parent = &pdev->dev;172 173	palmas_pdata = dev_get_platdata(palmas->dev);174	if (palmas_pdata && palmas_pdata->gpio_base)175		palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base;176	else177		palmas_gpio->gpio_chip.base = -1;178 179	ret = devm_gpiochip_add_data(&pdev->dev, &palmas_gpio->gpio_chip,180				     palmas_gpio);181	if (ret < 0) {182		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);183		return ret;184	}185 186	return ret;187}188 189static struct platform_driver palmas_gpio_driver = {190	.driver.name	= "palmas-gpio",191	.driver.of_match_table = of_palmas_gpio_match,192	.probe		= palmas_gpio_probe,193};194 195static int __init palmas_gpio_init(void)196{197	return platform_driver_register(&palmas_gpio_driver);198}199subsys_initcall(palmas_gpio_init);200