These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / pinctrl / pinctrl-rockchip.c
index dee7d5f..a065112 100644 (file)
@@ -63,6 +63,7 @@ enum rockchip_pinctrl_type {
        RK3066B,
        RK3188,
        RK3288,
+       RK3368,
 };
 
 /**
@@ -163,6 +164,9 @@ struct rockchip_pin_ctrl {
        void    (*pull_calc_reg)(struct rockchip_pin_bank *bank,
                                    int pin_num, struct regmap **regmap,
                                    int *reg, u8 *bit);
+       void    (*drv_calc_reg)(struct rockchip_pin_bank *bank,
+                                   int pin_num, struct regmap **regmap,
+                                   int *reg, u8 *bit);
 };
 
 struct rockchip_pin_config {
@@ -581,7 +585,6 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
 #define RK3288_DRV_BITS_PER_PIN                2
 #define RK3288_DRV_PINS_PER_REG                8
 #define RK3288_DRV_BANK_STRIDE         16
-static int rk3288_drv_list[] = { 2, 4, 8, 12 };
 
 static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
                                    int pin_num, struct regmap **regmap,
@@ -611,14 +614,81 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
        }
 }
 
-static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
+#define RK3368_PULL_GRF_OFFSET         0x100
+#define RK3368_PULL_PMU_OFFSET         0x10
+
+static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+                                   int pin_num, struct regmap **regmap,
+                                   int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+
+       /* The first 32 pins of the first bank are located in PMU */
+       if (bank->bank_num == 0) {
+               *regmap = info->regmap_pmu;
+               *reg = RK3368_PULL_PMU_OFFSET;
+
+               *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+               *bit = pin_num % RK3188_PULL_PINS_PER_REG;
+               *bit *= RK3188_PULL_BITS_PER_PIN;
+       } else {
+               *regmap = info->regmap_base;
+               *reg = RK3368_PULL_GRF_OFFSET;
+
+               /* correct the offset, as we're starting with the 2nd bank */
+               *reg -= 0x10;
+               *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+               *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+               *bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+               *bit *= RK3188_PULL_BITS_PER_PIN;
+       }
+}
+
+#define RK3368_DRV_PMU_OFFSET          0x20
+#define RK3368_DRV_GRF_OFFSET          0x200
+
+static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+                                   int pin_num, struct regmap **regmap,
+                                   int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+
+       /* The first 32 pins of the first bank are located in PMU */
+       if (bank->bank_num == 0) {
+               *regmap = info->regmap_pmu;
+               *reg = RK3368_DRV_PMU_OFFSET;
+
+               *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+               *bit = pin_num % RK3288_DRV_PINS_PER_REG;
+               *bit *= RK3288_DRV_BITS_PER_PIN;
+       } else {
+               *regmap = info->regmap_base;
+               *reg = RK3368_DRV_GRF_OFFSET;
+
+               /* correct the offset, as we're starting with the 2nd bank */
+               *reg -= 0x10;
+               *reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+               *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+               *bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+               *bit *= RK3288_DRV_BITS_PER_PIN;
+       }
+}
+
+static int rockchip_perpin_drv_list[] = { 2, 4, 8, 12 };
+
+static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank,
+                                    int pin_num)
 {
+       struct rockchip_pinctrl *info = bank->drvdata;
+       struct rockchip_pin_ctrl *ctrl = info->ctrl;
        struct regmap *regmap;
        int reg, ret;
        u32 data;
        u8 bit;
 
-       rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+       ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
 
        ret = regmap_read(regmap, reg, &data);
        if (ret)
@@ -627,24 +697,25 @@ static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
        data >>= bit;
        data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
 
-       return rk3288_drv_list[data];
+       return rockchip_perpin_drv_list[data];
 }
 
