Skip to content

Commit

Permalink
Davinci: gpio - register layout invariant inlines
Browse files Browse the repository at this point in the history
This patch renders the inlined gpio accessors in gpio.h independent of the
underlying controller's register layout.  This is done by including three new
fields in davinci_gpio_controller to hold the addresses of the set, clear, and
in data registers.

Other changes:

1. davinci_gpio_regs structure definition moved to gpio.c.  This structure is
no longer common across all davinci socs (davinci_gpio_controller is).

2. controller base address calculation code (gpio2controller()) moved to
gpio.c as this was no longer necessary for the inline implementation.

3. modified inline range checks to use davinci_soc_info.gpio_num instead of
DAVINCI_N_GPIO.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Tested-by: Sandeep Paulraj <s-paulraj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
  • Loading branch information
Cyril Chemparathy authored and Kevin Hilman committed May 6, 2010
1 parent 99e9e52 commit c12f415
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 45 deletions.
41 changes: 38 additions & 3 deletions arch/arm/mach-davinci/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,44 @@

#include <asm/mach/irq.h>

struct davinci_gpio_regs {
u32 dir;
u32 out_data;
u32 set_data;
u32 clr_data;
u32 in_data;
u32 set_rising;
u32 clr_rising;
u32 set_falling;
u32 clr_falling;
u32 intstat;
};

static DEFINE_SPINLOCK(gpio_lock);

#define chip2controller(chip) \
container_of(chip, struct davinci_gpio_controller, chip)

static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];

/* create a non-inlined version */
static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio)
{
return __gpio_to_controller(gpio);
void __iomem *ptr;
void __iomem *base = davinci_soc_info.gpio_base;

if (gpio < 32 * 1)
ptr = base + 0x10;
else if (gpio < 32 * 2)
ptr = base + 0x38;
else if (gpio < 32 * 3)
ptr = base + 0x60;
else if (gpio < 32 * 4)
ptr = base + 0x88;
else if (gpio < 32 * 5)
ptr = base + 0xb0;
else
ptr = NULL;
return ptr;
}

static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
Expand Down Expand Up @@ -116,6 +143,7 @@ static int __init davinci_gpio_setup(void)
int i, base;
unsigned ngpio;
struct davinci_soc_info *soc_info = &davinci_soc_info;
struct davinci_gpio_regs *regs;

/*
* The gpio banks conceptually expose a segmented bitmap,
Expand Down Expand Up @@ -144,11 +172,18 @@ static int __init davinci_gpio_setup(void)
if (chips[i].chip.ngpio > 32)
chips[i].chip.ngpio = 32;

chips[i].regs = gpio2regs(base);
regs = gpio2regs(base);
chips[i].regs = regs;
chips[i].set_data = &regs->set_data;
chips[i].clr_data = &regs->clr_data;
chips[i].in_data = &regs->in_data;

gpiochip_add(&chips[i].chip);
}

soc_info->gpio_ctlrs = chips;
soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);

davinci_gpio_irq_setup();
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/mach-davinci/include/mach/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct davinci_timer_info {
unsigned int clocksource_id;
};

struct davinci_gpio_controller;

/* SoC specific init support */
struct davinci_soc_info {
struct map_desc *io_desc;
Expand All @@ -61,6 +63,8 @@ struct davinci_soc_info {
unsigned gpio_num;
unsigned gpio_irq;
unsigned gpio_unbanked;
struct davinci_gpio_controller *gpio_ctlrs;
int gpio_ctlrs_num;
struct platform_device *serial_dev;
struct emac_platform_data *emac_pdata;
dma_addr_t sram_dma;
Expand Down
65 changes: 23 additions & 42 deletions arch/arm/mach-davinci/include/mach/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,13 @@
/* Convert GPIO signal to GPIO pin number */
#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio))

struct davinci_gpio_regs {
u32 dir;
u32 out_data;
u32 set_data;
u32 clr_data;
u32 in_data;
u32 set_rising;
u32 clr_rising;
u32 set_falling;
u32 clr_falling;
u32 intstat;
};

struct davinci_gpio_controller {
struct davinci_gpio_regs __iomem *regs;
struct gpio_chip chip;
int irq_base;
void __iomem *regs;
void __iomem *set_data;
void __iomem *clr_data;
void __iomem *in_data;
};

/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
Expand All @@ -73,25 +63,16 @@ struct davinci_gpio_controller {
*
* These are NOT part of the cross-platform GPIO interface
*/
static inline struct davinci_gpio_regs __iomem *
static inline struct davinci_gpio_controller *
__gpio_to_controller(unsigned gpio)
{
void __iomem *ptr;
void __iomem *base = davinci_soc_info.gpio_base;

if (gpio < 32 * 1)
ptr = base + 0x10;
else if (gpio < 32 * 2)
ptr = base + 0x38;
else if (gpio < 32 * 3)
ptr = base + 0x60;
else if (gpio < 32 * 4)
ptr = base + 0x88;
else if (gpio < 32 * 5)
ptr = base + 0xb0;
else
ptr = NULL;
return ptr;
struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
int index = gpio / 32;

if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
return NULL;

return ctlrs + index;
}

static inline u32 __gpio_mask(unsigned gpio)
Expand All @@ -107,16 +88,16 @@ static inline u32 __gpio_mask(unsigned gpio)
*/
static inline void gpio_set_value(unsigned gpio, int value)
{
if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) {
struct davinci_gpio_regs __iomem *g;
u32 mask;
if (__builtin_constant_p(value) && gpio < davinci_soc_info.gpio_num) {
struct davinci_gpio_controller *ctlr;
u32 mask;

g = __gpio_to_controller(gpio);
ctlr = __gpio_to_controller(gpio);
mask = __gpio_mask(gpio);
if (value)
__raw_writel(mask, &g->set_data);
__raw_writel(mask, ctlr->set_data);
else
__raw_writel(mask, &g->clr_data);
__raw_writel(mask, ctlr->clr_data);
return;
}

Expand All @@ -134,18 +115,18 @@ static inline void gpio_set_value(unsigned gpio, int value)
*/
static inline int gpio_get_value(unsigned gpio)
{
struct davinci_gpio_regs __iomem *g;
struct davinci_gpio_controller *ctlr;

if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO)
if (!__builtin_constant_p(gpio) || gpio >= davinci_soc_info.gpio_num)
return __gpio_get_value(gpio);

g = __gpio_to_controller(gpio);
return __gpio_mask(gpio) & __raw_readl(&g->in_data);
ctlr = __gpio_to_controller(gpio);
return __gpio_mask(gpio) & __raw_readl(ctlr->in_data);
}

static inline int gpio_cansleep(unsigned gpio)
{
if (__builtin_constant_p(gpio) && gpio < DAVINCI_N_GPIO)
if (__builtin_constant_p(gpio) && gpio < davinci_soc_info.gpio_num)
return 0;
else
return __gpio_cansleep(gpio);
Expand Down

0 comments on commit c12f415

Please sign in to comment.