diff options
author | Magnus Damm <damm@opensource.se> | 2011-12-13 11:00:55 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-08 19:33:52 -0500 |
commit | 18925e118b3b4d55b45711218cd3c3c4360e5cd1 (patch) | |
tree | 4cd9f84cc6f2343f3d97093976de1dc7be75bd2e | |
parent | ad4a07ff8da7147b391f1ff0034f313a8b9da9e5 (diff) |
sh: pfc: Add config_reg_helper() function
Add a helper function for shared config reg access
calculations. This allows us to reduce the amount
of duplicated code, and at the same time prepare
for a common place for future variable bitwidth
config reg support.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | drivers/sh/pfc.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c index 41e7c8f63b10..5481d19518f9 100644 --- a/drivers/sh/pfc.c +++ b/drivers/sh/pfc.c | |||
@@ -167,41 +167,52 @@ static void gpio_write_bit(struct pinmux_data_reg *dr, | |||
167 | gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); | 167 | gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); |
168 | } | 168 | } |
169 | 169 | ||
170 | static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width, | 170 | static void config_reg_helper(struct pinmux_info *gpioc, |
171 | unsigned long field_width, unsigned long in_pos, | 171 | struct pinmux_cfg_reg *crp, |
172 | unsigned long reg) | 172 | unsigned long in_pos, |
173 | void __iomem **mapped_regp, | ||
174 | unsigned long *maskp, | ||
175 | unsigned long *posp) | ||
173 | { | 176 | { |
174 | unsigned long data, mask, pos; | 177 | *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg); |
175 | 178 | ||
176 | data = 0; | 179 | *maskp = (1 << crp->field_width) - 1; |
177 | mask = (1 << field_width) - 1; | 180 | *posp = crp->reg_width - ((in_pos + 1) * crp->field_width); |
178 | pos = reg_width - ((in_pos + 1) * field_width); | 181 | } |
182 | |||
183 | static int read_config_reg(struct pinmux_info *gpioc, | ||
184 | struct pinmux_cfg_reg *crp, | ||
185 | unsigned long field) | ||
186 | { | ||
187 | void __iomem *mapped_reg; | ||
188 | unsigned long mask, pos; | ||
189 | |||
190 | config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos); | ||
179 | 191 | ||
180 | pr_debug("read_reg: addr = %lx, pos = %ld, " | 192 | pr_debug("read_reg: addr = %lx, field = %ld, " |
181 | "r_width = %ld, f_width = %ld\n", | 193 | "r_width = %ld, f_width = %ld\n", |
182 | reg, pos, reg_width, field_width); | 194 | crp->reg, field, crp->reg_width, crp->field_width); |
183 | 195 | ||
184 | data = gpio_read_raw_reg(mapped_reg, reg_width); | 196 | return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask; |
185 | return (data >> pos) & mask; | ||
186 | } | 197 | } |
187 | 198 | ||
188 | static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width, | 199 | static void write_config_reg(struct pinmux_info *gpioc, |
189 | unsigned long field_width, unsigned long in_pos, | 200 | struct pinmux_cfg_reg *crp, |
190 | unsigned long value, unsigned long reg) | 201 | unsigned long field, unsigned long value) |
191 | { | 202 | { |
203 | void __iomem *mapped_reg; | ||
192 | unsigned long mask, pos; | 204 | unsigned long mask, pos; |
193 | 205 | ||
194 | mask = (1 << field_width) - 1; | 206 | config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos); |
195 | pos = reg_width - ((in_pos + 1) * field_width); | ||
196 | 207 | ||
197 | pr_debug("write_reg addr = %lx, value = %ld, pos = %ld, " | 208 | pr_debug("write_reg addr = %lx, value = %ld, field = %ld, " |
198 | "r_width = %ld, f_width = %ld\n", | 209 | "r_width = %ld, f_width = %ld\n", |
199 | reg, value, pos, reg_width, field_width); | 210 | crp->reg, value, field, crp->reg_width, crp->field_width); |
200 | 211 | ||
201 | mask = ~(mask << pos); | 212 | mask = ~(mask << pos); |
202 | value = value << pos; | 213 | value = value << pos; |
203 | 214 | ||
204 | switch (reg_width) { | 215 | switch (crp->reg_width) { |
205 | case 8: | 216 | case 8: |
206 | iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg); | 217 | iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg); |
207 | break; | 218 | break; |
@@ -349,29 +360,6 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, | |||
349 | return -1; | 360 | return -1; |
350 | } | 361 | } |
351 | 362 | ||
352 | static void write_config_reg(struct pinmux_info *gpioc, | ||
353 | struct pinmux_cfg_reg *crp, | ||
354 | int field, int value) | ||
355 | { | ||
356 | void __iomem *mapped_reg = pfc_phys_to_virt(gpioc, crp->reg); | ||
357 | |||
358 | gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width, | ||
359 | field, value, crp->reg); | ||
360 | } | ||
361 | |||
362 | static int check_config_reg(struct pinmux_info *gpioc, | ||
363 | struct pinmux_cfg_reg *crp, | ||
364 | int field, int value) | ||
365 | { | ||
366 | void __iomem *mapped_reg = pfc_phys_to_virt(gpioc, crp->reg); | ||
367 | |||
368 | if (gpio_read_reg(mapped_reg, crp->reg_width, | ||
369 | crp->field_width, field, crp->reg) == value) | ||
370 | return 0; | ||
371 | |||
372 | return -1; | ||
373 | } | ||
374 | |||
375 | enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; | 363 | enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; |
376 | 364 | ||
377 | static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | 365 | static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, |
@@ -465,8 +453,8 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | |||
465 | 453 | ||
466 | switch (cfg_mode) { | 454 | switch (cfg_mode) { |
467 | case GPIO_CFG_DRYRUN: | 455 | case GPIO_CFG_DRYRUN: |
468 | if (!*cntp || !check_config_reg(gpioc, cr, | 456 | if (!*cntp || |
469 | field, value)) | 457 | (read_config_reg(gpioc, cr, field) != value)) |
470 | continue; | 458 | continue; |
471 | break; | 459 | break; |
472 | 460 | ||