xref: /linux/drivers/gpio/gpio-ppc44x.c (revision 1200d84f4c0a929a0780180d25063d93773be79c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * PPC44x gpio driver
4  *
5  * Copyright (c) 2008 Harris Corporation
6  * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
7  * Copyright (c) MontaVista Software, Inc. 2008.
8  *
9  * Author: Steve Falco <sfalco@harris.com>
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/io.h>
15 #include <linux/of.h>
16 #include <linux/gpio/generic.h>
17 #include <linux/types.h>
18 #include <linux/slab.h>
19 #include <linux/platform_device.h>
20 
21 #define GPIO_MASK(gpio)		(0x80000000 >> (gpio))
22 #define GPIO_MASK2(gpio)	(0xc0000000 >> (((gpio) % 16) * 2))
23 
24 /* Physical GPIO register layout */
25 struct ppc44x_gpio {
26 	__be32 or;
27 	__be32 tcr;
28 	__be32 osrl;
29 	__be32 osrh;
30 	__be32 tsrl;
31 	__be32 tsrh;
32 	__be32 odr;
33 	__be32 ir;
34 	__be32 rr1;
35 	__be32 rr2;
36 	__be32 rr3;
37 	__be32 reserved1;
38 	__be32 isr1l;
39 	__be32 isr1h;
40 	__be32 isr2l;
41 	__be32 isr2h;
42 	__be32 isr3l;
43 	__be32 isr3h;
44 };
45 
46 struct ppc44x_gpio_chip {
47 	struct gpio_generic_chip chip;
48 	void __iomem *regs;
49 };
50 
51 static inline void ppc44x_clrbits32(void __iomem *addr, u32 mask)
52 {
53 	u32 val = ioread32be(addr);
54 
55 	val &= ~mask;
56 	iowrite32be(val, addr);
57 }
58 
59 static inline void ppc44x_setbits32(void __iomem *addr, u32 mask)
60 {
61 	u32 val = ioread32be(addr);
62 
63 	val |= mask;
64 	iowrite32be(val, addr);
65 }
66 
67 /*
68  * GPIO LIB API implementation for GPIOs
69  *
70  * There are a maximum of 32 gpios in each gpio controller.
71  */
72 
73 static inline void
74 __ppc44x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
75 {
76 	struct ppc44x_gpio_chip *chip = gpiochip_get_data(gc);
77 	struct gpio_generic_chip *gen_gc = &chip->chip;
78 
79 	if (val)
80 		gen_gc->sdata |= GPIO_MASK(gpio);
81 	else
82 		gen_gc->sdata &= ~GPIO_MASK(gpio);
83 
84 	gpio_generic_write_reg(gen_gc, gen_gc->reg_set, gen_gc->sdata);
85 }
86 
87 static int ppc44x_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
88 {
89 	struct ppc44x_gpio_chip *chip = gpiochip_get_data(gc);
90 	struct gpio_generic_chip *gen_gc = &chip->chip;
91 	struct ppc44x_gpio __iomem *regs = chip->regs;
92 
93 	guard(gpio_generic_lock_irqsave)(gen_gc);
94 
95 	/* Disable open-drain function */
96 	ppc44x_clrbits32(&regs->odr, GPIO_MASK(gpio));
97 
98 	/* Float the pin */
99 	ppc44x_clrbits32(&regs->tcr, GPIO_MASK(gpio));
100 	gen_gc->sdir &= ~GPIO_MASK(gpio);
101 
102 	/* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */
103 	if (gpio < 16) {
104 		ppc44x_clrbits32(&regs->osrl, GPIO_MASK2(gpio));
105 		ppc44x_clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
106 	} else {
107 		ppc44x_clrbits32(&regs->osrh, GPIO_MASK2(gpio));
108 		ppc44x_clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
109 	}
110 
111 	return 0;
112 }
113 
114 static int
115 ppc44x_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
116 {
117 	struct ppc44x_gpio_chip *chip = gpiochip_get_data(gc);
118 	struct gpio_generic_chip *gen_gc = &chip->chip;
119 	struct ppc44x_gpio __iomem *regs = chip->regs;
120 
121 	guard(gpio_generic_lock_irqsave)(gen_gc);
122 
123 	/* First set initial value */
124 	__ppc44x_gpio_set(gc, gpio, val);
125 
126 	/* Disable open-drain function */
127 	ppc44x_clrbits32(&regs->odr, GPIO_MASK(gpio));
128 
129 	/* Drive the pin */
130 	ppc44x_setbits32(&regs->tcr, GPIO_MASK(gpio));
131 	gen_gc->sdir |= GPIO_MASK(gpio);
132 
133 	/* Bits 0-15 use TSRL, bits 16-31 use TSRH */
134 	if (gpio < 16) {
135 		ppc44x_clrbits32(&regs->osrl, GPIO_MASK2(gpio));
136 		ppc44x_clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
137 	} else {
138 		ppc44x_clrbits32(&regs->osrh, GPIO_MASK2(gpio));
139 		ppc44x_clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
140 	}
141 
142 	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
143 
144 	return 0;
145 }
146 
147 static int ppc44x_gpio_probe(struct platform_device *ofdev)
148 {
149 	struct device *dev = &ofdev->dev;
150 	struct ppc44x_gpio __iomem *regs;
151 	struct ppc44x_gpio_chip *chip;
152 	struct gpio_generic_chip_config config;
153 	struct gpio_chip *gc;
154 	int ret;
155 
156 	regs = devm_platform_ioremap_resource(ofdev, 0);
157 	if (IS_ERR(regs))
158 		return PTR_ERR(regs);
159 
160 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
161 	if (!chip)
162 		return -ENOMEM;
163 
164 	chip->regs = regs;
165 
166 	config = (struct gpio_generic_chip_config) {
167 		.dev = dev,
168 		.sz = 4,
169 		.dat = &regs->ir,
170 		.set = &regs->or,
171 		.dirout = &regs->tcr,
172 		.flags = GPIO_GENERIC_BIG_ENDIAN |
173 			 GPIO_GENERIC_BIG_ENDIAN_BYTE_ORDER,
174 	};
175 
176 	ret = gpio_generic_chip_init(&chip->chip, &config);
177 	if (ret)
178 		return ret;
179 
180 	gc = &chip->chip.gc;
181 	gc->label = dev_name(dev);
182 	gc->parent = dev;
183 	gc->direction_input = ppc44x_gpio_dir_in;
184 	gc->direction_output = ppc44x_gpio_dir_out;
185 
186 	return devm_gpiochip_add_data(dev, gc, chip);
187 }
188 
189 static const struct of_device_id ppc44x_gpio_match[] = {
190 	{
191 		.compatible = "ibm,ppc4xx-gpio",
192 	},
193 	{},
194 };
195 MODULE_DEVICE_TABLE(of, ppc44x_gpio_match);
196 
197 static struct platform_driver ppc44x_gpio_driver = {
198 	.probe		= ppc44x_gpio_probe,
199 	.driver		= {
200 		.name	= "ppc44x-gpio",
201 		.of_match_table	= ppc44x_gpio_match,
202 	},
203 };
204 
205 MODULE_DESCRIPTION("PPC44x gpio driver");
206 MODULE_LICENSE("GPL");
207 
208 module_platform_driver(ppc44x_gpio_driver);
209