xref: /linux/drivers/gpio/gpio-macsmc.c (revision 9b21051b0885912f5bb2cc9d4f95c6fca697da4d)
1*9b21051bSHector Martin // SPDX-License-Identifier: GPL-2.0-only OR MIT
2*9b21051bSHector Martin /*
3*9b21051bSHector Martin  * Apple SMC GPIO driver
4*9b21051bSHector Martin  * Copyright The Asahi Linux Contributors
5*9b21051bSHector Martin  *
6*9b21051bSHector Martin  * This driver implements basic SMC PMU GPIO support that can read inputs
7*9b21051bSHector Martin  * and write outputs. Mode changes and IRQ config are not yet implemented.
8*9b21051bSHector Martin  */
9*9b21051bSHector Martin 
10*9b21051bSHector Martin #include <linux/bitmap.h>
11*9b21051bSHector Martin #include <linux/device.h>
12*9b21051bSHector Martin #include <linux/gpio/driver.h>
13*9b21051bSHector Martin #include <linux/mfd/core.h>
14*9b21051bSHector Martin #include <linux/mfd/macsmc.h>
15*9b21051bSHector Martin 
16*9b21051bSHector Martin #define MAX_GPIO 64
17*9b21051bSHector Martin 
18*9b21051bSHector Martin /*
19*9b21051bSHector Martin  * Commands 0-6 are, presumably, the intended API.
20*9b21051bSHector Martin  * Command 0xff lets you get/set the pin configuration in detail directly,
21*9b21051bSHector Martin  * but the bit meanings seem not to be stable between devices/PMU hardware
22*9b21051bSHector Martin  * versions.
23*9b21051bSHector Martin  *
24*9b21051bSHector Martin  * We're going to try to make do with the low commands for now.
25*9b21051bSHector Martin  * We don't implement pin mode changes at this time.
26*9b21051bSHector Martin  */
27*9b21051bSHector Martin 
28*9b21051bSHector Martin #define CMD_ACTION	(0 << 24)
29*9b21051bSHector Martin #define CMD_OUTPUT	(1 << 24)
30*9b21051bSHector Martin #define CMD_INPUT	(2 << 24)
31*9b21051bSHector Martin #define CMD_PINMODE	(3 << 24)
32*9b21051bSHector Martin #define CMD_IRQ_ENABLE	(4 << 24)
33*9b21051bSHector Martin #define CMD_IRQ_ACK	(5 << 24)
34*9b21051bSHector Martin #define CMD_IRQ_MODE	(6 << 24)
35*9b21051bSHector Martin #define CMD_CONFIG	(0xff << 24)
36*9b21051bSHector Martin 
37*9b21051bSHector Martin #define MODE_INPUT	0
38*9b21051bSHector Martin #define MODE_OUTPUT	1
39*9b21051bSHector Martin #define MODE_VALUE_0	0
40*9b21051bSHector Martin #define MODE_VALUE_1	2
41*9b21051bSHector Martin 
42*9b21051bSHector Martin #define IRQ_MODE_HIGH		0
43*9b21051bSHector Martin #define IRQ_MODE_LOW		1
44*9b21051bSHector Martin #define IRQ_MODE_RISING		2
45*9b21051bSHector Martin #define IRQ_MODE_FALLING	3
46*9b21051bSHector Martin #define IRQ_MODE_BOTH		4
47*9b21051bSHector Martin 
48*9b21051bSHector Martin #define CONFIG_MASK	GENMASK(23, 16)
49*9b21051bSHector Martin #define CONFIG_VAL	GENMASK(7, 0)
50*9b21051bSHector Martin 
51*9b21051bSHector Martin #define CONFIG_OUTMODE	GENMASK(7, 6)
52*9b21051bSHector Martin #define CONFIG_IRQMODE	GENMASK(5, 3)
53*9b21051bSHector Martin #define CONFIG_PULLDOWN	BIT(2)
54*9b21051bSHector Martin #define CONFIG_PULLUP	BIT(1)
55*9b21051bSHector Martin #define CONFIG_OUTVAL	BIT(0)
56*9b21051bSHector Martin 
57*9b21051bSHector Martin /*
58*9b21051bSHector Martin  * Output modes seem to differ depending on the PMU in use... ?
59*9b21051bSHector Martin  * j274 / M1 (Sera PMU):
60*9b21051bSHector Martin  *   0 = input
61*9b21051bSHector Martin  *   1 = output
62*9b21051bSHector Martin  *   2 = open drain
63*9b21051bSHector Martin  *   3 = disable
64*9b21051bSHector Martin  * j314 / M1Pro (Maverick PMU):
65*9b21051bSHector Martin  *   0 = input
66*9b21051bSHector Martin  *   1 = open drain
67*9b21051bSHector Martin  *   2 = output
68*9b21051bSHector Martin  *   3 = ?
69*9b21051bSHector Martin  */
70*9b21051bSHector Martin 
71*9b21051bSHector Martin struct macsmc_gpio {
72*9b21051bSHector Martin 	struct device *dev;
73*9b21051bSHector Martin 	struct apple_smc *smc;
74*9b21051bSHector Martin 	struct gpio_chip gc;
75*9b21051bSHector Martin 
76*9b21051bSHector Martin 	int first_index;
77*9b21051bSHector Martin };
78*9b21051bSHector Martin 
79*9b21051bSHector Martin static int macsmc_gpio_nr(smc_key key)
80*9b21051bSHector Martin {
81*9b21051bSHector Martin 	int low = hex_to_bin(key & 0xff);
82*9b21051bSHector Martin 	int high = hex_to_bin((key >> 8) & 0xff);
83*9b21051bSHector Martin 
84*9b21051bSHector Martin 	if (low < 0 || high < 0)
85*9b21051bSHector Martin 		return -1;
86*9b21051bSHector Martin 
87*9b21051bSHector Martin 	return low | (high << 4);
88*9b21051bSHector Martin }
89*9b21051bSHector Martin 
90*9b21051bSHector Martin static int macsmc_gpio_key(unsigned int offset)
91*9b21051bSHector Martin {
92*9b21051bSHector Martin 	return _SMC_KEY("gP\0\0") | hex_asc_hi(offset) << 8 | hex_asc_lo(offset);
93*9b21051bSHector Martin }
94*9b21051bSHector Martin 
95*9b21051bSHector Martin static int macsmc_gpio_find_first_gpio_index(struct macsmc_gpio *smcgp)
96*9b21051bSHector Martin {
97*9b21051bSHector Martin 	struct apple_smc *smc = smcgp->smc;
98*9b21051bSHector Martin 	smc_key key = macsmc_gpio_key(0);
99*9b21051bSHector Martin 	smc_key first_key, last_key;
100*9b21051bSHector Martin 	int start, count, ret;
101*9b21051bSHector Martin 
102*9b21051bSHector Martin 	/* Return early if the key is out of bounds */
103*9b21051bSHector Martin 	ret = apple_smc_get_key_by_index(smc, 0, &first_key);
104*9b21051bSHector Martin 	if (ret)
105*9b21051bSHector Martin 		return ret;
106*9b21051bSHector Martin 	if (key <= first_key)
107*9b21051bSHector Martin 		return -ENODEV;
108*9b21051bSHector Martin 
109*9b21051bSHector Martin 	ret = apple_smc_get_key_by_index(smc, smc->key_count - 1, &last_key);
110*9b21051bSHector Martin 	if (ret)
111*9b21051bSHector Martin 		return ret;
112*9b21051bSHector Martin 	if (key > last_key)
113*9b21051bSHector Martin 		return -ENODEV;
114*9b21051bSHector Martin 
115*9b21051bSHector Martin 	/* Binary search to find index of first SMC key bigger or equal to key */
116*9b21051bSHector Martin 	start = 0;
117*9b21051bSHector Martin 	count = smc->key_count;
118*9b21051bSHector Martin 	while (count > 1) {
119*9b21051bSHector Martin 		smc_key pkey;
120*9b21051bSHector Martin 		int pivot = start + ((count - 1) >> 1);
121*9b21051bSHector Martin 
122*9b21051bSHector Martin 		ret = apple_smc_get_key_by_index(smc, pivot, &pkey);
123*9b21051bSHector Martin 		if (ret < 0)
124*9b21051bSHector Martin 			return ret;
125*9b21051bSHector Martin 
126*9b21051bSHector Martin 		if (pkey == key)
127*9b21051bSHector Martin 			return pivot;
128*9b21051bSHector Martin 
129*9b21051bSHector Martin 		pivot++;
130*9b21051bSHector Martin 
131*9b21051bSHector Martin 		if (pkey < key) {
132*9b21051bSHector Martin 			count -= pivot - start;
133*9b21051bSHector Martin 			start = pivot;
134*9b21051bSHector Martin 		} else {
135*9b21051bSHector Martin 			count = pivot - start;
136*9b21051bSHector Martin 		}
137*9b21051bSHector Martin 	}
138*9b21051bSHector Martin 
139*9b21051bSHector Martin 	return start;
140*9b21051bSHector Martin }
141*9b21051bSHector Martin 
142*9b21051bSHector Martin static int macsmc_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
143*9b21051bSHector Martin {
144*9b21051bSHector Martin 	struct macsmc_gpio *smcgp = gpiochip_get_data(gc);
145*9b21051bSHector Martin 	smc_key key = macsmc_gpio_key(offset);
146*9b21051bSHector Martin 	u32 val;
147*9b21051bSHector Martin 	int ret;
148*9b21051bSHector Martin 
149*9b21051bSHector Martin 	/* First try reading the explicit pin mode register */
150*9b21051bSHector Martin 	ret = apple_smc_rw_u32(smcgp->smc, key, CMD_PINMODE, &val);
151*9b21051bSHector Martin 	if (!ret)
152*9b21051bSHector Martin 		return (val & MODE_OUTPUT) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
153*9b21051bSHector Martin 
154*9b21051bSHector Martin 	/*
155*9b21051bSHector Martin 	 * Less common IRQ configs cause CMD_PINMODE to fail, and so does open drain mode.
156*9b21051bSHector Martin 	 * Fall back to reading IRQ mode, which will only succeed for inputs.
157*9b21051bSHector Martin 	 */
158*9b21051bSHector Martin 	ret = apple_smc_rw_u32(smcgp->smc, key, CMD_IRQ_MODE, &val);
159*9b21051bSHector Martin 	return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
160*9b21051bSHector Martin }
161*9b21051bSHector Martin 
162*9b21051bSHector Martin static int macsmc_gpio_get(struct gpio_chip *gc, unsigned int offset)
163*9b21051bSHector Martin {
164*9b21051bSHector Martin 	struct macsmc_gpio *smcgp = gpiochip_get_data(gc);
165*9b21051bSHector Martin 	smc_key key = macsmc_gpio_key(offset);
166*9b21051bSHector Martin 	u32 cmd, val;
167*9b21051bSHector Martin 	int ret;
168*9b21051bSHector Martin 
169*9b21051bSHector Martin 	ret = macsmc_gpio_get_direction(gc, offset);
170*9b21051bSHector Martin 	if (ret < 0)
171*9b21051bSHector Martin 		return ret;
172*9b21051bSHector Martin 
173*9b21051bSHector Martin 	if (ret == GPIO_LINE_DIRECTION_OUT)
174*9b21051bSHector Martin 		cmd = CMD_OUTPUT;
175*9b21051bSHector Martin 	else
176*9b21051bSHector Martin 		cmd = CMD_INPUT;
177*9b21051bSHector Martin 
178*9b21051bSHector Martin 	ret = apple_smc_rw_u32(smcgp->smc, key, cmd, &val);
179*9b21051bSHector Martin 	if (ret < 0)
180*9b21051bSHector Martin 		return ret;
181*9b21051bSHector Martin 
182*9b21051bSHector Martin 	return val ? 1 : 0;
183*9b21051bSHector Martin }
184*9b21051bSHector Martin 
185*9b21051bSHector Martin static int macsmc_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
186*9b21051bSHector Martin {
187*9b21051bSHector Martin 	struct macsmc_gpio *smcgp = gpiochip_get_data(gc);
188*9b21051bSHector Martin 	smc_key key = macsmc_gpio_key(offset);
189*9b21051bSHector Martin 	int ret;
190*9b21051bSHector Martin 
191*9b21051bSHector Martin 	value |= CMD_OUTPUT;
192*9b21051bSHector Martin 	ret = apple_smc_write_u32(smcgp->smc, key, CMD_OUTPUT | value);
193*9b21051bSHector Martin 	if (ret < 0)
194*9b21051bSHector Martin 		dev_err(smcgp->dev, "GPIO set failed %p4ch = 0x%x\n",
195*9b21051bSHector Martin 			&key, value);
196*9b21051bSHector Martin 
197*9b21051bSHector Martin 	return ret;
198*9b21051bSHector Martin }
199*9b21051bSHector Martin 
200*9b21051bSHector Martin static int macsmc_gpio_init_valid_mask(struct gpio_chip *gc,
201*9b21051bSHector Martin 				       unsigned long *valid_mask, unsigned int ngpios)
202*9b21051bSHector Martin {
203*9b21051bSHector Martin 	struct macsmc_gpio *smcgp = gpiochip_get_data(gc);
204*9b21051bSHector Martin 	int count;
205*9b21051bSHector Martin 	int i;
206*9b21051bSHector Martin 
207*9b21051bSHector Martin 	count = min(smcgp->smc->key_count, MAX_GPIO);
208*9b21051bSHector Martin 
209*9b21051bSHector Martin 	bitmap_zero(valid_mask, ngpios);
210*9b21051bSHector Martin 
211*9b21051bSHector Martin 	for (i = 0; i < count; i++) {
212*9b21051bSHector Martin 		int ret, gpio_nr;
213*9b21051bSHector Martin 		smc_key key;
214*9b21051bSHector Martin 
215*9b21051bSHector Martin 		ret = apple_smc_get_key_by_index(smcgp->smc, smcgp->first_index + i, &key);
216*9b21051bSHector Martin 		if (ret < 0)
217*9b21051bSHector Martin 			return ret;
218*9b21051bSHector Martin 
219*9b21051bSHector Martin 		if (key > SMC_KEY(gPff))
220*9b21051bSHector Martin 			break;
221*9b21051bSHector Martin 
222*9b21051bSHector Martin 		gpio_nr = macsmc_gpio_nr(key);
223*9b21051bSHector Martin 		if (gpio_nr < 0 || gpio_nr > MAX_GPIO) {
224*9b21051bSHector Martin 			dev_err(smcgp->dev, "Bad GPIO key %p4ch\n", &key);
225*9b21051bSHector Martin 			continue;
226*9b21051bSHector Martin 		}
227*9b21051bSHector Martin 
228*9b21051bSHector Martin 		set_bit(gpio_nr, valid_mask);
229*9b21051bSHector Martin 	}
230*9b21051bSHector Martin 
231*9b21051bSHector Martin 	return 0;
232*9b21051bSHector Martin }
233*9b21051bSHector Martin 
234*9b21051bSHector Martin static int macsmc_gpio_probe(struct platform_device *pdev)
235*9b21051bSHector Martin {
236*9b21051bSHector Martin 	struct macsmc_gpio *smcgp;
237*9b21051bSHector Martin 	struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
238*9b21051bSHector Martin 	smc_key key;
239*9b21051bSHector Martin 	int ret;
240*9b21051bSHector Martin 
241*9b21051bSHector Martin 	smcgp = devm_kzalloc(&pdev->dev, sizeof(*smcgp), GFP_KERNEL);
242*9b21051bSHector Martin 	if (!smcgp)
243*9b21051bSHector Martin 		return -ENOMEM;
244*9b21051bSHector Martin 
245*9b21051bSHector Martin 	smcgp->dev = &pdev->dev;
246*9b21051bSHector Martin 	smcgp->smc = smc;
247*9b21051bSHector Martin 
248*9b21051bSHector Martin 	smcgp->first_index = macsmc_gpio_find_first_gpio_index(smcgp);
249*9b21051bSHector Martin 	if (smcgp->first_index < 0)
250*9b21051bSHector Martin 		return smcgp->first_index;
251*9b21051bSHector Martin 
252*9b21051bSHector Martin 	ret = apple_smc_get_key_by_index(smc, smcgp->first_index, &key);
253*9b21051bSHector Martin 	if (ret < 0)
254*9b21051bSHector Martin 		return ret;
255*9b21051bSHector Martin 
256*9b21051bSHector Martin 	if (key > macsmc_gpio_key(MAX_GPIO - 1))
257*9b21051bSHector Martin 		return -ENODEV;
258*9b21051bSHector Martin 
259*9b21051bSHector Martin 	dev_info(smcgp->dev, "First GPIO key: %p4ch\n", &key);
260*9b21051bSHector Martin 
261*9b21051bSHector Martin 	smcgp->gc.label = "macsmc-pmu-gpio";
262*9b21051bSHector Martin 	smcgp->gc.owner = THIS_MODULE;
263*9b21051bSHector Martin 	smcgp->gc.get = macsmc_gpio_get;
264*9b21051bSHector Martin 	smcgp->gc.set_rv = macsmc_gpio_set;
265*9b21051bSHector Martin 	smcgp->gc.get_direction = macsmc_gpio_get_direction;
266*9b21051bSHector Martin 	smcgp->gc.init_valid_mask = macsmc_gpio_init_valid_mask;
267*9b21051bSHector Martin 	smcgp->gc.can_sleep = true;
268*9b21051bSHector Martin 	smcgp->gc.ngpio = MAX_GPIO;
269*9b21051bSHector Martin 	smcgp->gc.base = -1;
270*9b21051bSHector Martin 	smcgp->gc.parent = &pdev->dev;
271*9b21051bSHector Martin 
272*9b21051bSHector Martin 	return devm_gpiochip_add_data(&pdev->dev, &smcgp->gc, smcgp);
273*9b21051bSHector Martin }
274*9b21051bSHector Martin 
275*9b21051bSHector Martin static const struct of_device_id macsmc_gpio_of_table[] = {
276*9b21051bSHector Martin 	{ .compatible = "apple,smc-gpio", },
277*9b21051bSHector Martin 	{}
278*9b21051bSHector Martin };
279*9b21051bSHector Martin MODULE_DEVICE_TABLE(of, macsmc_gpio_of_table);
280*9b21051bSHector Martin 
281*9b21051bSHector Martin static struct platform_driver macsmc_gpio_driver = {
282*9b21051bSHector Martin 	.driver = {
283*9b21051bSHector Martin 		.name = "macsmc-gpio",
284*9b21051bSHector Martin 		.of_match_table = macsmc_gpio_of_table,
285*9b21051bSHector Martin 	},
286*9b21051bSHector Martin 	.probe = macsmc_gpio_probe,
287*9b21051bSHector Martin };
288*9b21051bSHector Martin module_platform_driver(macsmc_gpio_driver);
289*9b21051bSHector Martin 
290*9b21051bSHector Martin MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
291*9b21051bSHector Martin MODULE_LICENSE("Dual MIT/GPL");
292*9b21051bSHector Martin MODULE_DESCRIPTION("Apple SMC GPIO driver");
293