提交 18801be7 编写于 作者: M Magnus Damm 提交者: Paul Mundt

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: NMagnus Damm <damm@igel.co.jp>
Signed-off-by: NPaul Mundt <lethal@linux-sh.org>
上级 53760710
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#endif #endif
typedef unsigned short pinmux_enum_t; typedef unsigned short pinmux_enum_t;
typedef unsigned char pinmux_flag_t; typedef unsigned short pinmux_flag_t;
#define PINMUX_TYPE_NONE 0 #define PINMUX_TYPE_NONE 0
#define PINMUX_TYPE_FUNCTION 1 #define PINMUX_TYPE_FUNCTION 1
...@@ -34,6 +34,11 @@ typedef unsigned char pinmux_flag_t; ...@@ -34,6 +34,11 @@ typedef unsigned char pinmux_flag_t;
#define PINMUX_FLAG_WANT_PULLUP (1 << 3) #define PINMUX_FLAG_WANT_PULLUP (1 << 3)
#define PINMUX_FLAG_WANT_PULLDOWN (1 << 4) #define PINMUX_FLAG_WANT_PULLDOWN (1 << 4)
#define PINMUX_FLAG_DBIT_SHIFT 5
#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT)
#define PINMUX_FLAG_DREG_SHIFT 10
#define PINMUX_FLAG_DREG (0x3f << PINMUX_FLAG_DREG_SHIFT)
struct pinmux_gpio { struct pinmux_gpio {
pinmux_enum_t enum_id; pinmux_enum_t enum_id;
pinmux_flag_t flags; pinmux_flag_t flags;
......
...@@ -95,14 +95,13 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width, ...@@ -95,14 +95,13 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width,
return 0; return 0;
} }
static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
struct pinmux_data_reg **drp, int *bitp)
{ {
pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
struct pinmux_data_reg *data_reg; struct pinmux_data_reg *data_reg;
int k, n; int k, n;
if (!enum_in_range(enum_id, &gpioc->data)) if (!enum_in_range(gpiop->enum_id, &gpioc->data))
return -1; return -1;
k = 0; k = 0;
...@@ -113,19 +112,38 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, ...@@ -113,19 +112,38 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
break; break;
for (n = 0; n < data_reg->reg_width; n++) { for (n = 0; n < data_reg->reg_width; n++) {
if (data_reg->enum_ids[n] == enum_id) { if (data_reg->enum_ids[n] == gpiop->enum_id) {
*drp = data_reg; gpiop->flags &= ~PINMUX_FLAG_DREG;
*bitp = n; gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
gpiop->flags &= ~PINMUX_FLAG_DBIT;
gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
return 0; return 0;
} }
} }
k++; k++;
} }
BUG();
return -1; return -1;
} }
static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
struct pinmux_data_reg **drp, int *bitp)
{
struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
int k, n;
if (!enum_in_range(gpiop->enum_id, &gpioc->data))
return -1;
k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
*drp = gpioc->data_regs + k;
*bitp = n;
return 0;
}
static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
struct pinmux_cfg_reg **crp, int *indexp, struct pinmux_cfg_reg **crp, int *indexp,
unsigned long **cntp) unsigned long **cntp)
...@@ -341,7 +359,8 @@ int __gpio_request(unsigned gpio) ...@@ -341,7 +359,8 @@ int __gpio_request(unsigned gpio)
BUG(); BUG();
} }
gpioc->gpios[gpio].flags = pinmux_type; gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
gpioc->gpios[gpio].flags |= pinmux_type;
ret = 0; ret = 0;
err_unlock: err_unlock:
...@@ -364,7 +383,8 @@ void gpio_free(unsigned gpio) ...@@ -364,7 +383,8 @@ void gpio_free(unsigned gpio)
pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
gpioc->gpios[gpio].flags = PINMUX_TYPE_NONE; gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
gpioc->gpios[gpio].flags |= PINMUX_TYPE_NONE;
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
} }
...@@ -401,7 +421,8 @@ static int pinmux_direction(struct pinmux_info *gpioc, ...@@ -401,7 +421,8 @@ static int pinmux_direction(struct pinmux_info *gpioc,
GPIO_CFG_REQ) != 0) GPIO_CFG_REQ) != 0)
BUG(); BUG();
gpioc->gpios[gpio].flags = new_pinmux_type; gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
gpioc->gpios[gpio].flags |= new_pinmux_type;
ret = 0; ret = 0;
err_out: err_out:
...@@ -494,9 +515,14 @@ EXPORT_SYMBOL(gpio_set_value); ...@@ -494,9 +515,14 @@ EXPORT_SYMBOL(gpio_set_value);
int register_pinmux(struct pinmux_info *pip) int register_pinmux(struct pinmux_info *pip)
{ {
int k;
registered_gpio = pip; registered_gpio = pip;
pr_info("pinmux: %s handling gpio %d -> %d\n", pr_info("pinmux: %s handling gpio %d -> %d\n",
pip->name, pip->first_gpio, pip->last_gpio); pip->name, pip->first_gpio, pip->last_gpio);
for (k = pip->first_gpio; k <= pip->last_gpio; k++)
setup_data_reg(pip, k);
return 0; return 0;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册