Blame view

drivers/gpio/gpio-xilinx.c 7.01 KB
0bcb6069a   John Linn   GPIO: add new Xil...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  /*
   * Xilinx gpio driver
   *
   * Copyright 2008 Xilinx, Inc.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2
   * as published by the Free Software Foundation.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  #include <linux/init.h>
  #include <linux/errno.h>
  #include <linux/of_device.h>
  #include <linux/of_platform.h>
  #include <linux/of_gpio.h>
  #include <linux/io.h>
  #include <linux/gpio.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
0bcb6069a   John Linn   GPIO: add new Xil...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  
  /* Register Offset Definitions */
  #define XGPIO_DATA_OFFSET   (0x0)	/* Data register  */
  #define XGPIO_TRI_OFFSET    (0x4)	/* I/O direction register  */
  
  struct xgpio_instance {
  	struct of_mm_gpio_chip mmchip;
  	u32 gpio_state;		/* GPIO state shadow register */
  	u32 gpio_dir;		/* GPIO direction shadow register */
  	spinlock_t gpio_lock;	/* Lock used for synchronization */
  };
  
  /**
   * xgpio_get - Read the specified signal of the GPIO device.
   * @gc:     Pointer to gpio_chip device structure.
   * @gpio:   GPIO signal number.
   *
   * This function reads the specified signal of the GPIO device. It returns 0 if
   * the signal clear, 1 if signal is set or negative value on error.
   */
  static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
  {
  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
  
  	return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
  }
  
  /**
   * xgpio_set - Write the specified signal of the GPIO device.
   * @gc:     Pointer to gpio_chip device structure.
   * @gpio:   GPIO signal number.
   * @val:    Value to be written to specified signal.
   *
   * This function writes the specified value in to the specified signal of the
   * GPIO device.
   */
  static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
  {
  	unsigned long flags;
  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
  	struct xgpio_instance *chip =
  	    container_of(mm_gc, struct xgpio_instance, mmchip);
  
  	spin_lock_irqsave(&chip->gpio_lock, flags);
  
  	/* Write to GPIO signal and set its direction to output */
  	if (val)
  		chip->gpio_state |= 1 << gpio;
  	else
  		chip->gpio_state &= ~(1 << gpio);
  	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
  
  	spin_unlock_irqrestore(&chip->gpio_lock, flags);
  }
  
  /**
   * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
   * @gc:     Pointer to gpio_chip device structure.
   * @gpio:   GPIO signal number.
   *
   * This function sets the direction of specified GPIO signal as input.
   * It returns 0 if direction of GPIO signals is set as input otherwise it
   * returns negative error value.
   */
  static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
  {
  	unsigned long flags;
  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
  	struct xgpio_instance *chip =
  	    container_of(mm_gc, struct xgpio_instance, mmchip);
  
  	spin_lock_irqsave(&chip->gpio_lock, flags);
  
  	/* Set the GPIO bit in shadow register and set direction as input */
  	chip->gpio_dir |= (1 << gpio);
  	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
  
  	spin_unlock_irqrestore(&chip->gpio_lock, flags);
  
  	return 0;
  }
  
  /**
   * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
   * @gc:     Pointer to gpio_chip device structure.
   * @gpio:   GPIO signal number.
   * @val:    Value to be written to specified signal.
   *
   * This function sets the direction of specified GPIO signal as output. If all
   * GPIO signals of GPIO chip is configured as input then it returns
   * error otherwise it returns 0.
   */
  static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
  {
  	unsigned long flags;
  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
  	struct xgpio_instance *chip =
  	    container_of(mm_gc, struct xgpio_instance, mmchip);
  
  	spin_lock_irqsave(&chip->gpio_lock, flags);
  
  	/* Write state of GPIO signal */
  	if (val)
  		chip->gpio_state |= 1 << gpio;
  	else
  		chip->gpio_state &= ~(1 << gpio);
  	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
  
  	/* Clear the GPIO bit in shadow register and set direction as output */
  	chip->gpio_dir &= (~(1 << gpio));
  	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
  
  	spin_unlock_irqrestore(&chip->gpio_lock, flags);
  
  	return 0;
  }
  
  /**
   * xgpio_save_regs - Set initial values of GPIO pins
   * @mm_gc: pointer to memory mapped GPIO chip structure
   */
  static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
  {
  	struct xgpio_instance *chip =
  	    container_of(mm_gc, struct xgpio_instance, mmchip);
  
  	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
  	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
  }
  
  /**
   * xgpio_of_probe - Probe method for the GPIO device.
   * @np: pointer to device tree node
   *
   * This function probes the GPIO device in the device tree. It initializes the
   * driver data structure. It returns 0, if the driver is bound to the GPIO
   * device, or a negative value if there is an error.
   */
  static int __devinit xgpio_of_probe(struct device_node *np)
  {
  	struct xgpio_instance *chip;
0bcb6069a   John Linn   GPIO: add new Xil...
164
165
166
167
168
169
  	int status = 0;
  	const u32 *tree_info;
  
  	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
  	if (!chip)
  		return -ENOMEM;
0bcb6069a   John Linn   GPIO: add new Xil...
170
171
172
173
  
  	/* Update GPIO state shadow register with default value */
  	tree_info = of_get_property(np, "xlnx,dout-default", NULL);
  	if (tree_info)
a04e78b85   Michal Simek   of: GPIO: Fix OF ...
174
  		chip->gpio_state = be32_to_cpup(tree_info);
0bcb6069a   John Linn   GPIO: add new Xil...
175
176
177
178
179
  
  	/* Update GPIO direction shadow register with default value */
  	chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
  	tree_info = of_get_property(np, "xlnx,tri-default", NULL);
  	if (tree_info)
a04e78b85   Michal Simek   of: GPIO: Fix OF ...
180
  		chip->gpio_dir = be32_to_cpup(tree_info);
0bcb6069a   John Linn   GPIO: add new Xil...
181
182
  
  	/* Check device node and parent device node for device width */
a19e3da5b   Anton Vorontsov   of/gpio: Kill of_...
183
  	chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
0bcb6069a   John Linn   GPIO: add new Xil...
184
185
186
187
188
  	tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
  	if (!tree_info)
  		tree_info = of_get_property(np->parent,
  					    "xlnx,gpio-width", NULL);
  	if (tree_info)
a04e78b85   Michal Simek   of: GPIO: Fix OF ...
189
  		chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
0bcb6069a   John Linn   GPIO: add new Xil...
190
191
  
  	spin_lock_init(&chip->gpio_lock);
a19e3da5b   Anton Vorontsov   of/gpio: Kill of_...
192
193
194
195
  	chip->mmchip.gc.direction_input = xgpio_dir_in;
  	chip->mmchip.gc.direction_output = xgpio_dir_out;
  	chip->mmchip.gc.get = xgpio_get;
  	chip->mmchip.gc.set = xgpio_set;
0bcb6069a   John Linn   GPIO: add new Xil...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  
  	chip->mmchip.save_regs = xgpio_save_regs;
  
  	/* Call the OF gpio helper to setup and register the GPIO device */
  	status = of_mm_gpiochip_add(np, &chip->mmchip);
  	if (status) {
  		kfree(chip);
  		pr_err("%s: error in probe function with status %d
  ",
  		       np->full_name, status);
  		return status;
  	}
  	pr_info("XGpio: %s: registered
  ", np->full_name);
  	return 0;
  }
  
  static struct of_device_id xgpio_of_match[] __devinitdata = {
  	{ .compatible = "xlnx,xps-gpio-1.00.a", },
  	{ /* end of list */ },
  };
  
  static int __init xgpio_init(void)
  {
  	struct device_node *np;
  
  	for_each_matching_node(np, xgpio_of_match)
  		xgpio_of_probe(np);
  
  	return 0;
  }
  
  /* Make sure we get initialized before anyone else tries to use us */
  subsys_initcall(xgpio_init);
  /* No exit call at the moment as we cannot unregister of GPIO chips */
  
  MODULE_AUTHOR("Xilinx, Inc.");
  MODULE_DESCRIPTION("Xilinx GPIO driver");
  MODULE_LICENSE("GPL");