CHROMIUM: rk3288-vpu: Set use_dma_bidirectional=1 for decoder CAPTURE queue
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-rk30.c
index 3d30d7341fb7ca26074e921fdbe83fd09e529073..2a170ce574ef6da07d8c1619a34a24edbef47a24 100755 (executable)
 #include <mach/gpio.h>
 #include <mach/io.h>
 #include <mach/iomux.h>
+#include <mach/pmu.h>
 #include <asm/gpio.h>
 #include <asm/mach/irq.h>
 
+#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
+#define MAX_PIN        RK30_PIN3_PD7
+#elif defined(CONFIG_ARCH_RK319X)
+#define MAX_PIN        RK30_PIN4_PD7
+#elif defined(CONFIG_ARCH_RK30)
 #define MAX_PIN        RK30_PIN6_PB7
+#elif defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026)
+#define MAX_PIN        RK2928_PIN3_PD7
+#define RK30_GPIO0_PHYS        RK2928_GPIO0_PHYS
+#define RK30_GPIO0_BASE        RK2928_GPIO0_BASE
+#define RK30_GPIO0_SIZE        RK2928_GPIO0_SIZE
+#define RK30_GPIO1_PHYS        RK2928_GPIO1_PHYS
+#define RK30_GPIO1_BASE        RK2928_GPIO1_BASE
+#define RK30_GPIO1_SIZE        RK2928_GPIO1_SIZE
+#define RK30_GPIO2_PHYS        RK2928_GPIO2_PHYS
+#define RK30_GPIO2_BASE        RK2928_GPIO2_BASE
+#define RK30_GPIO2_SIZE        RK2928_GPIO2_SIZE
+#define RK30_GPIO3_PHYS        RK2928_GPIO3_PHYS
+#define RK30_GPIO3_BASE        RK2928_GPIO3_BASE
+#define RK30_GPIO3_SIZE        RK2928_GPIO3_SIZE
+#define RK30_GRF_BASE  RK2928_GRF_BASE
+#endif
 
 #define to_rk30_gpio_bank(c) container_of(c, struct rk30_gpio_bank, chip)
 
@@ -56,6 +78,7 @@ static int rk30_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset,
 static int rk30_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset);
 static int rk30_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable);
 static int rk30_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
+static int rk30_gpiolib_request(struct gpio_chip *chip, unsigned offset);
 
 #define RK30_GPIO_BANK(ID)                     \
        {                                                               \
@@ -65,10 +88,11 @@ static int rk30_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
                        .direction_output = rk30_gpiolib_direction_output, \
                        .get              = rk30_gpiolib_get,           \
                        .set              = rk30_gpiolib_set,           \
+                       .request          = rk30_gpiolib_request,       \
                        .pull_updown      = rk30_gpiolib_pull_updown,   \
                        .dbg_show         = rk30_gpiolib_dbg_show,      \
                        .to_irq           = rk30_gpiolib_to_irq,        \
-                       .base             = ID < 6 ? PIN_BASE + ID*NUM_GROUP : PIN_BASE + 5*NUM_GROUP,  \
+                       .base             = PIN_BASE + ID*NUM_GROUP,    \
                        .ngpio            = ID < 6 ? NUM_GROUP : 16,    \
                },                                                      \
                .id = ID, \
@@ -81,8 +105,12 @@ static struct rk30_gpio_bank rk30_gpio_banks[] = {
        RK30_GPIO_BANK(1),
        RK30_GPIO_BANK(2),
        RK30_GPIO_BANK(3),
+#if GPIO_BANKS > 4
        RK30_GPIO_BANK(4),
+#endif
+#if GPIO_BANKS > 5
        RK30_GPIO_BANK(6),
+#endif
 };
 
 static inline void rk30_gpio_bit_op(void __iomem *regbase, unsigned int offset, u32 bit, unsigned char flag)
@@ -281,6 +309,11 @@ static int rk30_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset)
        return 0;
 }
 
+static int rk30_gpiolib_request(struct gpio_chip *chip, unsigned offset)
+{
+       iomux_set_gpio_mode(chip->base + offset);
+        return 0;
+}
 
 static int rk30_gpiolib_get(struct gpio_chip *chip, unsigned offset)
 {
@@ -297,18 +330,74 @@ static void rk30_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
        spin_unlock_irqrestore(&bank->lock, flags);
 }
 
-static int rk30_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable)
+static int rk30_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, enum GPIOPullType type)
 {
+#if defined(CONFIG_ARCH_RK3066B)
+#else
        struct rk30_gpio_bank *bank = to_rk30_gpio_bank(chip);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bank->lock, flags);
