1187767Sluigi// SPDX-License-Identifier: GPL-2.0-or-later
2187767Sluigi/*
3187767Sluigi * RDC321x GPIO driver
4187767Sluigi *
5187767Sluigi * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
6187767Sluigi * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
7187767Sluigi */
8187767Sluigi#include <linux/module.h>
9187767Sluigi#include <linux/kernel.h>
10187767Sluigi#include <linux/init.h>
11187767Sluigi#include <linux/spinlock.h>
12187767Sluigi#include <linux/platform_device.h>
13187767Sluigi#include <linux/pci.h>
14187767Sluigi#include <linux/gpio/driver.h>
15187767Sluigi#include <linux/mfd/rdc321x.h>
16187767Sluigi#include <linux/slab.h>
17187767Sluigi
18187767Sluigistruct rdc321x_gpio {
19187767Sluigi	spinlock_t		lock;
20187767Sluigi	struct pci_dev		*sb_pdev;
21187767Sluigi	u32			data_reg[2];
22187767Sluigi	int			reg1_ctrl_base;
23187767Sluigi	int			reg1_data_base;
24187767Sluigi	int			reg2_ctrl_base;
25187767Sluigi	int			reg2_data_base;
26187767Sluigi	struct gpio_chip	chip;
27187767Sluigi};
28187767Sluigi
29187767Sluigi/* read GPIO pin */
30187767Sluigistatic int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
31187767Sluigi{
32187767Sluigi	struct rdc321x_gpio *gpch;
33187767Sluigi	u32 value = 0;
34187767Sluigi	int reg;
35187767Sluigi
36187767Sluigi	gpch = gpiochip_get_data(chip);
37187767Sluigi	reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
38204591Sluigi
39187767Sluigi	spin_lock(&gpch->lock);
40187767Sluigi	pci_write_config_dword(gpch->sb_pdev, reg,
41187767Sluigi					gpch->data_reg[gpio < 32 ? 0 : 1]);
42187767Sluigi	pci_read_config_dword(gpch->sb_pdev, reg, &value);
43187767Sluigi	spin_unlock(&gpch->lock);
44187767Sluigi
45187767Sluigi	return (1 << (gpio & 0x1f)) & value ? 1 : 0;
46187767Sluigi}
47187767Sluigi
48187767Sluigistatic void rdc_gpio_set_value_impl(struct gpio_chip *chip,
49346205Sae				unsigned gpio, int value)
50346205Sae{
51187767Sluigi	struct rdc321x_gpio *gpch;
52187767Sluigi	int reg = (gpio < 32) ? 0 : 1;
53187767Sluigi
54187767Sluigi	gpch = gpiochip_get_data(chip);
55187767Sluigi
56187767Sluigi	if (value)
57187767Sluigi		gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
58187767Sluigi	else
59332400Sae		gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
60332400Sae
61332400Sae	pci_write_config_dword(gpch->sb_pdev,
62332400Sae			reg ? gpch->reg2_data_base : gpch->reg1_data_base,
63332400Sae			gpch->data_reg[reg]);
64332400Sae}
65187767Sluigi
66187767Sluigi/* set GPIO pin to value */
67187767Sluigistatic void rdc_gpio_set_value(struct gpio_chip *chip,
68187767Sluigi				unsigned gpio, int value)
69187767Sluigi{
70187767Sluigi	struct rdc321x_gpio *gpch;
71187767Sluigi
72187767Sluigi	gpch = gpiochip_get_data(chip);
73187767Sluigi	spin_lock(&gpch->lock);
74187767Sluigi	rdc_gpio_set_value_impl(chip, gpio, value);
75187767Sluigi	spin_unlock(&gpch->lock);
76187767Sluigi}
77187767Sluigi
78187767Sluigistatic int rdc_gpio_config(struct gpio_chip *chip,
79187767Sluigi				unsigned gpio, int value)
80270424Smelifaro{
81270424Smelifaro	struct rdc321x_gpio *gpch;
82187769Sluigi	int err;
83187769Sluigi	u32 reg;
84187769Sluigi
85187769Sluigi	gpch = gpiochip_get_data(chip);
86187769Sluigi
87187769Sluigi	spin_lock(&gpch->lock);
88187769Sluigi	err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
89187769Sluigi			gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
90332229Stuexen	if (err)
91332229Stuexen		goto unlock;
92187769Sluigi
93187769Sluigi	reg |= 1 << (gpio & 0x1f);
94298016Sae
95187769Sluigi	err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
96204591Sluigi			gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
97187769Sluigi	if (err)
98204591Sluigi		goto unlock;
99204591Sluigi
100187769Sluigi	rdc_gpio_set_value_impl(chip, gpio, value);
101187769Sluigi
102187769Sluigiunlock:
103187769Sluigi	spin_unlock(&gpch->lock);
104187769Sluigi
105187769Sluigi	return err;
106187769Sluigi}
107187769Sluigi
108187769Sluigi/* configure GPIO pin as input */
109187769Sluigistatic int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
110187769Sluigi{
111187769Sluigi	return rdc_gpio_config(chip, gpio, 1);
112190633Spiso}
113223666Sae
114223666Sae/*
115187769Sluigi * Cache the initial value of both GPIO data registers
116187769Sluigi */
117187769Sluigistatic int rdc321x_gpio_probe(struct platform_device *pdev)
118187769Sluigi{
119187769Sluigi	int err;
120187769Sluigi	struct resource *r;
121187769Sluigi	struct rdc321x_gpio *rdc321x_gpio_dev;
122187769Sluigi	struct rdc321x_gpio_pdata *pdata;
123187769Sluigi
124187769Sluigi	pdata = dev_get_platdata(&pdev->dev);
125187769Sluigi	if (!pdata) {
126187769Sluigi		dev_err(&pdev->dev, "no platform data supplied\n");
127337461Sae		return -ENODEV;
128187769Sluigi	}
129337461Sae
130187769Sluigi	rdc321x_gpio_dev = devm_kzalloc(&pdev->dev, sizeof(struct rdc321x_gpio),
131187769Sluigi					GFP_KERNEL);
132187769Sluigi	if (!rdc321x_gpio_dev)
133187769Sluigi		return -ENOMEM;
134187769Sluigi
135187769Sluigi	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
136187769Sluigi	if (!r) {
137187769Sluigi		dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
138187769Sluigi		return -ENODEV;
139187769Sluigi	}
140187769Sluigi
141187769Sluigi	spin_lock_init(&rdc321x_gpio_dev->lock);
142187769Sluigi	rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
143205169Sluigi	rdc321x_gpio_dev->reg1_ctrl_base = r->start;
144187769Sluigi	rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
145187769Sluigi
146187769Sluigi	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
147187769Sluigi	if (!r) {
148187769Sluigi		dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
149187769Sluigi		return -ENODEV;
150187769Sluigi	}
151187769Sluigi
152187769Sluigi	rdc321x_gpio_dev->reg2_ctrl_base = r->start;
153187769Sluigi	rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
154349573Sae
155187769Sluigi	rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
156187769Sluigi	rdc321x_gpio_dev->chip.owner = THIS_MODULE;
157187769Sluigi	rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
158187769Sluigi	rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
159187769Sluigi	rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
160187769Sluigi	rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
161187769Sluigi	rdc321x_gpio_dev->chip.base = 0;
162187769Sluigi	rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
163187769Sluigi
164187769Sluigi	platform_set_drvdata(pdev, rdc321x_gpio_dev);
165187769Sluigi
166187769Sluigi	/* This might not be, what others (BIOS, bootloader, etc.)
167187769Sluigi	   wrote to these registers before, but it's a good guess. Still
168187769Sluigi	   better than just using 0xffffffff. */
169187769Sluigi	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
170187769Sluigi					rdc321x_gpio_dev->reg1_data_base,
171187769Sluigi					&rdc321x_gpio_dev->data_reg[0]);
172187769Sluigi	if (err)
173187769Sluigi		return err;
174204591Sluigi
175204591Sluigi	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
176187769Sluigi					rdc321x_gpio_dev->reg2_data_base,
177187769Sluigi					&rdc321x_gpio_dev->data_reg[1]);
178204591Sluigi	if (err)
179194930Soleg		return err;
180187769Sluigi
181187769Sluigi	dev_info(&pdev->dev, "registering %d GPIOs\n",
182266941Shiren					rdc321x_gpio_dev->chip.ngpio);
183187769Sluigi	return devm_gpiochip_add_data(&pdev->dev, &rdc321x_gpio_dev->chip,
184187769Sluigi				      rdc321x_gpio_dev);
185300779Struckman}
186300779Struckman
187300779Struckmanstatic struct platform_driver rdc321x_gpio_driver = {
188300779Struckman	.driver.name	= "rdc321x-gpio",
189300779Struckman	.probe		= rdc321x_gpio_probe,
190300779Struckman};
191300779Struckman
192300779Struckmanmodule_platform_driver(rdc321x_gpio_driver);
193300779Struckman
194300779StruckmanMODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
195300779StruckmanMODULE_DESCRIPTION("RDC321x GPIO driver");
196300779StruckmanMODULE_LICENSE("GPL");
197300779StruckmanMODULE_ALIAS("platform:rdc321x-gpio");
198300779Struckman