Skip to content

Commit

Permalink
MIPS: RB532: Convert to GPIO lib
Browse files Browse the repository at this point in the history
This patch converts the rb532 code to use gpio library
and register its gpio chip.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Florian Fainelli authored and Ralf Baechle committed Oct 11, 2008
1 parent 09b7dcf commit d888e25
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 129 deletions.
2 changes: 1 addition & 1 deletion arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ config MIKROTIK_RB532
select SYS_SUPPORTS_LITTLE_ENDIAN
select SWAP_IO_SPACE
select BOOT_RAW
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
Support the Mikrotik(tm) RouterBoard 532 series,
based on the IDT RC32434 SoC.
Expand Down
228 changes: 161 additions & 67 deletions arch/mips/rb532/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,23 @@
*/

#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/platform_device.h>

#include <asm/addrspace.h>
#include <linux/gpio.h>

#include <asm/mach-rc32434/rb.h>

struct rb532_gpio_reg __iomem *rb532_gpio_reg0;
EXPORT_SYMBOL(rb532_gpio_reg0);
#include <asm/mach-rc32434/gpio.h>

struct rb532_gpio_chip {
struct gpio_chip chip;
void __iomem *regbase;
void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value);
int (*get_int_level)(struct gpio_chip *chip, unsigned offset);
void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value);
int (*get_int_status)(struct gpio_chip *chip, unsigned offset);
};

struct mpmc_device dev3;

Expand Down Expand Up @@ -108,108 +111,199 @@ unsigned char get_latch_u5(void)
}
EXPORT_SYMBOL(get_latch_u5);

int rb532_gpio_get_value(unsigned gpio)
/*
* Return GPIO level */
static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
{
return readl(&rb532_gpio_reg0->gpiod) & (1 << gpio);
u32 mask = 1 << offset;
struct rb532_gpio_chip *gpch;

gpch = container_of(chip, struct rb532_gpio_chip, chip);
return readl(gpch->regbase + GPIOD) & mask;
}
EXPORT_SYMBOL(rb532_gpio_get_value);

void rb532_gpio_set_value(unsigned gpio, int value)
/*
* Set output GPIO level
*/
static void rb532_gpio_set(struct gpio_chip *chip,
unsigned offset, int value)
{
unsigned tmp;
unsigned long flags;
u32 mask = 1 << offset;
u32 tmp;
struct rb532_gpio_chip *gpch;
void __iomem *gpvr;

tmp = readl(&rb532_gpio_reg0->gpiod) & ~(1 << gpio);
if (value)
tmp |= 1 << gpio;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
gpvr = gpch->regbase + GPIOD;

writel(tmp, (void *)&rb532_gpio_reg0->gpiod);
local_irq_save(flags);
tmp = readl(gpvr);
if (value)
tmp |= mask;
else
tmp &= ~mask;
writel(tmp, gpvr);
local_irq_restore(flags);
}
EXPORT_SYMBOL(rb532_gpio_set_value);

int rb532_gpio_direction_input(unsigned gpio)
/*
* Set GPIO direction to input
*/
static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
writel(readl(&rb532_gpio_reg0->gpiocfg) & ~(1 << gpio),
(void *)&rb532_gpio_reg0->gpiocfg);
unsigned long flags;
u32 mask = 1 << offset;
u32 value;
struct rb532_gpio_chip *gpch;
void __iomem *gpdr;

return 0;
}
EXPORT_SYMBOL(rb532_gpio_direction_input);
gpch = container_of(chip, struct rb532_gpio_chip, chip);
gpdr = gpch->regbase + GPIOCFG;

int rb532_gpio_direction_output(unsigned gpio, int value)
{
gpio_set_value(gpio, value);
writel(readl(&rb532_gpio_reg0->gpiocfg) | (1 << gpio),
(void *)&rb532_gpio_reg0->gpiocfg);
local_irq_save(flags);
value = readl(gpdr);
value &= ~mask;
writel(value, gpdr);
local_irq_restore(flags);

return 0;
}
EXPORT_SYMBOL(rb532_gpio_direction_output);

