aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorJamie Iles <jamie@jamieiles.com>2011-05-20 02:40:14 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-05-20 02:40:14 -0400
commit8467afec5f8137fd0c13121f8a38c99c54c913f6 (patch)
treeb4a5c5d93f6be6dcbd9d2c39956757b037d00924 /drivers/gpio
parent61c4f2c81c61f73549928dfd9f3e8f26aa36a8cf (diff)
basic_mmio_gpio: remove runtime width/endianness evaluation
Remove endianness/width calculations at runtime by installing function pointers for bit-to-mask conversion and register accessors. Reported-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Jamie Iles <jamie@jamieiles.com> Acked-by: Anton Vorontsov <cbouatmailru@gmail.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/basic_mmio_gpio.c136
1 files changed, 92 insertions, 44 deletions
diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/basic_mmio_gpio.c
index 3addea65894e..e935a24f7d29 100644
--- a/drivers/gpio/basic_mmio_gpio.c
+++ b/drivers/gpio/basic_mmio_gpio.c
@@ -63,6 +63,10 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
63 63
64struct bgpio_chip { 64struct bgpio_chip {
65 struct gpio_chip gc; 65 struct gpio_chip gc;
66
67 unsigned long (*read_reg)(void __iomem *reg);
68 void (*write_reg)(void __iomem *reg, unsigned long data);
69
66 void __iomem *reg_dat; 70 void __iomem *reg_dat;
67 void __iomem *reg_set; 71 void __iomem *reg_set;
68 void __iomem *reg_clr; 72 void __iomem *reg_clr;
@@ -74,7 +78,7 @@ struct bgpio_chip {
74 * Some GPIO controllers work with the big-endian bits notation, 78 * Some GPIO controllers work with the big-endian bits notation,
75 * e.g. in a 8-bits register, GPIO7 is the least significant bit. 79 * e.g. in a 8-bits register, GPIO7 is the least significant bit.
76 */ 80 */
77 int big_endian_bits; 81 unsigned long (*pin2mask)(struct bgpio_chip *bgc, unsigned int pin);
78 82
79 /* 83 /*
80 * Used to lock bgpio_chip->data. Also, this is needed to keep 84 * Used to lock bgpio_chip->data. Also, this is needed to keep
@@ -91,70 +95,77 @@ static struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc)
91 return container_of(gc, struct bgpio_chip, gc); 95 return container_of(gc, struct bgpio_chip, gc);
92} 96}
93 97
94static unsigned long bgpio_in(struct bgpio_chip *bgc) 98static void bgpio_write8(void __iomem *reg, unsigned long data)
95{ 99{
96 switch (bgc->bits) { 100 __raw_writeb(data, reg);
97 case 8:
98 return __raw_readb(bgc->reg_dat);
99 case 16:
100 return __raw_readw(bgc->reg_dat);
101 case 32:
102 return __raw_readl(bgc->reg_dat);
103#if BITS_PER_LONG >= 64
104 case 64:
105 return __raw_readq(bgc->reg_dat);
106#endif
107 }
108 return -EINVAL;
109} 101}
110 102
111static void bgpio_out(struct bgpio_chip *bgc, void __iomem *reg, 103static unsigned long bgpio_read8(void __iomem *reg)
112 unsigned long data)
113{ 104{
114 switch (bgc->bits) { 105 return __raw_readb(reg);
115 case 8: 106}
116 __raw_writeb(data, reg); 107
117 return; 108static void bgpio_write16(void __iomem *reg, unsigned long data)
118 case 16: 109{
119 __raw_writew(data, reg); 110 __raw_writew(data, reg);
120 return; 111}
121 case 32: 112
122 __raw_writel(data, reg); 113static unsigned long bgpio_read16(void __iomem *reg)
123 return; 114{
115 return __raw_readw(reg);
116}
117
118static void bgpio_write32(void __iomem *reg, unsigned long data)
119{
120 __raw_writel(data, reg);
121}
122
123static unsigned long bgpio_read32(void __iomem *reg)
124{
125 return __raw_readl(reg);
126}
127
124#if BITS_PER_LONG >= 64 128#if BITS_PER_LONG >= 64
125 case 64: 129static void bgpio_write64(void __iomem *reg, unsigned long data)
126 __raw_writeq(data, reg); 130{
127 return; 131 __raw_writeq(data, reg);
128#endif
129 }
130} 132}
131 133
134static unsigned long bgpio_read64(void __iomem *reg)
135{
136 return __raw_readq(reg);
137}
138#endif /* BITS_PER_LONG >= 64 */
139
132static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) 140static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
133{ 141{
134 if (bgc->big_endian_bits) 142 return 1 << pin;
135 return 1 << (bgc->bits - 1 - pin); 143}
136 else 144
137 return 1 << pin; 145static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc,
146 unsigned int pin)
147{
148 return 1 << (bgc->bits - 1 - pin);
138} 149}
139 150
140static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) 151static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
141{ 152{
142 struct bgpio_chip *bgc = to_bgpio_chip(gc); 153 struct bgpio_chip *bgc = to_bgpio_chip(gc);
143 154
144 return bgpio_in(bgc) & bgpio_pin2mask(bgc, gpio); 155 return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
145} 156}
146 157
147static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 158static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
148{ 159{
149 struct bgpio_chip *bgc = to_bgpio_chip(gc); 160 struct bgpio_chip *bgc = to_bgpio_chip(gc);
150 unsigned long mask = bgpio_pin2mask(bgc, gpio); 161 unsigned long mask = bgc->pin2mask(bgc, gpio);
151 unsigned long flags; 162 unsigned long flags;
152 163
153 if (bgc->reg_set) { 164 if (bgc->reg_set) {
154 if (val) 165 if (val)
155 bgpio_out(bgc, bgc->reg_set, mask); 166 bgc->write_reg(bgc->reg_set, mask);
156 else 167 else
157 bgpio_out(bgc, bgc->reg_clr, mask); 168 bgc->write_reg(bgc->reg_clr, mask);
158 return; 169 return;
159 } 170 }
160 171
@@ -165,7 +176,7 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
165 else 176 else
166 bgc->data &= ~mask; 177 bgc->data &= ~mask;
167 178
168 bgpio_out(bgc, bgc->reg_dat, bgc->data); 179 bgc->write_reg(bgc->reg_dat, bgc->data);
169 180
170 spin_unlock_irqrestore(&bgc->lock, flags); 181 spin_unlock_irqrestore(&bgc->lock, flags);
171} 182}
@@ -181,9 +192,44 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
181 return 0; 192 return 0;
182} 193}
183 194
184static int __devinit bgpio_probe(struct platform_device *pdev) 195static int bgpio_setup_accessors(struct platform_device *pdev,
196 struct bgpio_chip *bgc)
185{ 197{
186 const struct platform_device_id *platid = platform_get_device_id(pdev); 198 const struct platform_device_id *platid = platform_get_device_id(pdev);
199
200 switch (bgc->bits) {
201 case 8:
202 bgc->read_reg = bgpio_read8;
203 bgc->write_reg = bgpio_write8;
204 break;
205 case 16:
206 bgc->read_reg = bgpio_read16;
207 bgc->write_reg = bgpio_write16;
208 break;
209 case 32:
210 bgc->read_reg = bgpio_read32;
211 bgc->write_reg = bgpio_write32;
212 break;
213#if BITS_PER_LONG >= 64
214 case 64:
215 bgc->read_reg = bgpio_read64;
216 bgc->write_reg = bgpio_write64;
217 break;
218#endif /* BITS_PER_LONG >= 64 */
219 default:
220 dev_err(&pdev->dev, "unsupported data width %u bits\n",
221 bgc->bits);
222 return -EINVAL;
223 }
224
225 bgc->pin2mask = strcmp(platid->name, "basic-mmio-gpio-be") ?
226 bgpio_pin2mask : bgpio_pin2mask_be;
227
228 return 0;
229}
230
231static int __devinit bgpio_probe(struct platform_device *pdev)
232{
187 struct device *dev = &pdev->dev; 233 struct device *dev = &pdev->dev;
188 struct bgpio_pdata *pdata = dev_get_platdata(dev); 234 struct bgpio_pdata *pdata = dev_get_platdata(dev);
189 struct bgpio_chip *bgc; 235 struct bgpio_chip *bgc;
@@ -232,9 +278,11 @@ static int __devinit bgpio_probe(struct platform_device *pdev)
232 spin_lock_init(&bgc->lock); 278 spin_lock_init(&bgc->lock);
233 279
234 bgc->bits = bits; 280 bgc->bits = bits;
235 bgc->big_endian_bits = !strcmp(platid->name, "basic-mmio-gpio-be"); 281 ret = bgpio_setup_accessors(pdev, bgc);
236 bgc->data = bgpio_in(bgc); 282 if (ret)
283 return ret;
237 284
285 bgc->data = bgc->read_reg(bgc->reg_dat);
238 bgc->gc.ngpio = bits; 286 bgc->gc.ngpio = bits;
239 bgc->gc.direction_input = bgpio_dir_in; 287 bgc->gc.direction_input = bgpio_dir_in;
240 bgc->gc.direction_output = bgpio_dir_out; 288 bgc->gc.direction_output = bgpio_dir_out;