diff options
author | Jamie Iles <jamie@jamieiles.com> | 2011-05-20 02:40:14 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-05-20 02:40:14 -0400 |
commit | 8467afec5f8137fd0c13121f8a38c99c54c913f6 (patch) | |
tree | b4a5c5d93f6be6dcbd9d2c39956757b037d00924 /drivers/gpio | |
parent | 61c4f2c81c61f73549928dfd9f3e8f26aa36a8cf (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.c | 136 |
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 | ||
64 | struct bgpio_chip { | 64 | struct 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 | ||
94 | static unsigned long bgpio_in(struct bgpio_chip *bgc) | 98 | static 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 | ||
111 | static void bgpio_out(struct bgpio_chip *bgc, void __iomem *reg, | 103 | static 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; | 108 | static 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); | 113 | static unsigned long bgpio_read16(void __iomem *reg) |
123 | return; | 114 | { |
115 | return __raw_readw(reg); | ||
116 | } | ||
117 | |||
118 | static void bgpio_write32(void __iomem *reg, unsigned long data) | ||
119 | { | ||
120 | __raw_writel(data, reg); | ||
121 | } | ||
122 | |||
123 | static 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: | 129 | static 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 | ||
134 | static unsigned long bgpio_read64(void __iomem *reg) | ||
135 | { | ||
136 | return __raw_readq(reg); | ||
137 | } | ||
138 | #endif /* BITS_PER_LONG >= 64 */ | ||
139 | |||
132 | static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) | 140 | static 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; | 145 | static 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 | ||
140 | static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) | 151 | static 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 | ||
147 | static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | 158 | static 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 | ||
184 | static int __devinit bgpio_probe(struct platform_device *pdev) | 195 | static 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 | |||
231 | static 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; |