void rb532_gpio_set_int_level(unsigned gpio, int value)
/*
* Set GPIO direction to output
*/
static int rb532_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
unsigned tmp;
unsigned long flags;
u32 mask = 1 << offset;
u32 tmp;
struct rb532_gpio_chip *gpch;
void __iomem *gpdr;

gpch = container_of(chip, struct rb532_gpio_chip, chip);
writel(mask, gpch->regbase + GPIOD);
gpdr = gpch->regbase + GPIOCFG;

local_irq_save(flags);
tmp = readl(gpdr);
tmp |= mask;
writel(tmp, gpdr);
local_irq_restore(flags);

tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel);
return 0;
}
EXPORT_SYMBOL(rb532_gpio_set_int_level);

int rb532_gpio_get_int_level(unsigned gpio)
/*
* Set the GPIO interrupt level
*/
static void rb532_gpio_set_int_level(struct gpio_chip *chip,
unsigned offset, int value)
{
return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio);
}
EXPORT_SYMBOL(rb532_gpio_get_int_level);
unsigned long flags;
u32 mask = 1 << offset;
u32 tmp;
struct rb532_gpio_chip *gpch;
void __iomem *gpil;

void rb532_gpio_set_int_status(unsigned gpio, int value)
{
unsigned tmp;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
gpil = gpch->regbase + GPIOILEVEL;

tmp = readl(&rb532_gpio_reg0->gpioistat);
local_irq_save(flags);
tmp = readl(gpil);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpioistat);
tmp |= mask;
else
tmp &= ~mask;
writel(tmp, gpil);
local_irq_restore(flags);
}
EXPORT_SYMBOL(rb532_gpio_set_int_status);

int rb532_gpio_get_int_status(unsigned gpio)
/*
* Get the GPIO interrupt level
*/
static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset)
{
return readl(&rb532_gpio_reg0->gpioistat) & (1 << gpio);
u32 mask = 1 << offset;
struct rb532_gpio_chip *gpch;

gpch = container_of(chip, struct rb532_gpio_chip, chip);
return readl(gpch->regbase + GPIOILEVEL) & mask;
}
EXPORT_SYMBOL(rb532_gpio_get_int_status);

void rb532_gpio_set_func(unsigned gpio, int value)
/*
* Set the GPIO interrupt status
*/
static void rb532_gpio_set_int_status(struct gpio_chip *chip,
unsigned offset, int value)
{
unsigned tmp;
unsigned long flags;
u32 mask = 1 << offset;
u32 tmp;
struct rb532_gpio_chip *gpch;
void __iomem *gpis;

gpch = container_of(chip, struct rb532_gpio_chip, chip);
gpis = gpch->regbase + GPIOISTAT;

tmp = readl(&rb532_gpio_reg0->gpiofunc);
local_irq_save(flags);
tmp = readl(gpis);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpiofunc);
tmp |= mask;
else
tmp &= ~mask;
writel(tmp, gpis);
local_irq_restore(flags);
}
EXPORT_SYMBOL(rb532_gpio_set_func);

int rb532_gpio_get_func(unsigned gpio)
/*
* Get the GPIO interrupt status
*/
static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset)
{
return readl(&rb532_gpio_reg0->gpiofunc) & (1 << gpio);
u32 mask = 1 << offset;
struct rb532_gpio_chip *gpch;

gpch = container_of(chip, struct rb532_gpio_chip, chip);
return readl(gpch->regbase + GPIOISTAT) & mask;
}
EXPORT_SYMBOL(rb532_gpio_get_func);

static struct rb532_gpio_chip rb532_gpio_chip[] = {
[0] = {
.chip = {
.label = "gpio0",
.direction_input = rb532_gpio_direction_input,
.direction_output = rb532_gpio_direction_output,
.get = rb532_gpio_get,
.set = rb532_gpio_set,
.base = 0,
.ngpio = 32,
},
.get_int_level = rb532_gpio_get_int_level,
.set_int_level = rb532_gpio_set_int_level,
.get_int_status = rb532_gpio_get_int_status,
.set_int_status = rb532_gpio_set_int_status,
},
};

