1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Simple Memory-Mapped GPIOs
4  *
5  * Copyright (c) MontaVista Software, Inc. 2008.
6  *
7  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
8  */
9 
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/types.h>
14 #include <linux/ioport.h>
15 #include <linux/io.h>
16 #include <linux/of.h>
17 #include <linux/of_gpio.h>
18 #include <linux/gpio/driver.h>
19 #include <linux/slab.h>
20 #include <asm/prom.h>
21 #include "simple_gpio.h"
22 
23 struct u8_gpio_chip {
24 	struct of_mm_gpio_chip mm_gc;
25 	spinlock_t lock;
26 
27 	/* shadowed data register to clear/set bits safely */
28 	u8 data;
29 };
30 
u8_pin2mask(unsigned int pin)31 static u8 u8_pin2mask(unsigned int pin)
32 {
33 	return 1 << (8 - 1 - pin);
34 }
35 
u8_gpio_get(struct gpio_chip * gc,unsigned int gpio)36 static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio)
37 {
38 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
39 
40 	return !!(in_8(mm_gc->regs) & u8_pin2mask(gpio));
41 }
42 
u8_gpio_set(struct gpio_chip * gc,unsigned int gpio,int val)43 static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
44 {
45 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
46 	struct u8_gpio_chip *u8_gc = gpiochip_get_data(gc);
47 	unsigned long flags;
48 
49 	spin_lock_irqsave(&u8_gc->lock, flags);
50 
51 	if (val)
52 		u8_gc->data |= u8_pin2mask(gpio);
53 	else
54 		u8_gc->data &= ~u8_pin2mask(gpio);
55 
56 	out_8(mm_gc->regs, u8_gc->data);
57 
58 	spin_unlock_irqrestore(&u8_gc->lock, flags);
59 }
60 
u8_gpio_dir_in(struct gpio_chip * gc,unsigned int gpio)61 static int u8_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
62 {
63 	return 0;
64 }
65 
u8_gpio_dir_out(struct gpio_chip * gc,unsigned int gpio,int val)66 static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
67 {
68 	u8_gpio_set(gc, gpio, val);
69 	return 0;
70 }
71 
u8_gpio_save_regs(struct of_mm_gpio_chip * mm_gc)72 static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
73 {
74 	struct u8_gpio_chip *u8_gc =
75 		container_of(mm_gc, struct u8_gpio_chip, mm_gc);
76 
77 	u8_gc->data = in_8(mm_gc->regs);
78 }
79 
u8_simple_gpiochip_add(struct device_node * np)80 static int __init u8_simple_gpiochip_add(struct device_node *np)
81 {
82 	int ret;
83 	struct u8_gpio_chip *u8_gc;
84 	struct of_mm_gpio_chip *mm_gc;
85 	struct gpio_chip *gc;
86 
87 	u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL);
88 	if (!u8_gc)
89 		return -ENOMEM;
90 
91 	spin_lock_init(&u8_gc->lock);
92 
93 	mm_gc = &u8_gc->mm_gc;
94 	gc = &mm_gc->gc;
95 
96 	mm_gc->save_regs = u8_gpio_save_regs;
97 	gc->ngpio = 8;
98 	gc->direction_input = u8_gpio_dir_in;
99 	gc->direction_output = u8_gpio_dir_out;
100 	gc->get = u8_gpio_get;
101 	gc->set = u8_gpio_set;
102 
103 	ret = of_mm_gpiochip_add_data(np, mm_gc, u8_gc);
104 	if (ret)
105 		goto err;
106 	return 0;
107 err:
108 	kfree(u8_gc);
109 	return ret;
110 }
111 
simple_gpiochip_init(const char * compatible)112 void __init simple_gpiochip_init(const char *compatible)
113 {
114 	struct device_node *np;
115 
116 	for_each_compatible_node(np, NULL, compatible) {
117 		int ret;
118 		struct resource r;
119 
120 		ret = of_address_to_resource(np, 0, &r);
121 		if (ret)
122 			goto err;
123 
124 		switch (resource_size(&r)) {
125 		case 1:
126 			ret = u8_simple_gpiochip_add(np);
127 			if (ret)
128 				goto err;
129 			break;
130 		default:
131 			/*
132 			 * Whenever you need support for GPIO bank width > 1,
133 			 * please just turn u8_ code into huge macros, and
134 			 * construct needed uX_ code with it.
135 			 */
136 			ret = -ENOSYS;
137 			goto err;
138 		}
139 		continue;
140 err:
141 		pr_err("%pOF: registration failed, status %d\n", np, ret);
142 	}
143 }
144