-static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
-                           int strength)
+static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
+                                    int pin_num, int strength)
 {
        struct rockchip_pinctrl *info = bank->drvdata;
+       struct rockchip_pin_ctrl *ctrl = info->ctrl;
        struct regmap *regmap;
        unsigned long flags;
        int reg, ret, i;
        u32 data, rmask;
        u8 bit;
 
-       rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+       ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
 
        ret = -EINVAL;
-       for (i = 0; i < ARRAY_SIZE(rk3288_drv_list); i++) {
-               if (rk3288_drv_list[i] == strength) {
+       for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list); i++) {
+               if (rockchip_perpin_drv_list[i] == strength) {
                        ret = i;
                        break;
                }
@@ -695,6 +766,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
                                : PIN_CONFIG_BIAS_DISABLE;
        case RK3188:
        case RK3288:
+       case RK3368:
                data >>= bit;
                data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
@@ -750,6 +822,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                break;
        case RK3188:
        case RK3288:
+       case RK3368:
                spin_lock_irqsave(&bank->slock, flags);
 
                /* enable the write to the equivalent lower bits */
@@ -872,6 +945,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
        if (ret < 0)
                return ret;
 
+       clk_enable(bank->clk);
        spin_lock_irqsave(&bank->slock, flags);
 
        data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@@ -883,6 +957,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
        writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
 
        spin_unlock_irqrestore(&bank->slock, flags);
+       clk_disable(bank->clk);
 
        return 0;
 }
@@ -927,6 +1002,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
                return pull ? false : true;
        case RK3188:
        case RK3288:
+       case RK3368:
                return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
        }
 
@@ -983,10 +1059,11 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
                        break;
                case PIN_CONFIG_DRIVE_STRENGTH:
                        /* rk3288 is the first with per-pin drive-strength */
-                       if (info->ctrl->type != RK3288)
+                       if (!info->ctrl->drv_calc_reg)
                                return -ENOTSUPP;
 
-                       rc = rk3288_set_drive(bank, pin - bank->pin_base, arg);
+                       rc = rockchip_set_drive_perpin(bank,
+                                               pin - bank->pin_base, arg);
                        if (rc < 0)
                                return rc;
                        break;
@@ -1041,10 +1118,10 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
                break;
        case PIN_CONFIG_DRIVE_STRENGTH:
                /* rk3288 is the first with per-pin drive-strength */
-               if (info->ctrl->type != RK3288)
+               if (!info->ctrl->drv_calc_reg)
                        return -ENOTSUPP;
 
-               rc = rk3288_get_drive(bank, pin - bank->pin_base);
+               rc = rockchip_get_drive_perpin(bank, pin - bank->pin_base);
                if (rc < 0)
                        return rc;
 
@@ -1274,9 +1351,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
                return ret;
 
        info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info);
-       if (!info->pctl_dev) {
+       if (IS_ERR(info->pctl_dev)) {
                dev_err(&pdev->dev, "could not register pinctrl driver\n");
-               return -EINVAL;
+               return PTR_ERR(info->pctl_dev);
        }
 
        for (bank = 0; bank < info->ctrl->nr_banks; ++bank) {
@@ -1297,16 +1374,6 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
  * GPIO handling
  */
 
-static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       pinctrl_free_gpio(chip->base + offset);
-}
-
 static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
        struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
@@ -1314,6 +1381,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
        unsigned long flags;
        u32 data;
 
+       clk_enable(bank->clk);
        spin_lock_irqsave(&bank->slock, flags);
 
        data = readl(reg);
@@ -1323,6 +1391,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
        writel(data, reg);
 
        spin_unlock_irqrestore(&bank->slock, flags);
+       clk_disable(bank->clk);
 }
 
 /*
@@ -1334,7 +1403,9 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
        struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
        u32 data;
 
+       clk_enable(bank->clk);
        data = readl(bank->reg_base + GPIO_EXT_PORT);
+       clk_disable(bank->clk);
        data >>= offset;
        data &= 1;
        return data;
@@ -1380,8 +1451,8 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 }
 
 static const struct gpio_chip rockchip_gpiolib_chip = {
-       .request = rockchip_gpio_request,
-       .free = rockchip_gpio_free,
+       .request = gpiochip_generic_request,
+       .free = gpiochip_generic_free,
        .set = rockchip_gpio_set,
        .get = rockchip_gpio_get,
        .direction_input = rockchip_gpio_direction_input,
@@ -1394,10 +1465,10 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
  * Interrupt handling
  */
 
