aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-12-13 11:00:55 -0500
committerPaul Mundt <lethal@linux-sh.org>2012-01-08 19:33:52 -0500
commit18925e118b3b4d55b45711218cd3c3c4360e5cd1 (patch)
tree4cd9f84cc6f2343f3d97093976de1dc7be75bd2e
parentad4a07ff8da7147b391f1ff0034f313a8b9da9e5 (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.c76
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
170static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width, 170static 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
183static 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
188static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width, 199static 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
352static 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
362static 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
375enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; 363enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
376 364
377static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, 365static 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