aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2008-12-25 04:17:09 -0500
committerPaul Mundt <lethal@linux-sh.org>2009-01-27 00:49:09 -0500
commit18801be7f805b891876a6676ec7fac2e1acdec13 (patch)
tree71b4366a89ac25980dc16bc1b33fbc6943f1155c /arch/sh
parent5376071069ec8a7e6a8112beab16fc24f5139475 (diff)
sh: make gpio_get/set_value() O(1)
This patch modifies the table based SuperH gpio implementation to make use of direct table lookups. With this change the functions gpio_get_value() and gpio_set_value() are O(1). Tested on Migo-R using bitbanging mmc. Performance is improved from 11 KBytes/s to 26 Kbytes/s. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/gpio.h7
-rw-r--r--arch/sh/kernel/gpio.c48
2 files changed, 43 insertions, 12 deletions
diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h
index 90673658eb14..942fefa61c7e 100644
--- a/arch/sh/include/asm/gpio.h
+++ b/arch/sh/include/asm/gpio.h
@@ -20,7 +20,7 @@
20#endif 20#endif
21 21
22typedef unsigned short pinmux_enum_t; 22typedef unsigned short pinmux_enum_t;
23typedef unsigned char pinmux_flag_t; 23typedef unsigned short pinmux_flag_t;
24 24
25#define PINMUX_TYPE_NONE 0 25#define PINMUX_TYPE_NONE 0
26#define PINMUX_TYPE_FUNCTION 1 26#define PINMUX_TYPE_FUNCTION 1
@@ -34,6 +34,11 @@ typedef unsigned char pinmux_flag_t;
34#define PINMUX_FLAG_WANT_PULLUP (1 << 3) 34#define PINMUX_FLAG_WANT_PULLUP (1 << 3)
35#define PINMUX_FLAG_WANT_PULLDOWN (1 << 4) 35#define PINMUX_FLAG_WANT_PULLDOWN (1 << 4)
36 36
37#define PINMUX_FLAG_DBIT_SHIFT 5
38#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT)
39#define PINMUX_FLAG_DREG_SHIFT 10
40#define PINMUX_FLAG_DREG (0x3f << PINMUX_FLAG_DREG_SHIFT)
41
37struct pinmux_gpio { 42struct pinmux_gpio {
38 pinmux_enum_t enum_id; 43 pinmux_enum_t enum_id;
39 pinmux_flag_t flags; 44 pinmux_flag_t flags;
diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c
index d37165361034..fe92ba151b89 100644
--- a/arch/sh/kernel/gpio.c
+++ b/arch/sh/kernel/gpio.c
@@ -95,14 +95,13 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width,
95 return 0; 95 return 0;
96} 96}
97 97
98static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, 98static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
99 struct pinmux_data_reg **drp, int *bitp)
100{ 99{
101 pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; 100 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
102 struct pinmux_data_reg *data_reg; 101 struct pinmux_data_reg *data_reg;
103 int k, n; 102 int k, n;
104 103
105 if (!enum_in_range(enum_id, &gpioc->data)) 104 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
106 return -1; 105 return -1;
107 106
108 k = 0; 107 k = 0;
@@ -113,19 +112,38 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
113 break; 112 break;
114 113
115 for (n = 0; n < data_reg->reg_width; n++) { 114 for (n = 0; n < data_reg->reg_width; n++) {
116 if (data_reg->enum_ids[n] == enum_id) { 115 if (data_reg->enum_ids[n] == gpiop->enum_id) {
117 *drp = data_reg; 116 gpiop->flags &= ~PINMUX_FLAG_DREG;
118 *bitp = n; 117 gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
118 gpiop->flags &= ~PINMUX_FLAG_DBIT;
119 gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
119 return 0; 120 return 0;
120
121 } 121 }
122 } 122 }
123 k++; 123 k++;
124 } 124 }
125 125
126 BUG();
127
126 return -1; 128 return -1;
127} 129}
128 130
131static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
132 struct pinmux_data_reg **drp, int *bitp)
133{
134 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
135 int k, n;
136
137 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
138 return -1;
139
140 k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
141 n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
142 *drp = gpioc->data_regs + k;
143 *bitp = n;
144 return 0;
145}
146
129static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, 147static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
130 struct pinmux_cfg_reg **crp, int *indexp, 148 struct pinmux_cfg_reg **crp, int *indexp,
131 unsigned long **cntp) 149 unsigned long **cntp)
@@ -341,7 +359,8 @@ int __gpio_request(unsigned gpio)
341 BUG(); 359 BUG();
342 } 360 }
343 361
344 gpioc->gpios[gpio].flags = pinmux_type; 362 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
363 gpioc->gpios[gpio].flags |= pinmux_type;
345 364
346 ret = 0; 365 ret = 0;
347 err_unlock: 366 err_unlock:
@@ -364,7 +383,8 @@ void gpio_free(unsigned gpio)
364 383
365 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; 384 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
366 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); 385 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
367 gpioc->gpios[gpio].flags = PINMUX_TYPE_NONE; 386 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
387 gpioc->gpios[gpio].flags |= PINMUX_TYPE_NONE;
368 388
369 spin_unlock_irqrestore(&gpio_lock, flags); 389 spin_unlock_irqrestore(&gpio_lock, flags);
370} 390}
@@ -401,7 +421,8 @@ static int pinmux_direction(struct pinmux_info *gpioc,
401 GPIO_CFG_REQ) != 0) 421 GPIO_CFG_REQ) != 0)
402 BUG(); 422 BUG();
403 423
404 gpioc->gpios[gpio].flags = new_pinmux_type; 424 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
425 gpioc->gpios[gpio].flags |= new_pinmux_type;
405 426
406 ret = 0; 427 ret = 0;
407 err_out: 428 err_out:
@@ -494,9 +515,14 @@ EXPORT_SYMBOL(gpio_set_value);
494 515
495int register_pinmux(struct pinmux_info *pip) 516int register_pinmux(struct pinmux_info *pip)
496{ 517{
518 int k;
519
497 registered_gpio = pip; 520 registered_gpio = pip;
498 pr_info("pinmux: %s handling gpio %d -> %d\n", 521 pr_info("pinmux: %s handling gpio %d -> %d\n",
499 pip->name, pip->first_gpio, pip->last_gpio); 522 pip->name, pip->first_gpio, pip->last_gpio);
500 523
524 for (k = pip->first_gpio; k <= pip->last_gpio; k++)
525 setup_data_reg(pip, k);
526
501 return 0; 527 return 0;
502} 528}