int __init rb532_gpio_init(void)
{
rb532_gpio_reg0 = ioremap_nocache(rb532_gpio_reg0_res[0].start,
rb532_gpio_reg0_res[0].end -
rb532_gpio_reg0_res[0].start);
struct resource *r;

if (!rb532_gpio_reg0) {
r = rb532_gpio_reg0_res;
rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start);

if (!rb532_gpio_chip->regbase) {
printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");
return -ENXIO;
}

dev3.base = ioremap_nocache(rb532_dev3_ctl_res[0].start,
rb532_dev3_ctl_res[0].end -
rb532_dev3_ctl_res[0].start);
/* Register our GPIO chip */
gpiochip_add(&rb532_gpio_chip->chip);

r = rb532_dev3_ctl_res;
dev3.base = ioremap_nocache(r->start, r->end - r->start);

if (!dev3.base) {
printk(KERN_ERR "rb532: cannot remap device controller 3\n");
Expand Down
75 changes: 14 additions & 61 deletions include/asm-mips/mach-rc32434/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@

#include <linux/types.h>

#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value

#define gpio_cansleep __gpio_cansleep

#define gpio_to_irq(gpio) IRQ_GPIO(gpio)
#define irq_to_gpio(irq) IRQ_TO_GPIO(irq)

#include <asm-generic/gpio.h>

struct rb532_gpio_reg {
u32 gpiofunc; /* GPIO Function Register
* gpiofunc[x]==0 bit = gpio
Expand Down Expand Up @@ -62,74 +72,17 @@ struct rb532_gpio_reg {
#define RC32434_PCI_MSU_GPIO (1 << 13)

/* NAND GPIO signals */
#define GPIO_RDY (1 << 0x08)
#define GPIO_WPX (1 << 0x09)
#define GPIO_ALE (1 << 0x0a)
#define GPIO_CLE (1 << 0x0b)
#define GPIO_RDY 8
#define GPIO_WPX 9
#define GPIO_ALE 10
#define GPIO_CLE 11

/* Compact Flash GPIO pin */
#define CF_GPIO_NUM 13


extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val);
extern unsigned get_434_reg(unsigned reg_offs);
extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask);
extern unsigned char get_latch_u5(void);

extern int rb532_gpio_get_value(unsigned gpio);
extern void rb532_gpio_set_value(unsigned gpio, int value);
extern int rb532_gpio_direction_input(unsigned gpio);
extern int rb532_gpio_direction_output(unsigned gpio, int value);
extern void rb532_gpio_set_int_level(unsigned gpio, int value);
extern int rb532_gpio_get_int_level(unsigned gpio);
extern void rb532_gpio_set_int_status(unsigned gpio, int value);
extern int rb532_gpio_get_int_status(unsigned gpio);


/* Wrappers for the arch-neutral GPIO API */

static inline int gpio_request(unsigned gpio, const char *label)
{
/* Not yet implemented */
return 0;
}

static inline void gpio_free(unsigned gpio)
{
/* Not yet implemented */
}

static inline int gpio_direction_input(unsigned gpio)
{
return rb532_gpio_direction_input(gpio);
}

static inline int gpio_direction_output(unsigned gpio, int value)
{
return rb532_gpio_direction_output(gpio, value);
}

static inline int gpio_get_value(unsigned gpio)
{
return rb532_gpio_get_value(gpio);
}

static inline void gpio_set_value(unsigned gpio, int value)
{
rb532_gpio_set_value(gpio, value);
}

static inline int gpio_to_irq(unsigned gpio)
{
return gpio;
}

static inline int irq_to_gpio(unsigned irq)
{
return irq;
}

/* For cansleep */
#include <asm-generic/gpio.h>

#endif /* _RC32434_GPIO_H_ */

0 comments on commit d888e25

Please sign in to comment.