-       if(offset>=16)  
-       rk30_gpio_bit_op((void *__iomem) RK30_GRF_BASE, GRF_GPIO0H_PULL + bank->id * 8, (1<<offset) | offset_to_bit(offset-16), !enable);
-       else    
-       rk30_gpio_bit_op((void *__iomem) RK30_GRF_BASE, GRF_GPIO0L_PULL + bank->id * 8, (1<<(offset+16)) | offset_to_bit(offset), !enable);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       void __iomem *base;
+       u32 val;
+
+#if defined(CONFIG_ARCH_RK3188) || defined(CONFIG_ARCH_RK319X)
+       /*
+        * pull setting
+        * 2'b00: Z(Noraml operaton)
+        * 2'b01: weak 1(pull-up)
+        * 2'b10: weak 0(pull-down)
+        * 2'b11: Repeater(Bus keeper)
+        */
+       switch (type) {
+       case PullDisable:
+               val = 0;
+               break;
+       case GPIOPullUp:
+               val = 1;
+               break;
+       case GPIOPullDown:
+               val = 2;
+               break;
+       default:
+               WARN(1, "%s: unsupported pull type %d\n", __func__, type);
+               return -EINVAL;
+       }
 
+#if defined(CONFIG_ARCH_RK319X)
+       if (bank->id == 0) {
+               base = RK319X_BB_GRF_BASE + BB_GRF_GPIO0A_PULL + ((offset / 8) * 4);
+               offset = (offset % 8) * 2;
+               __raw_writel((0x3 << (16 + offset)) | (val << offset), base);
+       } else {
+               base = RK319X_GRF_BASE + GRF_GPIO1A_PULL + (bank->id - 1) * 16 + ((offset / 8) * 4);
+               offset = (7 - (offset % 8)) * 2;
+               __raw_writel((0x3 << (16 + offset)) | (val << offset), base);
+       }
+#else
+       if (bank->id == 0 && offset < 12) {
+               base = RK30_PMU_BASE + PMU_GPIO0A_PULL + ((offset / 8) * 4);
+               offset = (offset % 8) * 2;
+               __raw_writel((0x3 << (16 + offset)) | (val << offset), base);
+       } else {
+               base = RK30_GRF_BASE + GRF_GPIO0B_PULL - 4 + bank->id * 16 + ((offset / 8) * 4);
+               offset = (7 - (offset % 8)) * 2;
+               __raw_writel((0x3 << (16 + offset)) | (val << offset), base);
+       }
+#endif
+#else
+       /* RK30XX && RK292X */
+       /*
+        * Values written to this register independently
+        * control Pullup/Pulldown or not for the
+        * corresponding data bit in GPIO.
+        * 0: pull up/down enable, PAD type will decide
+        * to be up or down, not related with this value
+        * 1: pull up/down disable
+       */
+       val = (type == PullDisable) ? 1 : 0;
+       base = RK30_GRF_BASE + GRF_GPIO0L_PULL + bank->id * 8 + ((offset / 16) * 4);
+       offset = offset % 16;
+       __raw_writel((1 << (16 + offset)) | (val << offset), base);
+#endif
+#endif
        return 0;
 }
 
@@ -397,11 +486,10 @@ static struct irq_chip rk30_gpio_irq_chip = {
 
 void __init rk30_gpio_init(void)
 {
-       unsigned int i, j, pin;
+       unsigned int i, j, pin, irqs = 0;
        struct rk30_gpio_bank *bank;
 
        bank = rk30_gpio_banks;
-       pin = PIN_BASE;
 
        for (i = 0; i < ARRAY_SIZE(rk30_gpio_banks); i++, bank++) {
                spin_lock_init(&bank->lock);
@@ -410,6 +498,7 @@ void __init rk30_gpio_init(void)
                gpiochip_add(&bank->chip);
 
                __raw_writel(0, bank->regbase + GPIO_INTEN);
+               pin = bank->chip.base;
                for (j = 0; j < 32; j++) {
                        unsigned int irq = gpio_to_irq(pin);
                        if (pin > MAX_PIN)
@@ -419,12 +508,13 @@ void __init rk30_gpio_init(void)
                        irq_set_chip_and_handler(irq, &rk30_gpio_irq_chip, handle_level_irq);
                        set_irq_flags(irq, IRQF_VALID);
                        pin++;
+                       irqs++;
                }
 
                irq_set_handler_data(bank->irq, bank);
                irq_set_chained_handler(bank->irq, rk30_gpio_irq_handler);
        }
-       printk("%s: %d gpio irqs in %d banks\n", __func__, pin - PIN_BASE, ARRAY_SIZE(rk30_gpio_banks));
+       printk("%s: %d gpio irqs in %d banks\n", __func__, irqs, ARRAY_SIZE(rk30_gpio_banks));
 }
 
 #ifdef CONFIG_PM