aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 02:29:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 02:29:20 -0500
commit4c4d285ad5665bfbd983b95fde8d7a477d24a361 (patch)
tree05da51053d4c8943ae21ea0b152aef4c67eba19d /drivers/sh
parent56c8bc3b7ed3d24c665e2ce992f86a5bedffc852 (diff)
parente64e1b11b14d363ac70fd13ab809969a6d7e42a8 (diff)
Merge tag 'rmobile-for-linus' of git://github.com/pmundt/linux-sh
SH/R-Mobile updates for 3.3 merge window. * tag 'rmobile-for-linus' of git://github.com/pmundt/linux-sh: (32 commits) arm: mach-shmobile: add a resource name for shdma ARM: mach-shmobile: r8a7779 SMP support V3 ARM: mach-shmobile: Add kota2 defconfig. ARM: mach-shmobile: Add marzen defconfig. ARM: mach-shmobile: r8a7779 power domain support V2 ARM: mach-shmobile: Fix up marzen build for recent GIC changes. ARM: mach-shmobile: r8a7779 PFC function support ARM: mach-shmobile: Flush caches in platform_cpu_die() ARM: mach-shmobile: Allow SoC specific CPU kill code ARM: mach-shmobile: Fix headsmp.S code to use CPUINIT ARM: mach-shmobile: clock-r8a7779: clkz/clkzs support ARM: mach-shmobile: clock-r8a7779: add DIV4 clock support ARM: mach-shmobile: Marzen LAN89218 support ARM: mach-shmobile: Marzen SCIF2/SCIF4 support ARM: mach-shmobile: r8a7779 PFC GPIO-only support V2 ARM: mach-shmobile: r8a7779 and Marzen base support V2 sh: pfc: Unlock register support sh: pfc: Variable bitfield width config register support sh: pfc: Add config_reg_helper() function sh: pfc: Convert index to field and value pair ...
Diffstat (limited to 'drivers/sh')
-rw-r--r--drivers/sh/pfc.c176
1 files changed, 94 insertions, 82 deletions
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index e7d127a9c1c..522c6c46d1b 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -135,6 +135,19 @@ static void gpio_write_raw_reg(void __iomem *mapped_reg,
135 BUG(); 135 BUG();
136} 136}
137 137
138static int gpio_read_bit(struct pinmux_data_reg *dr,
139 unsigned long in_pos)
140{
141 unsigned long pos;
142
143 pos = dr->reg_width - (in_pos + 1);
144
145 pr_debug("read_bit: addr = %lx, pos = %ld, "
146 "r_width = %ld\n", dr->reg, pos, dr->reg_width);
147
148 return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
149}
150
138static void gpio_write_bit(struct pinmux_data_reg *dr, 151static void gpio_write_bit(struct pinmux_data_reg *dr,
139 unsigned long in_pos, unsigned long value) 152 unsigned long in_pos, unsigned long value)
140{ 153{
@@ -154,51 +167,69 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
154 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);
155} 168}
156 169
157static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width, 170static void config_reg_helper(struct pinmux_info *gpioc,
158 unsigned long field_width, unsigned long in_pos, 171 struct pinmux_cfg_reg *crp,
159 unsigned long reg) 172 unsigned long in_pos,
173 void __iomem **mapped_regp,
174 unsigned long *maskp,
175 unsigned long *posp)
160{ 176{
161 unsigned long data, mask, pos; 177 int k;
162 178
163 data = 0; 179 *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
164 mask = (1 << field_width) - 1;
165 pos = reg_width - ((in_pos + 1) * field_width);
166 180
167 pr_debug("read_reg: addr = %lx, pos = %ld, " 181 if (crp->field_width) {
182 *maskp = (1 << crp->field_width) - 1;
183 *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
184 } else {
185 *maskp = (1 << crp->var_field_width[in_pos]) - 1;
186 *posp = crp->reg_width;
187 for (k = 0; k <= in_pos; k++)
188 *posp -= crp->var_field_width[k];
189 }
190}
191
192static int read_config_reg(struct pinmux_info *gpioc,
193 struct pinmux_cfg_reg *crp,
194 unsigned long field)
195{
196 void __iomem *mapped_reg;
197 unsigned long mask, pos;
198
199 config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
200
201 pr_debug("read_reg: addr = %lx, field = %ld, "
168 "r_width = %ld, f_width = %ld\n", 202 "r_width = %ld, f_width = %ld\n",
169 reg, pos, reg_width, field_width); 203 crp->reg, field, crp->reg_width, crp->field_width);
170 204
171 data = gpio_read_raw_reg(mapped_reg, reg_width); 205 return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
172 return (data >> pos) & mask;
173} 206}
174 207
175static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width, 208static void write_config_reg(struct pinmux_info *gpioc,
176 unsigned long field_width, unsigned long in_pos, 209 struct pinmux_cfg_reg *crp,
177 unsigned long value, unsigned long reg) 210 unsigned long field, unsigned long value)
178{ 211{
179 unsigned long mask, pos; 212 void __iomem *mapped_reg;
213 unsigned long mask, pos, data;
180 214
181 mask = (1 << field_width) - 1; 215 config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
182 pos = reg_width - ((in_pos + 1) * field_width);
183 216
184 pr_debug("write_reg addr = %lx, value = %ld, pos = %ld, " 217 pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
185 "r_width = %ld, f_width = %ld\n", 218 "r_width = %ld, f_width = %ld\n",
186 reg, value, pos, reg_width, field_width); 219 crp->reg, value, field, crp->reg_width, crp->field_width);
187 220
188 mask = ~(mask << pos); 221 mask = ~(mask << pos);
189 value = value << pos; 222 value = value << pos;
190 223
191 switch (reg_width) { 224 data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
192 case 8: 225 data &= mask;
193 iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg); 226 data |= value;
194 break; 227
195 case 16: 228 if (gpioc->unlock_reg)
196 iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg); 229 gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
197 break; 230 32, ~data);
198 case 32: 231
199 iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg); 232 gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
200 break;
201 }
202} 233}
203 234
204static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) 235static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
@@ -274,12 +305,13 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
274} 305}
275 306
276static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, 307static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
277 struct pinmux_cfg_reg **crp, int *indexp, 308 struct pinmux_cfg_reg **crp,
309 int *fieldp, int *valuep,
278 unsigned long **cntp) 310 unsigned long **cntp)
279{ 311{
280 struct pinmux_cfg_reg *config_reg; 312 struct pinmux_cfg_reg *config_reg;
281 unsigned long r_width, f_width; 313 unsigned long r_width, f_width, curr_width, ncomb;
282 int k, n; 314 int k, m, n, pos, bit_pos;
283 315
284 k = 0; 316 k = 0;
285 while (1) { 317 while (1) {
@@ -290,13 +322,27 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
290 322
291 if (!r_width) 323 if (!r_width)
292 break; 324 break;
293 for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) { 325
294 if (config_reg->enum_ids[n] == enum_id) { 326 pos = 0;
295 *crp = config_reg; 327 m = 0;
296 *indexp = n; 328 for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
297 *cntp = &config_reg->cnt[n / (1 << f_width)]; 329 if (f_width)
298 return 0; 330 curr_width = f_width;
331 else
332 curr_width = config_reg->var_field_width[m];
333
334 ncomb = 1 << curr_width;
335 for (n = 0; n < ncomb; n++) {
336 if (config_reg->enum_ids[pos + n] == enum_id) {
337 *crp = config_reg;
338 *fieldp = m;
339 *valuep = n;
340 *cntp = &config_reg->cnt[m];
341 return 0;
342 }
299 } 343 }
344 pos += ncomb;
345 m++;
300 } 346 }
301 k++; 347 k++;
302 } 348 }
@@ -334,43 +380,6 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
334 return -1; 380 return -1;
335} 381}
336 382
337static void write_config_reg(struct pinmux_info *gpioc,
338 struct pinmux_cfg_reg *crp,
339 int index)
340{
341 unsigned long ncomb, pos, value;
342 void __iomem *mapped_reg;
343
344 ncomb = 1 << crp->field_width;
345 pos = index / ncomb;
346 value = index % ncomb;
347
348 mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
349
350 gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width,
351 pos, value, crp->reg);
352}
353
354static int check_config_reg(struct pinmux_info *gpioc,
355 struct pinmux_cfg_reg *crp,
356 int index)
357{
358 unsigned long ncomb, pos, value;
359 void __iomem *mapped_reg;
360
361 ncomb = 1 << crp->field_width;
362 pos = index / ncomb;
363 value = index % ncomb;
364
365 mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
366
367 if (gpio_read_reg(mapped_reg, crp->reg_width,
368 crp->field_width, pos, crp->reg) == value)
369 return 0;
370
371 return -1;
372}
373
374enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; 383enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
375 384
376static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, 385static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
@@ -379,7 +388,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
379 struct pinmux_cfg_reg *cr = NULL; 388 struct pinmux_cfg_reg *cr = NULL;
380 pinmux_enum_t enum_id; 389 pinmux_enum_t enum_id;
381 struct pinmux_range *range; 390 struct pinmux_range *range;
382 int in_range, pos, index; 391 int in_range, pos, field, value;
383 unsigned long *cntp; 392 unsigned long *cntp;
384 393
385 switch (pinmux_type) { 394 switch (pinmux_type) {
@@ -410,7 +419,8 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
410 419
411 pos = 0; 420 pos = 0;
412 enum_id = 0; 421 enum_id = 0;
413 index = 0; 422 field = 0;
423 value = 0;
414 while (1) { 424 while (1) {
415 pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id); 425 pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
416 if (pos <= 0) 426 if (pos <= 0)
@@ -457,17 +467,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
457 if (!in_range) 467 if (!in_range)
458 continue; 468 continue;
459 469
460 if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0) 470 if (get_config_reg(gpioc, enum_id, &cr,
471 &field, &value, &cntp) != 0)
461 goto out_err; 472 goto out_err;
462 473
463 switch (cfg_mode) { 474 switch (cfg_mode) {
464 case GPIO_CFG_DRYRUN: 475 case GPIO_CFG_DRYRUN:
465 if (!*cntp || !check_config_reg(gpioc, cr, index)) 476 if (!*cntp ||
477 (read_config_reg(gpioc, cr, field) != value))
466 continue; 478 continue;
467 break; 479 break;
468 480
469 case GPIO_CFG_REQ: 481 case GPIO_CFG_REQ:
470 write_config_reg(gpioc, cr, index); 482 write_config_reg(gpioc, cr, field, value);
471 *cntp = *cntp + 1; 483 *cntp = *cntp + 1;
472 break; 484 break;
473 485
@@ -644,7 +656,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
644 if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) 656 if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
645 return -EINVAL; 657 return -EINVAL;
646 658
647 return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg); 659 return gpio_read_bit(dr, bit);
648} 660}
649 661
650static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) 662static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)