Blame view

arch/powerpc/platforms/86xx/gef_gpio.c 4.43 KB
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
1
  /*
948e78c3f   Martyn Welch   powerpc/86xx: Ren...
2
   * Driver for GE FPGA based GPIO
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
3
   *
948e78c3f   Martyn Welch   powerpc/86xx: Ren...
4
   * Author: Martyn Welch <martyn.welch@ge.com>
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
5
   *
948e78c3f   Martyn Welch   powerpc/86xx: Ren...
6
   * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   *
   * This file is licensed under the terms of the GNU General Public License
   * version 2.  This program is licensed "as is" without any warranty of any
   * kind, whether express or implied.
   */
  
  /* TODO
   *
   * Configuration of output modes (totem-pole/open-drain)
   * Interrupt configuration - interrupts are always generated the FPGA relies on
   * 	the I/O interrupt controllers mask to stop them propergating
   */
  
  #include <linux/kernel.h>
  #include <linux/compiler.h>
  #include <linux/init.h>
  #include <linux/io.h>
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/of_platform.h>
  #include <linux/of_gpio.h>
  #include <linux/gpio.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
29
  #include <linux/slab.h>
7dfe293cf   Paul Gortmaker   powerpc: Fix up m...
30
  #include <linux/module.h>
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
31
32
33
34
35
36
37
38
39
40
  
  #define GEF_GPIO_DIRECT		0x00
  #define GEF_GPIO_IN		0x04
  #define GEF_GPIO_OUT		0x08
  #define GEF_GPIO_TRIG		0x0C
  #define GEF_GPIO_POLAR_A	0x10
  #define GEF_GPIO_POLAR_B	0x14
  #define GEF_GPIO_INT_STAT	0x18
  #define GEF_GPIO_OVERRUN	0x1C
  #define GEF_GPIO_MODE		0x20
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
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
  static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
  {
  	unsigned int data;
  
  	data = ioread32be(reg);
  	/* value: 0=low; 1=high */
  	if (value & 0x1)
  		data = data | (0x1 << offset);
  	else
  		data = data & ~(0x1 << offset);
  
  	iowrite32be(data, reg);
  }
  
  
  static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
  {
  	unsigned int data;
  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  
  	data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
  	data = data | (0x1 << offset);
  	iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
  
  	return 0;
  }
  
  static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
  {
  	unsigned int data;
  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  
  	/* Set direction before switching to input */
  	_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
  
  	data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
  	data = data & ~(0x1 << offset);
  	iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
  
  	return 0;
  }
  
  static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
  {
  	unsigned int data;
  	int state = 0;
  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  
  	data = ioread32be(mmchip->regs + GEF_GPIO_IN);
  	state = (int)((data >> offset) & 0x1);
  
  	return state;
  }
  
  static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  {
  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
  
  	_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
  }
  
  static int __init gef_gpio_init(void)
  {
  	struct device_node *np;
b1dd62f7f   Martyn Welch   powerpc/86xx: Ext...
105
106
  	int retval;
  	struct of_mm_gpio_chip *gef_gpio_chip;
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
107
108
  
  	for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  
  		pr_debug("%s: Initialising GEF GPIO
  ", np->full_name);
  
  		/* Allocate chip structure */
  		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
  		if (!gef_gpio_chip) {
  			pr_err("%s: Unable to allocate structure
  ",
  				np->full_name);
  			continue;
  		}
  
  		/* Setup pointers to chip functions */
a19e3da5b   Anton Vorontsov   of/gpio: Kill of_...
123
124
125
126
127
128
  		gef_gpio_chip->gc.of_gpio_n_cells = 2;
  		gef_gpio_chip->gc.ngpio = 19;
  		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
  		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
  		gef_gpio_chip->gc.get = gef_gpio_get;
  		gef_gpio_chip->gc.set = gef_gpio_set;
b1dd62f7f   Martyn Welch   powerpc/86xx: Ext...
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
  
  		/* This function adds a memory mapped GPIO chip */
  		retval = of_mm_gpiochip_add(np, gef_gpio_chip);
  		if (retval) {
  			kfree(gef_gpio_chip);
  			pr_err("%s: Unable to add GPIO
  ", np->full_name);
  		}
  	}
  
  	for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
  
  		pr_debug("%s: Initialising GEF GPIO
  ", np->full_name);
  
  		/* Allocate chip structure */
  		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
  		if (!gef_gpio_chip) {
  			pr_err("%s: Unable to allocate structure
  ",
  				np->full_name);
  			continue;
  		}
  
  		/* Setup pointers to chip functions */
a19e3da5b   Anton Vorontsov   of/gpio: Kill of_...
154
155
156
157
158
159
  		gef_gpio_chip->gc.of_gpio_n_cells = 2;
  		gef_gpio_chip->gc.ngpio = 6;
  		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
  		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
  		gef_gpio_chip->gc.get = gef_gpio_get;
  		gef_gpio_chip->gc.set = gef_gpio_set;
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
160
161
162
163
164
165
166
167
168
169
170
171
172
  
  		/* This function adds a memory mapped GPIO chip */
  		retval = of_mm_gpiochip_add(np, gef_gpio_chip);
  		if (retval) {
  			kfree(gef_gpio_chip);
  			pr_err("%s: Unable to add GPIO
  ", np->full_name);
  		}
  	}
  
  	return 0;
  };
  arch_initcall(gef_gpio_init);
948e78c3f   Martyn Welch   powerpc/86xx: Ren...
173
174
  MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
  MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
965dc5fc5   Martyn Welch   powerpc/86xx: Bas...
175
  MODULE_LICENSE("GPL");