-static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void rockchip_irq_demux(struct irq_desc *desc)
 {
-       struct irq_chip *chip = irq_get_chip(irq);
-       struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
        u32 pend;
 
        dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
@@ -1407,7 +1478,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
        pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
 
        while (pend) {
-               unsigned int virq;
+               unsigned int irq, virq;
 
                irq = __ffs(pend);
                pend &= ~BIT(irq);
@@ -1471,6 +1542,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
        if (ret < 0)
                return ret;
 
+       clk_enable(bank->clk);
        spin_lock_irqsave(&bank->slock, flags);
 
        data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@@ -1480,9 +1552,9 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
        spin_unlock_irqrestore(&bank->slock, flags);
 
        if (type & IRQ_TYPE_EDGE_BOTH)
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
        else
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
 
        spin_lock_irqsave(&bank->slock, flags);
        irq_gc_lock(gc);
@@ -1528,6 +1600,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
        default:
                irq_gc_unlock(gc);
                spin_unlock_irqrestore(&bank->slock, flags);
+               clk_disable(bank->clk);
                return -EINVAL;
        }
 
@@ -1536,6 +1609,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
 
        irq_gc_unlock(gc);
        spin_unlock_irqrestore(&bank->slock, flags);
+       clk_disable(bank->clk);
 
        return 0;
 }
@@ -1545,8 +1619,10 @@ static void rockchip_irq_suspend(struct irq_data *d)
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct rockchip_pin_bank *bank = gc->private;
 
+       clk_enable(bank->clk);
        bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
        irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
+       clk_disable(bank->clk);
 }
 
 static void rockchip_irq_resume(struct irq_data *d)
@@ -1554,7 +1630,27 @@ static void rockchip_irq_resume(struct irq_data *d)
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct rockchip_pin_bank *bank = gc->private;
 
+       clk_enable(bank->clk);
        irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK);
+       clk_disable(bank->clk);
+}
+
+static void rockchip_irq_gc_mask_clr_bit(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct rockchip_pin_bank *bank = gc->private;
+
+       clk_enable(bank->clk);
+       irq_gc_mask_clr_bit(d);
+}
+
+void rockchip_irq_gc_mask_set_bit(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct rockchip_pin_bank *bank = gc->private;
+
+       irq_gc_mask_set_bit(d);
+       clk_disable(bank->clk);
 }
 
 static int rockchip_interrupts_register(struct platform_device *pdev,
@@ -1565,7 +1661,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
        unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
        struct irq_chip_generic *gc;
        int ret;
-       int i;
+       int i, j;
 
        for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
                if (!bank->valid) {
@@ -1574,11 +1670,19 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
                        continue;
                }
 
+               ret = clk_enable(bank->clk);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to enable clock for bank %s\n",
+                               bank->name);
+                       continue;
+               }
+
                bank->domain = irq_domain_add_linear(bank->of_node, 32,
                                                &irq_generic_chip_ops, NULL);
                if (!bank->domain) {
                        dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
                                 bank->name);
+                       clk_disable(bank->clk);
                        continue;
                }
 
@@ -1589,6 +1693,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
                        dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
                                bank->name);
                        irq_domain_remove(bank->domain);
+                       clk_disable(bank->clk);
                        continue;
                }
 
@@ -1606,16 +1711,23 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
                gc->chip_types[0].regs.mask = GPIO_INTMASK;
                gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
                gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
