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