xref: /OK3568_Linux_fs/kernel/drivers/gpio/gpio-menz127.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * MEN 16Z127 GPIO driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2016 MEN Mikroelektronik GmbH (www.men.de)
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/err.h>
12*4882a593Smuzhiyun #include <linux/mcb.h>
13*4882a593Smuzhiyun #include <linux/bitops.h>
14*4882a593Smuzhiyun #include <linux/gpio/driver.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define MEN_Z127_CTRL	0x00
17*4882a593Smuzhiyun #define MEN_Z127_PSR	0x04
18*4882a593Smuzhiyun #define MEN_Z127_IRQR	0x08
19*4882a593Smuzhiyun #define MEN_Z127_GPIODR	0x0c
20*4882a593Smuzhiyun #define MEN_Z127_IER1	0x10
21*4882a593Smuzhiyun #define MEN_Z127_IER2	0x14
22*4882a593Smuzhiyun #define MEN_Z127_DBER	0x18
23*4882a593Smuzhiyun #define MEN_Z127_ODER	0x1C
24*4882a593Smuzhiyun #define GPIO_TO_DBCNT_REG(gpio)	((gpio * 4) + 0x80)
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define MEN_Z127_DB_MIN_US	50
27*4882a593Smuzhiyun /* 16 bit compare register. Each bit represents 50us */
28*4882a593Smuzhiyun #define MEN_Z127_DB_MAX_US	(0xffff * MEN_Z127_DB_MIN_US)
29*4882a593Smuzhiyun #define MEN_Z127_DB_IN_RANGE(db)	((db >= MEN_Z127_DB_MIN_US) && \
30*4882a593Smuzhiyun 					 (db <= MEN_Z127_DB_MAX_US))
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun struct men_z127_gpio {
33*4882a593Smuzhiyun 	struct gpio_chip gc;
34*4882a593Smuzhiyun 	void __iomem *reg_base;
35*4882a593Smuzhiyun 	struct resource *mem;
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun 
men_z127_debounce(struct gpio_chip * gc,unsigned gpio,unsigned debounce)38*4882a593Smuzhiyun static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
39*4882a593Smuzhiyun 			     unsigned debounce)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	struct men_z127_gpio *priv = gpiochip_get_data(gc);
42*4882a593Smuzhiyun 	struct device *dev = gc->parent;
43*4882a593Smuzhiyun 	unsigned int rnd;
44*4882a593Smuzhiyun 	u32 db_en, db_cnt;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (!MEN_Z127_DB_IN_RANGE(debounce)) {
47*4882a593Smuzhiyun 		dev_err(dev, "debounce value %u out of range", debounce);
48*4882a593Smuzhiyun 		return -EINVAL;
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	if (debounce > 0) {
52*4882a593Smuzhiyun 		/* round up or down depending on MSB-1 */
53*4882a593Smuzhiyun 		rnd = fls(debounce) - 1;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 		if (rnd && (debounce & BIT(rnd - 1)))
56*4882a593Smuzhiyun 			debounce = roundup(debounce, MEN_Z127_DB_MIN_US);
57*4882a593Smuzhiyun 		else
58*4882a593Smuzhiyun 			debounce = rounddown(debounce, MEN_Z127_DB_MIN_US);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 		if (debounce > MEN_Z127_DB_MAX_US)
61*4882a593Smuzhiyun 			debounce = MEN_Z127_DB_MAX_US;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 		/* 50us per register unit */
64*4882a593Smuzhiyun 		debounce /= 50;
65*4882a593Smuzhiyun 	}
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	spin_lock(&gc->bgpio_lock);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	db_en = readl(priv->reg_base + MEN_Z127_DBER);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	if (debounce == 0) {
72*4882a593Smuzhiyun 		db_en &= ~BIT(gpio);
73*4882a593Smuzhiyun 		db_cnt = 0;
74*4882a593Smuzhiyun 	} else {
75*4882a593Smuzhiyun 		db_en |= BIT(gpio);
76*4882a593Smuzhiyun 		db_cnt = debounce;
77*4882a593Smuzhiyun 	}
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	writel(db_en, priv->reg_base + MEN_Z127_DBER);
80*4882a593Smuzhiyun 	writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio));
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	spin_unlock(&gc->bgpio_lock);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return 0;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
men_z127_set_single_ended(struct gpio_chip * gc,unsigned offset,enum pin_config_param param)87*4882a593Smuzhiyun static int men_z127_set_single_ended(struct gpio_chip *gc,
88*4882a593Smuzhiyun 				     unsigned offset,
89*4882a593Smuzhiyun 				     enum pin_config_param param)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct men_z127_gpio *priv = gpiochip_get_data(gc);
92*4882a593Smuzhiyun 	u32 od_en;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	spin_lock(&gc->bgpio_lock);
95*4882a593Smuzhiyun 	od_en = readl(priv->reg_base + MEN_Z127_ODER);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
98*4882a593Smuzhiyun 		od_en |= BIT(offset);
99*4882a593Smuzhiyun 	else
100*4882a593Smuzhiyun 		/* Implicitly PIN_CONFIG_DRIVE_PUSH_PULL */
101*4882a593Smuzhiyun 		od_en &= ~BIT(offset);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	writel(od_en, priv->reg_base + MEN_Z127_ODER);
104*4882a593Smuzhiyun 	spin_unlock(&gc->bgpio_lock);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
men_z127_set_config(struct gpio_chip * gc,unsigned offset,unsigned long config)109*4882a593Smuzhiyun static int men_z127_set_config(struct gpio_chip *gc, unsigned offset,
110*4882a593Smuzhiyun 			       unsigned long config)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	enum pin_config_param param = pinconf_to_config_param(config);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	switch (param) {
115*4882a593Smuzhiyun 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
116*4882a593Smuzhiyun 	case PIN_CONFIG_DRIVE_PUSH_PULL:
117*4882a593Smuzhiyun 		return men_z127_set_single_ended(gc, offset, param);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	case PIN_CONFIG_INPUT_DEBOUNCE:
120*4882a593Smuzhiyun 		return men_z127_debounce(gc, offset,
121*4882a593Smuzhiyun 			pinconf_to_config_argument(config));
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	default:
124*4882a593Smuzhiyun 		break;
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	return -ENOTSUPP;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
men_z127_probe(struct mcb_device * mdev,const struct mcb_device_id * id)130*4882a593Smuzhiyun static int men_z127_probe(struct mcb_device *mdev,
131*4882a593Smuzhiyun 			  const struct mcb_device_id *id)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	struct men_z127_gpio *men_z127_gpio;
134*4882a593Smuzhiyun 	struct device *dev = &mdev->dev;
135*4882a593Smuzhiyun 	int ret;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	men_z127_gpio = devm_kzalloc(dev, sizeof(struct men_z127_gpio),
138*4882a593Smuzhiyun 				     GFP_KERNEL);
139*4882a593Smuzhiyun 	if (!men_z127_gpio)
140*4882a593Smuzhiyun 		return -ENOMEM;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	men_z127_gpio->mem = mcb_request_mem(mdev, dev_name(dev));
143*4882a593Smuzhiyun 	if (IS_ERR(men_z127_gpio->mem)) {
144*4882a593Smuzhiyun 		dev_err(dev, "failed to request device memory");
145*4882a593Smuzhiyun 		return PTR_ERR(men_z127_gpio->mem);
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	men_z127_gpio->reg_base = ioremap(men_z127_gpio->mem->start,
149*4882a593Smuzhiyun 					  resource_size(men_z127_gpio->mem));
150*4882a593Smuzhiyun 	if (men_z127_gpio->reg_base == NULL) {
151*4882a593Smuzhiyun 		ret = -ENXIO;
152*4882a593Smuzhiyun 		goto err_release;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	mcb_set_drvdata(mdev, men_z127_gpio);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4,
158*4882a593Smuzhiyun 			 men_z127_gpio->reg_base + MEN_Z127_PSR,
159*4882a593Smuzhiyun 			 men_z127_gpio->reg_base + MEN_Z127_CTRL,
160*4882a593Smuzhiyun 			 NULL,
161*4882a593Smuzhiyun 			 men_z127_gpio->reg_base + MEN_Z127_GPIODR,
162*4882a593Smuzhiyun 			 NULL, 0);
163*4882a593Smuzhiyun 	if (ret)
164*4882a593Smuzhiyun 		goto err_unmap;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	men_z127_gpio->gc.set_config = men_z127_set_config;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
169*4882a593Smuzhiyun 	if (ret) {
170*4882a593Smuzhiyun 		dev_err(dev, "failed to register MEN 16Z127 GPIO controller");
171*4882a593Smuzhiyun 		goto err_unmap;
172*4882a593Smuzhiyun 	}
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	dev_info(dev, "MEN 16Z127 GPIO driver registered");
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	return 0;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun err_unmap:
179*4882a593Smuzhiyun 	iounmap(men_z127_gpio->reg_base);
180*4882a593Smuzhiyun err_release:
181*4882a593Smuzhiyun 	mcb_release_mem(men_z127_gpio->mem);
182*4882a593Smuzhiyun 	return ret;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
men_z127_remove(struct mcb_device * mdev)185*4882a593Smuzhiyun static void men_z127_remove(struct mcb_device *mdev)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	struct men_z127_gpio *men_z127_gpio = mcb_get_drvdata(mdev);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	gpiochip_remove(&men_z127_gpio->gc);
190*4882a593Smuzhiyun 	iounmap(men_z127_gpio->reg_base);
191*4882a593Smuzhiyun 	mcb_release_mem(men_z127_gpio->mem);
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun static const struct mcb_device_id men_z127_ids[] = {
195*4882a593Smuzhiyun 	{ .device = 0x7f },
196*4882a593Smuzhiyun 	{ }
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun MODULE_DEVICE_TABLE(mcb, men_z127_ids);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun static struct mcb_driver men_z127_driver = {
201*4882a593Smuzhiyun 	.driver = {
202*4882a593Smuzhiyun 		.name = "z127-gpio",
203*4882a593Smuzhiyun 	},
204*4882a593Smuzhiyun 	.probe = men_z127_probe,
205*4882a593Smuzhiyun 	.remove = men_z127_remove,
206*4882a593Smuzhiyun 	.id_table = men_z127_ids,
207*4882a593Smuzhiyun };
208*4882a593Smuzhiyun module_mcb_driver(men_z127_driver);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
211*4882a593Smuzhiyun MODULE_DESCRIPTION("MEN 16z127 GPIO Controller");
212*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
213*4882a593Smuzhiyun MODULE_ALIAS("mcb:16z127");
214*4882a593Smuzhiyun MODULE_IMPORT_NS(MCB);
215