1124144Sphk// SPDX-License-Identifier: GPL-2.0+
2124144Sphk/*
3124144Sphk * gpiolib support for Wolfson WM8994
4124144Sphk *
5139788Simp * Copyright 2009 Wolfson Microelectronics PLC.
6139788Simp *
7139788Simp * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8139788Simp *
9139788Simp */
10139788Simp
11139788Simp#include <linux/cleanup.h>
12139788Simp#include <linux/kernel.h>
13124144Sphk#include <linux/slab.h>
14139788Simp#include <linux/module.h>
15139788Simp#include <linux/gpio/driver.h>
16139788Simp#include <linux/mfd/core.h>
17139788Simp#include <linux/platform_device.h>
18139788Simp#include <linux/seq_file.h>
19139788Simp#include <linux/regmap.h>
20139788Simp
21139788Simp#include <linux/mfd/wm8994/core.h>
22139788Simp#include <linux/mfd/wm8994/pdata.h>
23139788Simp#include <linux/mfd/wm8994/gpio.h>
24139788Simp#include <linux/mfd/wm8994/registers.h>
25139788Simp
26139788Simpstruct wm8994_gpio {
27139788Simp	struct wm8994 *wm8994;
28124144Sphk	struct gpio_chip gpio_chip;
29124144Sphk};
30124144Sphk
31124144Sphkstatic int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
32124144Sphk{
33124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
34124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
35124144Sphk
36124144Sphk	switch (wm8994->type) {
37124144Sphk	case WM8958:
38124144Sphk		switch (offset) {
39124144Sphk		case 1:
40124144Sphk		case 2:
41124144Sphk		case 3:
42124144Sphk		case 4:
43124144Sphk		case 6:
44124144Sphk			return -EINVAL;
45124144Sphk		}
46124144Sphk		break;
47124144Sphk	default:
48124144Sphk		break;
49124144Sphk	}
50124144Sphk
51124144Sphk	return 0;
52124144Sphk}
53124144Sphk
54124144Sphkstatic int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
55124144Sphk{
56124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
57124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
58124144Sphk
59124144Sphk	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
60124144Sphk			       WM8994_GPN_DIR, WM8994_GPN_DIR);
61124144Sphk}
62124144Sphk
63124144Sphkstatic int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
64124144Sphk{
65124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
66124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
67124144Sphk	int ret;
68124144Sphk
69124144Sphk	ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
70124144Sphk	if (ret < 0)
71124144Sphk		return ret;
72124144Sphk
73124144Sphk	if (ret & WM8994_GPN_LVL)
74124144Sphk		return 1;
75124144Sphk	else
76124144Sphk		return 0;
77124144Sphk}
78124144Sphk
79124144Sphkstatic int wm8994_gpio_direction_out(struct gpio_chip *chip,
80124144Sphk				     unsigned offset, int value)
81124144Sphk{
82124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
83124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
84124144Sphk
85124144Sphk	if (value)
86124144Sphk		value = WM8994_GPN_LVL;
87124144Sphk
88124144Sphk	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
89124144Sphk			       WM8994_GPN_DIR | WM8994_GPN_LVL, value);
90124144Sphk}
91124144Sphk
92124144Sphkstatic void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
93124144Sphk{
94124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
95124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
96124144Sphk
97124144Sphk	if (value)
98124144Sphk		value = WM8994_GPN_LVL;
99124144Sphk
100124144Sphk	wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
101124144Sphk}
102124144Sphk
103124144Sphkstatic int wm8994_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
104124144Sphk				  unsigned long config)
105124144Sphk{
106124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
107124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
108124144Sphk
109124144Sphk	switch (pinconf_to_config_param(config)) {
110124144Sphk	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
111124144Sphk		return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
112124144Sphk				       WM8994_GPN_OP_CFG_MASK,
113124144Sphk				       WM8994_GPN_OP_CFG);
114124144Sphk	case PIN_CONFIG_DRIVE_PUSH_PULL:
115124144Sphk		return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
116124144Sphk				       WM8994_GPN_OP_CFG_MASK, 0);
117124144Sphk	default:
118124144Sphk		break;
119124144Sphk	}
120124144Sphk
121124144Sphk	return -ENOTSUPP;
122124144Sphk}
123124144Sphk
124124144Sphkstatic int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
125124144Sphk{
126124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
127124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
128124144Sphk
129124144Sphk	return regmap_irq_get_virq(wm8994->irq_data, offset);
130124144Sphk}
131124144Sphk
132124144Sphk
133124144Sphk#ifdef CONFIG_DEBUG_FS
134124144Sphkstatic const char *wm8994_gpio_fn(u16 fn)
135124144Sphk{
136124144Sphk	switch (fn) {
137124144Sphk	case WM8994_GP_FN_PIN_SPECIFIC:
138124144Sphk		return "pin-specific";
139124144Sphk	case WM8994_GP_FN_GPIO:
140124144Sphk		return "GPIO";
141124144Sphk	case WM8994_GP_FN_SDOUT:
142124144Sphk		return "SDOUT";
143124144Sphk	case WM8994_GP_FN_IRQ:
144124144Sphk		return "IRQ";
145124144Sphk	case WM8994_GP_FN_TEMPERATURE:
146124144Sphk		return "Temperature";
147124144Sphk	case WM8994_GP_FN_MICBIAS1_DET:
148124144Sphk		return "MICBIAS1 detect";
149124144Sphk	case WM8994_GP_FN_MICBIAS1_SHORT:
150124144Sphk		return "MICBIAS1 short";
151124144Sphk	case WM8994_GP_FN_MICBIAS2_DET:
152124144Sphk		return "MICBIAS2 detect";
153124144Sphk	case WM8994_GP_FN_MICBIAS2_SHORT:
154124144Sphk		return "MICBIAS2 short";
155124144Sphk	case WM8994_GP_FN_FLL1_LOCK:
156124144Sphk		return "FLL1 lock";
157124144Sphk	case WM8994_GP_FN_FLL2_LOCK:
158124144Sphk		return "FLL2 lock";
159124144Sphk	case WM8994_GP_FN_SRC1_LOCK:
160124144Sphk		return "SRC1 lock";
161124144Sphk	case WM8994_GP_FN_SRC2_LOCK:
162124144Sphk		return "SRC2 lock";
163124144Sphk	case WM8994_GP_FN_DRC1_ACT:
164124144Sphk		return "DRC1 activity";
165124144Sphk	case WM8994_GP_FN_DRC2_ACT:
166124144Sphk		return "DRC2 activity";
167124144Sphk	case WM8994_GP_FN_DRC3_ACT:
168124144Sphk		return "DRC3 activity";
169124144Sphk	case WM8994_GP_FN_WSEQ_STATUS:
170124144Sphk		return "Write sequencer";
171124144Sphk	case WM8994_GP_FN_FIFO_ERROR:
172124144Sphk		return "FIFO error";
173124144Sphk	case WM8994_GP_FN_OPCLK:
174124144Sphk		return "OPCLK";
175124144Sphk	case WM8994_GP_FN_THW:
176124144Sphk		return "Thermal warning";
177124144Sphk	case WM8994_GP_FN_DCS_DONE:
178124144Sphk		return "DC servo";
179124144Sphk	case WM8994_GP_FN_FLL1_OUT:
180124144Sphk		return "FLL1 output";
181124144Sphk	case WM8994_GP_FN_FLL2_OUT:
182124144Sphk		return "FLL1 output";
183124144Sphk	default:
184124144Sphk		return "Unknown";
185124144Sphk	}
186124144Sphk}
187124144Sphk
188124144Sphkstatic void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
189124144Sphk{
190124144Sphk	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
191124144Sphk	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
192124144Sphk	int i;
193124144Sphk
194124144Sphk	for (i = 0; i < chip->ngpio; i++) {
195124144Sphk		int gpio = i + chip->base;
196124144Sphk		int reg;
197124144Sphk
198124144Sphk		/* We report the GPIO even if it's not requested since
199124144Sphk		 * we're also reporting things like alternate
200124144Sphk		 * functions which apply even when the GPIO is not in
201124144Sphk		 * use as a GPIO.
202124144Sphk		 */
203124144Sphk		char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
204124144Sphk		if (IS_ERR(label)) {
205124144Sphk			dev_err(wm8994->dev, "Failed to duplicate label\n");
206124144Sphk			continue;
207124144Sphk		}
208124144Sphk
209124144Sphk		seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio,
210124144Sphk			   label ?: "Unrequested");
211124144Sphk
212124144Sphk		reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
213124144Sphk		if (reg < 0) {
214124144Sphk			dev_err(wm8994->dev,
215124144Sphk				"GPIO control %d read failed: %d\n",
216124144Sphk				gpio, reg);
217124144Sphk			seq_printf(s, "\n");
218124144Sphk			continue;
219124144Sphk		}
220124144Sphk
221124144Sphk		if (reg & WM8994_GPN_DIR)
222124144Sphk			seq_printf(s, "in ");
223124144Sphk		else
224124144Sphk			seq_printf(s, "out ");
225124144Sphk
226124144Sphk		if (reg & WM8994_GPN_PU)
227124144Sphk			seq_printf(s, "pull up ");
228124144Sphk
229124144Sphk		if (reg & WM8994_GPN_PD)
230124144Sphk			seq_printf(s, "pull down ");
231124144Sphk
232124144Sphk		if (reg & WM8994_GPN_POL)
233124144Sphk			seq_printf(s, "inverted ");
234124144Sphk		else
235124144Sphk			seq_printf(s, "noninverted ");
236124144Sphk
237124144Sphk		if (reg & WM8994_GPN_OP_CFG)
238124144Sphk			seq_printf(s, "open drain ");
239124144Sphk		else
240124144Sphk			seq_printf(s, "push-pull ");
241124144Sphk
242124144Sphk		seq_printf(s, "%s (%x)\n",
243124144Sphk			   wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg);
244124144Sphk	}
245124144Sphk}
246124144Sphk#else
247124144Sphk#define wm8994_gpio_dbg_show NULL
248124144Sphk#endif
249124144Sphk
250124144Sphkstatic const struct gpio_chip template_chip = {
251124144Sphk	.label			= "wm8994",
252124144Sphk	.owner			= THIS_MODULE,
253124144Sphk	.request		= wm8994_gpio_request,
254124144Sphk	.direction_input	= wm8994_gpio_direction_in,
255124144Sphk	.get			= wm8994_gpio_get,
256124144Sphk	.direction_output	= wm8994_gpio_direction_out,
257124144Sphk	.set			= wm8994_gpio_set,
258124144Sphk	.set_config		= wm8994_gpio_set_config,
259124144Sphk	.to_irq			= wm8994_gpio_to_irq,
260124144Sphk	.dbg_show		= wm8994_gpio_dbg_show,
261124144Sphk	.can_sleep		= true,
262124144Sphk};
263124144Sphk
264124144Sphkstatic int wm8994_gpio_probe(struct platform_device *pdev)
265124144Sphk{
266124144Sphk	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
267124144Sphk	struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev);
268124144Sphk	struct wm8994_gpio *wm8994_gpio;
269124144Sphk
270124144Sphk	wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio),
271124144Sphk				   GFP_KERNEL);
272124144Sphk	if (wm8994_gpio == NULL)
273124144Sphk		return -ENOMEM;
274124144Sphk
275124144Sphk	wm8994_gpio->wm8994 = wm8994;
276124144Sphk	wm8994_gpio->gpio_chip = template_chip;
277124144Sphk	wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
278124144Sphk	wm8994_gpio->gpio_chip.parent = &pdev->dev;
279124144Sphk	if (pdata && pdata->gpio_base)
280124144Sphk		wm8994_gpio->gpio_chip.base = pdata->gpio_base;
281124144Sphk	else
282124144Sphk		wm8994_gpio->gpio_chip.base = -1;
283124144Sphk
284124144Sphk	return devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, wm8994_gpio);
285124144Sphk}
286124144Sphk
287124144Sphkstatic struct platform_driver wm8994_gpio_driver = {
288124144Sphk	.driver.name	= "wm8994-gpio",
289124144Sphk	.probe		= wm8994_gpio_probe,
290124144Sphk};
291124144Sphk
292124144Sphkstatic int __init wm8994_gpio_init(void)
293124144Sphk{
294124144Sphk	return platform_driver_register(&wm8994_gpio_driver);
295124144Sphk}
296124144Sphksubsys_initcall(wm8994_gpio_init);
297124144Sphk
298124144Sphkstatic void __exit wm8994_gpio_exit(void)
299124144Sphk{
300124144Sphk	platform_driver_unregister(&wm8994_gpio_driver);
301}
302module_exit(wm8994_gpio_exit);
303
304MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
305MODULE_DESCRIPTION("GPIO interface for WM8994");
306MODULE_LICENSE("GPL");
307MODULE_ALIAS("platform:wm8994-gpio");
308