-               gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
-               gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
+               gc->chip_types[0].chip.irq_mask = rockchip_irq_gc_mask_set_bit;
+               gc->chip_types[0].chip.irq_unmask =
+                                                 rockchip_irq_gc_mask_clr_bit;
                gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
                gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
                gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
                gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
                gc->wake_enabled = IRQ_MSK(bank->nr_pins);
 
-               irq_set_handler_data(bank->irq, bank);
-               irq_set_chained_handler(bank->irq, rockchip_irq_demux);
+               irq_set_chained_handler_and_data(bank->irq,
+                                                rockchip_irq_demux, bank);
+
+               /* map the gpio irqs here, when the clock is still running */
+               for (j = 0 ; j < 32 ; j++)
+                       irq_create_mapping(bank->domain, j);
+
+               clk_disable(bank->clk);
        }
 
        return 0;
@@ -1733,7 +1845,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
        if (IS_ERR(bank->clk))
                return PTR_ERR(bank->clk);
 
-       return clk_prepare_enable(bank->clk);
+       return clk_prepare(bank->clk);
 }
 
 static const struct of_device_id rockchip_pinctrl_dt_match[];
@@ -1967,6 +2079,21 @@ static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
                .pull_calc_reg          = rk2928_calc_pull_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3036_pin_banks[] = {
+       PIN_BANK(0, 32, "gpio0"),
+       PIN_BANK(1, 32, "gpio1"),
+       PIN_BANK(2, 32, "gpio2"),
+};
+
+static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
+               .pin_banks              = rk3036_pin_banks,
+               .nr_banks               = ARRAY_SIZE(rk3036_pin_banks),
+               .label                  = "RK3036-GPIO",
+               .type                   = RK2928,
+               .grf_mux_offset         = 0xa8,
+               .pull_calc_reg          = rk2928_calc_pull_reg_and_bit,
+};
+
 static struct rockchip_pin_bank rk3066a_pin_banks[] = {
        PIN_BANK(0, 32, "gpio0"),
        PIN_BANK(1, 32, "gpio1"),
@@ -2056,11 +2183,37 @@ static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
                .grf_mux_offset         = 0x0,
                .pmu_mux_offset         = 0x84,
                .pull_calc_reg          = rk3288_calc_pull_reg_and_bit,
+               .drv_calc_reg           = rk3288_calc_drv_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3368_pin_banks[] = {
+       PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+                                            IOMUX_SOURCE_PMU,
+                                            IOMUX_SOURCE_PMU,
+                                            IOMUX_SOURCE_PMU
+                           ),
+       PIN_BANK(1, 32, "gpio1"),
+       PIN_BANK(2, 32, "gpio2"),
+       PIN_BANK(3, 32, "gpio3"),
+};
+
+static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
+               .pin_banks              = rk3368_pin_banks,
+               .nr_banks               = ARRAY_SIZE(rk3368_pin_banks),
+               .label                  = "RK3368-GPIO",
+               .type                   = RK3368,
+               .grf_mux_offset         = 0x0,
+               .pmu_mux_offset         = 0x0,
+               .pull_calc_reg          = rk3368_calc_pull_reg_and_bit,
+               .drv_calc_reg           = rk3368_calc_drv_reg_and_bit,
+};
+
+
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
        { .compatible = "rockchip,rk2928-pinctrl",
                .data = (void *)&rk2928_pin_ctrl },
+       { .compatible = "rockchip,rk3036-pinctrl",
+               .data = (void *)&rk3036_pin_ctrl },
        { .compatible = "rockchip,rk3066a-pinctrl",
                .data = (void *)&rk3066a_pin_ctrl },
        { .compatible = "rockchip,rk3066b-pinctrl",
@@ -2069,6 +2222,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
                .data = (void *)&rk3188_pin_ctrl },
        { .compatible = "rockchip,rk3288-pinctrl",
                .data = (void *)&rk3288_pin_ctrl },
+       { .compatible = "rockchip,rk3368-pinctrl",
+               .data = (void *)&rk3368_pin_ctrl },
        {},
 };
 MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);