Loading arch/mips/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -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. Loading arch/mips/rb532/gpio.c +161 −67 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio); if (value) tmp |= 1 << gpio; writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel); } EXPORT_SYMBOL(rb532_gpio_set_int_level); gpch = container_of(chip, struct rb532_gpio_chip, chip); writel(mask, gpch->regbase + GPIOD); gpdr = gpch->regbase + GPIOCFG; int rb532_gpio_get_int_level(unsigned gpio) { return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio); local_irq_save(flags); tmp = readl(gpdr); tmp |= mask; writel(tmp, gpdr); local_irq_restore(flags); return 0; } EXPORT_SYMBOL(rb532_gpio_get_int_level); void rb532_gpio_set_int_status(unsigned gpio, int value) /* * Set the GPIO interrupt level */ static void rb532_gpio_set_int_level(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 *gpil; tmp = readl(&rb532_gpio_reg0->gpioistat); gpch = container_of(chip, struct rb532_gpio_chip, chip); gpil = gpch->regbase + GPIOILEVEL; 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"); Loading include/asm-mips/mach-rc32434/gpio.h +14 −61 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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_ */ Loading
arch/mips/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -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. Loading
arch/mips/rb532/gpio.c +161 −67 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio); if (value) tmp |= 1 << gpio; writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel); } EXPORT_SYMBOL(rb532_gpio_set_int_level); gpch = container_of(chip, struct rb532_gpio_chip, chip); writel(mask, gpch->regbase + GPIOD); gpdr = gpch->regbase + GPIOCFG; int rb532_gpio_get_int_level(unsigned gpio) { return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio); local_irq_save(flags); tmp = readl(gpdr); tmp |= mask; writel(tmp, gpdr); local_irq_restore(flags); return 0; } EXPORT_SYMBOL(rb532_gpio_get_int_level); void rb532_gpio_set_int_status(unsigned gpio, int value) /* * Set the GPIO interrupt level */ static void rb532_gpio_set_int_level(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 *gpil; tmp = readl(&rb532_gpio_reg0->gpioistat); gpch = container_of(chip, struct rb532_gpio_chip, chip); gpil = gpch->regbase + GPIOILEVEL; 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"); Loading
include/asm-mips/mach-rc32434/gpio.h +14 −61 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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_ */