File Index
Files and directories
Sign in
FILE

gpio-mpc5200.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpio-mpc5200.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * MPC52xx gpio driver
  4 *
  5 * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  6 */
  7
  8#include <linux/of.h>
  9#include <linux/kernel.h>
 10#include <linux/slab.h>
 11#include <linux/gpio/driver.h>
 12#include <linux/io.h>
 13#include <linux/platform_device.h>
 14#include <linux/module.h>
 15
 16#include <asm/mpc52xx.h>
 17#include <sysdev/fsl_soc.h>
 18
 19static DEFINE_SPINLOCK(gpio_lock);
 20
 21struct mpc52xx_gpiochip {
 22	struct gpio_chip gc;
 23	void __iomem *regs;
 24	unsigned int shadow_dvo;
 25	unsigned int shadow_gpioe;
 26	unsigned int shadow_ddr;
 27};
 28
 29/*
 30 * GPIO LIB API implementation for wakeup GPIOs.
 31 *
 32 * There's a maximum of 8 wakeup GPIOs. Which of these are available
 33 * for use depends on your board setup.
 34 *
 35 * 0 -> GPIO_WKUP_7
 36 * 1 -> GPIO_WKUP_6
 37 * 2 -> PSC6_1
 38 * 3 -> PSC6_0
 39 * 4 -> ETH_17
 40 * 5 -> PSC3_9
 41 * 6 -> PSC2_4
 42 * 7 -> PSC1_4
 43 *
 44 */
 45static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
 46{
 47	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
 48	struct mpc52xx_gpio_wkup __iomem *regs = chip->regs;
 49	unsigned int ret;
 50
 51	ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1;
 52
 53	pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
 54
 55	return ret;
 56}
 57
 58static inline void
 59__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 60{
 61	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
 62	struct mpc52xx_gpio_wkup __iomem *regs = chip->regs;
 63
 64	if (val)
 65		chip->shadow_dvo |= 1 << (7 - gpio);
 66	else
 67		chip->shadow_dvo &= ~(1 << (7 - gpio));
 68
 69	out_8(&regs->wkup_dvo, chip->shadow_dvo);
 70}
 71
 72static int
 73mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 74{
 75	unsigned long flags;
 76
 77	spin_lock_irqsave(&gpio_lock, flags);
 78
 79	__mpc52xx_wkup_gpio_set(gc, gpio, val);
 80
 81	spin_unlock_irqrestore(&gpio_lock, flags);
 82
 83	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
 84
 85	return 0;
 86}
 87
 88static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
 89{
 90	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
 91	struct mpc52xx_gpio_wkup __iomem *regs = chip->regs;
 92	unsigned long flags;
 93
 94	spin_lock_irqsave(&gpio_lock, flags);
 95
 96	/* set the direction */
 97	chip->shadow_ddr &= ~(1 << (7 - gpio));
 98	out_8(&regs->wkup_ddr, chip->shadow_ddr);
 99
100	/* and enable the pin */
101	chip->shadow_gpioe |= 1 << (7 - gpio);
102	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
103
104	spin_unlock_irqrestore(&gpio_lock, flags);
105
106	return 0;
107}
108
109static int
110mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
111{
112	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
113	struct mpc52xx_gpio_wkup __iomem *regs = chip->regs;
114	unsigned long flags;
115
116	spin_lock_irqsave(&gpio_lock, flags);
117
118	__mpc52xx_wkup_gpio_set(gc, gpio, val);
119
120	/* Then set direction */
121	chip->shadow_ddr |= 1 << (7 - gpio);
122	out_8(&regs->wkup_ddr, chip->shadow_ddr);
123
124	/* Finally enable the pin */
125	chip->shadow_gpioe |= 1 << (7 - gpio);
126	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
127
128	spin_unlock_irqrestore(&gpio_lock, flags);
129
130	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
131
132	return 0;
133}
134
135static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
136{
137	struct device *dev = &ofdev->dev;
138	struct device_node *np = dev->of_node;
139	struct mpc52xx_gpiochip *chip;
140	struct mpc52xx_gpio_wkup __iomem *regs;
141	struct gpio_chip *gc;
142	int ret;
143
144	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
145	if (!chip)
146		return -ENOMEM;
147
148	platform_set_drvdata(ofdev, chip);
149
150	gc = &chip->gc;
151
152	gc->base             = -1;
153	gc->ngpio            = 8;
154	gc->direction_input  = mpc52xx_wkup_gpio_dir_in;
155	gc->direction_output = mpc52xx_wkup_gpio_dir_out;
156	gc->get              = mpc52xx_wkup_gpio_get;
157	gc->set              = mpc52xx_wkup_gpio_set;
158
159	gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
160	if (!gc->label)
161		return -ENOMEM;
162
163	chip->regs = devm_of_iomap(dev, np, 0, NULL);
164	if (IS_ERR(chip->regs))
165		return PTR_ERR(chip->regs);
166
167	ret = devm_gpiochip_add_data(dev, gc, chip);
168	if (ret)
169		return ret;
170
171	regs = chip->regs;
172	chip->shadow_gpioe = in_8(&regs->wkup_gpioe);
173	chip->shadow_ddr = in_8(&regs->wkup_ddr);
174	chip->shadow_dvo = in_8(&regs->wkup_dvo);
175
176	return 0;
177}
178
179static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
180	{ .compatible = "fsl,mpc5200-gpio-wkup", },
181	{}
182};
183
184static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
185	.driver = {
186		.name = "mpc5200-gpio-wkup",
187		.of_match_table = mpc52xx_wkup_gpiochip_match,
188	},
189	.probe = mpc52xx_wkup_gpiochip_probe,
190};
191
192/*
193 * GPIO LIB API implementation for simple GPIOs
194 *
195 * There's a maximum of 32 simple GPIOs. Which of these are available
196 * for use depends on your board setup.
197 * The numbering reflects the bit numbering in the port registers:
198 *
199 *  0..1  > reserved
200 *  2..3  > IRDA
201 *  4..7  > ETHR
202 *  8..11 > reserved
203 * 12..15 > USB
204 * 16..17 > reserved
205 * 18..23 > PSC3
206 * 24..27 > PSC2
207 * 28..31 > PSC1
208 */
209static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
210{
211	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
212	struct mpc52xx_gpio __iomem *regs = chip->regs;
213	unsigned int ret;
214
215	ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1;
216
217	return ret;
218}
219
220static inline void
221__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
222{
223	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
224	struct mpc52xx_gpio __iomem *regs = chip->regs;
225
226	if (val)
227		chip->shadow_dvo |= 1 << (31 - gpio);
228	else
229		chip->shadow_dvo &= ~(1 << (31 - gpio));
230	out_be32(&regs->simple_dvo, chip->shadow_dvo);
231}
232
233static int
234mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
235{
236	unsigned long flags;
237
238	spin_lock_irqsave(&gpio_lock, flags);
239
240	__mpc52xx_simple_gpio_set(gc, gpio, val);
241
242	spin_unlock_irqrestore(&gpio_lock, flags);
243
244	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
245
246	return 0;
247}
248
249static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
250{
251	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
252	struct mpc52xx_gpio __iomem *regs = chip->regs;
253	unsigned long flags;
254
255	spin_lock_irqsave(&gpio_lock, flags);
256
257	/* set the direction */
258	chip->shadow_ddr &= ~(1 << (31 - gpio));
259	out_be32(&regs->simple_ddr, chip->shadow_ddr);
260
261	/* and enable the pin */
262	chip->shadow_gpioe |= 1 << (31 - gpio);
263	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
264
265	spin_unlock_irqrestore(&gpio_lock, flags);
266
267	return 0;
268}
269
270static int
271mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
272{
273	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
274	struct mpc52xx_gpio __iomem *regs = chip->regs;
275	unsigned long flags;
276
277	spin_lock_irqsave(&gpio_lock, flags);
278
279	/* First set initial value */
280	__mpc52xx_simple_gpio_set(gc, gpio, val);
281
282	/* Then set direction */
283	chip->shadow_ddr |= 1 << (31 - gpio);
284	out_be32(&regs->simple_ddr, chip->shadow_ddr);
285
286	/* Finally enable the pin */
287	chip->shadow_gpioe |= 1 << (31 - gpio);
288	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
289
290	spin_unlock_irqrestore(&gpio_lock, flags);
291
292	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
293
294	return 0;
295}
296
297static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
298{
299	struct device *dev = &ofdev->dev;
300	struct device_node *np = dev->of_node;
301	struct mpc52xx_gpiochip *chip;
302	struct gpio_chip *gc;
303	struct mpc52xx_gpio __iomem *regs;
304	int ret;
305
306	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
307	if (!chip)
308		return -ENOMEM;
309
310	platform_set_drvdata(ofdev, chip);
311
312	gc = &chip->gc;
313
314	gc->base             = -1;
315	gc->ngpio            = 32;
316	gc->direction_input  = mpc52xx_simple_gpio_dir_in;
317	gc->direction_output = mpc52xx_simple_gpio_dir_out;
318	gc->get              = mpc52xx_simple_gpio_get;
319	gc->set              = mpc52xx_simple_gpio_set;
320
321	gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
322	if (!gc->label)
323		return -ENOMEM;
324
325	chip->regs = devm_of_iomap(dev, np, 0, NULL);
326	if (IS_ERR(chip->regs))
327		return PTR_ERR(chip->regs);
328
329	ret = devm_gpiochip_add_data(dev, gc, chip);
330	if (ret)
331		return ret;
332
333	regs = chip->regs;
334	chip->shadow_gpioe = in_be32(&regs->simple_gpioe);
335	chip->shadow_ddr = in_be32(&regs->simple_ddr);
336	chip->shadow_dvo = in_be32(&regs->simple_dvo);
337
338	return 0;
339}
340
341static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
342	{ .compatible = "fsl,mpc5200-gpio", },
343	{}
344};
345
346static struct platform_driver mpc52xx_simple_gpiochip_driver = {
347	.driver = {
348		.name = "mpc5200-gpio",
349		.of_match_table = mpc52xx_simple_gpiochip_match,
350	},
351	.probe = mpc52xx_simple_gpiochip_probe,
352};
353
354static struct platform_driver * const drivers[] = {
355	&mpc52xx_wkup_gpiochip_driver,
356	&mpc52xx_simple_gpiochip_driver,
357};
358
359static int __init mpc52xx_gpio_init(void)
360{
361	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
362}
363
364/* Make sure we get initialised before anyone else tries to use us */
365subsys_initcall(mpc52xx_gpio_init);
366
367static void __exit mpc52xx_gpio_exit(void)
368{
369	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
370}
371module_exit(mpc52xx_gpio_exit);
372
373MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
374MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
375MODULE_LICENSE("GPL v2");
376
~/ Read-only file preview.