Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: rockchip: add support for the rk3399

The pinctrl of rk3399 is much different from other's,
especially the 3bits of drive strength.

Signed-off-by: David Wu <david.wu@rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

David Wu and committed by
Linus Walleij
b6c23275 aac7e974

+356 -15
+1 -1
Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
··· 22 22 - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl" 23 23 "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl" 24 24 "rockchip,rk3228-pinctrl", "rockchip,rk3288-pinctrl" 25 - "rockchip,rk3368-pinctrl" 25 + "rockchip,rk3368-pinctrl", "rockchip,rk3399-pinctrl" 26 26 - rockchip,grf: phandle referencing a syscon providing the 27 27 "general register files" 28 28
+355 -14
drivers/pinctrl/pinctrl-rockchip.c
··· 64 64 RK3188, 65 65 RK3288, 66 66 RK3368, 67 + RK3399, 67 68 }; 68 69 69 70 /** ··· 87 86 }; 88 87 89 88 /** 89 + * enum type index corresponding to rockchip_perpin_drv_list arrays index. 90 + */ 91 + enum rockchip_pin_drv_type { 92 + DRV_TYPE_IO_DEFAULT = 0, 93 + DRV_TYPE_IO_1V8_OR_3V0, 94 + DRV_TYPE_IO_1V8_ONLY, 95 + DRV_TYPE_IO_1V8_3V0_AUTO, 96 + DRV_TYPE_IO_3V3_ONLY, 97 + DRV_TYPE_MAX 98 + }; 99 + 100 + /** 101 + * @drv_type: drive strength variant using rockchip_perpin_drv_type 102 + * @offset: if initialized to -1 it will be autocalculated, by specifying 103 + * an initial offset value the relevant source offset can be reset 104 + * to a new value for autocalculating the following drive strength 105 + * registers. if used chips own cal_drv func instead to calculate 106 + * registers offset, the variant could be ignored. 107 + */ 108 + struct rockchip_drv { 109 + enum rockchip_pin_drv_type drv_type; 110 + int offset; 111 + }; 112 + 113 + /** 90 114 * @reg_base: register base of the gpio bank 91 115 * @reg_pull: optional separate register for additional pull settings 92 116 * @clk: clock of the gpio bank ··· 122 96 * @name: name of the bank 123 97 * @bank_num: number of the bank, to account for holes 124 98 * @iomux: array describing the 4 iomux sources of the bank 99 + * @drv: array describing the 4 drive strength sources of the bank 125 100 * @valid: are all necessary informations present 126 101 * @of_node: dt node of this bank 127 102 * @drvdata: common pinctrl basedata ··· 142 115 char *name; 143 116 u8 bank_num; 144 117 struct rockchip_iomux iomux[4]; 118 + struct rockchip_drv drv[4]; 145 119 bool valid; 146 120 struct device_node *of_node; 147 121 struct rockchip_pinctrl *drvdata; ··· 179 151 }, \ 180 152 } 181 153 154 + #define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \ 155 + { \ 156 + .bank_num = id, \ 157 + .nr_pins = pins, \ 158 + .name = label, \ 159 + .iomux = { \ 160 + { .offset = -1 }, \ 161 + { .offset = -1 }, \ 162 + { .offset = -1 }, \ 163 + { .offset = -1 }, \ 164 + }, \ 165 + .drv = { \ 166 + { .drv_type = type0, .offset = -1 }, \ 167 + { .drv_type = type1, .offset = -1 }, \ 168 + { .drv_type = type2, .offset = -1 }, \ 169 + { .drv_type = type3, .offset = -1 }, \ 170 + }, \ 171 + } 172 + 173 + #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1, \ 174 + iom2, iom3, drv0, drv1, drv2, \ 175 + drv3, offset0, offset1, \ 176 + offset2, offset3) \ 177 + { \ 178 + .bank_num = id, \ 179 + .nr_pins = pins, \ 180 + .name = label, \ 181 + .iomux = { \ 182 + { .type = iom0, .offset = -1 }, \ 183 + { .type = iom1, .offset = -1 }, \ 184 + { .type = iom2, .offset = -1 }, \ 185 + { .type = iom3, .offset = -1 }, \ 186 + }, \ 187 + .drv = { \ 188 + { .drv_type = drv0, .offset = offset0 }, \ 189 + { .drv_type = drv1, .offset = offset1 }, \ 190 + { .drv_type = drv2, .offset = offset2 }, \ 191 + { .drv_type = drv3, .offset = offset3 }, \ 192 + }, \ 193 + } 194 + 182 195 /** 183 196 */ 184 197 struct rockchip_pin_ctrl { ··· 230 161 enum rockchip_pinctrl_type type; 231 162 int grf_mux_offset; 232 163 int pmu_mux_offset; 164 + int grf_drv_offset; 165 + int pmu_drv_offset; 166 + 233 167 void (*pull_calc_reg)(struct rockchip_pin_bank *bank, 234 168 int pin_num, struct regmap **regmap, 235 169 int *reg, u8 *bit); ··· 777 705 } 778 706 } 779 707 780 - static int rockchip_perpin_drv_list[] = { 2, 4, 8, 12 }; 708 + #define RK3399_PULL_GRF_OFFSET 0xe040 709 + #define RK3399_PULL_PMU_OFFSET 0x40 710 + #define RK3399_DRV_3BITS_PER_PIN 3 711 + 712 + static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 713 + int pin_num, struct regmap **regmap, 714 + int *reg, u8 *bit) 715 + { 716 + struct rockchip_pinctrl *info = bank->drvdata; 717 + 718 + /* The bank0:16 and bank1:32 pins are located in PMU */ 719 + if ((bank->bank_num == 0) || (bank->bank_num == 1)) { 720 + *regmap = info->regmap_pmu; 721 + *reg = RK3399_PULL_PMU_OFFSET; 722 + 723 + *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 724 + 725 + *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 726 + *bit = pin_num % RK3188_PULL_PINS_PER_REG; 727 + *bit *= RK3188_PULL_BITS_PER_PIN; 728 + } else { 729 + *regmap = info->regmap_base; 730 + *reg = RK3399_PULL_GRF_OFFSET; 731 + 732 + /* correct the offset, as we're starting with the 3rd bank */ 733 + *reg -= 0x20; 734 + *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 735 + *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 736 + 737 + *bit = (pin_num % RK3188_PULL_PINS_PER_REG); 738 + *bit *= RK3188_PULL_BITS_PER_PIN; 739 + } 740 + } 741 + 742 + static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 743 + int pin_num, struct regmap **regmap, 744 + int *reg, u8 *bit) 745 + { 746 + struct rockchip_pinctrl *info = bank->drvdata; 747 + int drv_num = (pin_num / 8); 748 + 749 + /* The bank0:16 and bank1:32 pins are located in PMU */ 750 + if ((bank->bank_num == 0) || (bank->bank_num == 1)) 751 + *regmap = info->regmap_pmu; 752 + else 753 + *regmap = info->regmap_base; 754 + 755 + *reg = bank->drv[drv_num].offset; 756 + if ((bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) || 757 + (bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY)) 758 + *bit = (pin_num % 8) * 3; 759 + else 760 + *bit = (pin_num % 8) * 2; 761 + } 762 + 763 + static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = { 764 + { 2, 4, 8, 12, -1, -1, -1, -1 }, 765 + { 3, 6, 9, 12, -1, -1, -1, -1 }, 766 + { 5, 10, 15, 20, -1, -1, -1, -1 }, 767 + { 4, 6, 8, 10, 12, 14, 16, 18 }, 768 + { 4, 7, 10, 13, 16, 19, 22, 26 } 769 + }; 781 770 782 771 static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, 783 772 int pin_num) ··· 847 714 struct rockchip_pin_ctrl *ctrl = info->ctrl; 848 715 struct regmap *regmap; 849 716 int reg, ret; 850 - u32 data; 717 + u32 data, temp, rmask_bits; 851 718 u8 bit; 719 + int drv_type = bank->drv[pin_num / 8].drv_type; 852 720 853 721 ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit); 722 + 723 + switch (drv_type) { 724 + case DRV_TYPE_IO_1V8_3V0_AUTO: 725 + case DRV_TYPE_IO_3V3_ONLY: 726 + rmask_bits = RK3399_DRV_3BITS_PER_PIN; 727 + switch (bit) { 728 + case 0 ... 12: 729 + /* regular case, nothing to do */ 730 + break; 731 + case 15: 732 + /* 733 + * drive-strength offset is special, as it is 734 + * spread over 2 registers 735 + */ 736 + ret = regmap_read(regmap, reg, &data); 737 + if (ret) 738 + return ret; 739 + 740 + ret = regmap_read(regmap, reg + 0x4, &temp); 741 + if (ret) 742 + return ret; 743 + 744 + /* 745 + * the bit data[15] contains bit 0 of the value 746 + * while temp[1:0] contains bits 2 and 1 747 + */ 748 + data >>= 15; 749 + temp &= 0x3; 750 + temp <<= 1; 751 + data |= temp; 752 + 753 + return rockchip_perpin_drv_list[drv_type][data]; 754 + case 18 ... 21: 755 + /* setting fully enclosed in the second register */ 756 + reg += 4; 757 + bit -= 16; 758 + break; 759 + default: 760 + dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n", 761 + bit, drv_type); 762 + return -EINVAL; 763 + } 764 + 765 + break; 766 + case DRV_TYPE_IO_DEFAULT: 767 + case DRV_TYPE_IO_1V8_OR_3V0: 768 + case DRV_TYPE_IO_1V8_ONLY: 769 + rmask_bits = RK3288_DRV_BITS_PER_PIN; 770 + break; 771 + default: 772 + dev_err(info->dev, "unsupported pinctrl drive type: %d\n", 773 + drv_type); 774 + return -EINVAL; 775 + } 854 776 855 777 ret = regmap_read(regmap, reg, &data); 856 778 if (ret) 857 779 return ret; 858 780 859 781 data >>= bit; 860 - data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1; 782 + data &= (1 << rmask_bits) - 1; 861 783 862 - return rockchip_perpin_drv_list[data]; 784 + return rockchip_perpin_drv_list[drv_type][data]; 863 785 } 864 786 865 787 static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, ··· 925 737 struct regmap *regmap; 926 738 unsigned long flags; 927 739 int reg, ret, i; 928 - u32 data, rmask; 740 + u32 data, rmask, rmask_bits, temp; 929 741 u8 bit; 742 + int drv_type = bank->drv[pin_num / 8].drv_type; 743 + 744 + dev_dbg(info->dev, "setting drive of GPIO%d-%d to %d\n", 745 + bank->bank_num, pin_num, strength); 930 746 931 747 ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit); 932 748 933 749 ret = -EINVAL; 934 - for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list); i++) { 935 - if (rockchip_perpin_drv_list[i] == strength) { 750 + for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[drv_type]); i++) { 751 + if (rockchip_perpin_drv_list[drv_type][i] == strength) { 936 752 ret = i; 753 + break; 754 + } else if (rockchip_perpin_drv_list[drv_type][i] < 0) { 755 + ret = rockchip_perpin_drv_list[drv_type][i]; 937 756 break; 938 757 } 939 758 } ··· 953 758 954 759 spin_lock_irqsave(&bank->slock, flags); 955 760 761 + switch (drv_type) { 762 + case DRV_TYPE_IO_1V8_3V0_AUTO: 763 + case DRV_TYPE_IO_3V3_ONLY: 764 + rmask_bits = RK3399_DRV_3BITS_PER_PIN; 765 + switch (bit) { 766 + case 0 ... 12: 767 + /* regular case, nothing to do */ 768 + break; 769 + case 15: 770 + /* 771 + * drive-strength offset is special, as it is spread 772 + * over 2 registers, the bit data[15] contains bit 0 773 + * of the value while temp[1:0] contains bits 2 and 1 774 + */ 775 + data = (ret & 0x1) << 15; 776 + temp = (ret >> 0x1) & 0x3; 777 + 778 + rmask = BIT(15) | BIT(31); 779 + data |= BIT(31); 780 + ret = regmap_update_bits(regmap, reg, rmask, data); 781 + if (ret) { 782 + spin_unlock_irqrestore(&bank->slock, flags); 783 + return ret; 784 + } 785 + 786 + rmask = 0x3 | (0x3 << 16); 787 + temp |= (0x3 << 16); 788 + reg += 0x4; 789 + ret = regmap_update_bits(regmap, reg, rmask, temp); 790 + 791 + spin_unlock_irqrestore(&bank->slock, flags); 792 + return ret; 793 + case 18 ... 21: 794 + /* setting fully enclosed in the second register */ 795 + reg += 4; 796 + bit -= 16; 797 + break; 798 + default: 799 + spin_unlock_irqrestore(&bank->slock, flags); 800 + dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n", 801 + bit, drv_type); 802 + return -EINVAL; 803 + } 804 + break; 805 + case DRV_TYPE_IO_DEFAULT: 806 + case DRV_TYPE_IO_1V8_OR_3V0: 807 + case DRV_TYPE_IO_1V8_ONLY: 808 + rmask_bits = RK3288_DRV_BITS_PER_PIN; 809 + break; 810 + default: 811 + spin_unlock_irqrestore(&bank->slock, flags); 812 + dev_err(info->dev, "unsupported pinctrl drive type: %d\n", 813 + drv_type); 814 + return -EINVAL; 815 + } 816 + 956 817 /* enable the write to the equivalent lower bits */ 957 - data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16); 818 + data = ((1 << rmask_bits) - 1) << (bit + 16); 958 819 rmask = data | (data >> 16); 959 820 data |= (ret << bit); 960 821 ··· 1047 796 case RK3188: 1048 797 case RK3288: 1049 798 case RK3368: 799 + case RK3399: 1050 800 data >>= bit; 1051 801 data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; 1052 802 ··· 1104 852 case RK3188: 1105 853 case RK3288: 1106 854 case RK3368: 855 + case RK3399: 1107 856 spin_lock_irqsave(&bank->slock, flags); 1108 857 1109 858 /* enable the write to the equivalent lower bits */ ··· 1285 1032 case RK3188: 1286 1033 case RK3288: 1287 1034 case RK3368: 1035 + case RK3399: 1288 1036 return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT); 1289 1037 } 1290 1038 ··· 2146 1892 struct device_node *np; 2147 1893 struct rockchip_pin_ctrl *ctrl; 2148 1894 struct rockchip_pin_bank *bank; 2149 - int grf_offs, pmu_offs, i, j; 1895 + int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j; 2150 1896 2151 1897 match = of_match_node(rockchip_pinctrl_dt_match, node); 2152 1898 ctrl = (struct rockchip_pin_ctrl *)match->data; ··· 2170 1916 2171 1917 grf_offs = ctrl->grf_mux_offset; 2172 1918 pmu_offs = ctrl->pmu_mux_offset; 1919 + drv_pmu_offs = ctrl->pmu_drv_offset; 1920 + drv_grf_offs = ctrl->grf_drv_offset; 2173 1921 bank = ctrl->pin_banks; 2174 1922 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 2175 1923 int bank_pins = 0; ··· 2181 1925 bank->pin_base = ctrl->nr_pins; 2182 1926 ctrl->nr_pins += bank->nr_pins; 2183 1927 2184 - /* calculate iomux offsets */ 1928 + /* calculate iomux and drv offsets */ 2185 1929 for (j = 0; j < 4; j++) { 2186 1930 struct rockchip_iomux *iom = &bank->iomux[j]; 1931 + struct rockchip_drv *drv = &bank->drv[j]; 2187 1932 int inc; 2188 1933 2189 1934 if (bank_pins >= bank->nr_pins) 2190 1935 break; 2191 1936 2192 - /* preset offset value, set new start value */ 1937 + /* preset iomux offset value, set new start value */ 2193 1938 if (iom->offset >= 0) { 2194 1939 if (iom->type & IOMUX_SOURCE_PMU) 2195 1940 pmu_offs = iom->offset; 2196 1941 else 2197 1942 grf_offs = iom->offset; 2198 - } else { /* set current offset */ 1943 + } else { /* set current iomux offset */ 2199 1944 iom->offset = (iom->type & IOMUX_SOURCE_PMU) ? 2200 1945 pmu_offs : grf_offs; 2201 1946 } 2202 1947 2203 - dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n", 2204 - i, j, iom->offset); 1948 + /* preset drv offset value, set new start value */ 1949 + if (drv->offset >= 0) { 1950 + if (iom->type & IOMUX_SOURCE_PMU) 1951 + drv_pmu_offs = drv->offset; 1952 + else 1953 + drv_grf_offs = drv->offset; 1954 + } else { /* set current drv offset */ 1955 + drv->offset = (iom->type & IOMUX_SOURCE_PMU) ? 1956 + drv_pmu_offs : drv_grf_offs; 1957 + } 1958 + 1959 + dev_dbg(d->dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n", 1960 + i, j, iom->offset, drv->offset); 2205 1961 2206 1962 /* 2207 1963 * Increase offset according to iomux width. ··· 2224 1956 pmu_offs += inc; 2225 1957 else 2226 1958 grf_offs += inc; 1959 + 1960 + /* 1961 + * Increase offset according to drv width. 1962 + * 3bit drive-strenth'es are spread over two registers. 1963 + */ 1964 + if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) || 1965 + (drv->drv_type == DRV_TYPE_IO_3V3_ONLY)) 1966 + inc = 8; 1967 + else 1968 + inc = 4; 1969 + 1970 + if (iom->type & IOMUX_SOURCE_PMU) 1971 + drv_pmu_offs += inc; 1972 + else 1973 + drv_grf_offs += inc; 2227 1974 2228 1975 bank_pins += 8; 2229 1976 } ··· 2540 2257 .drv_calc_reg = rk3368_calc_drv_reg_and_bit, 2541 2258 }; 2542 2259 2260 + static struct rockchip_pin_bank rk3399_pin_banks[] = { 2261 + PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU, 2262 + IOMUX_SOURCE_PMU, 2263 + IOMUX_SOURCE_PMU, 2264 + IOMUX_SOURCE_PMU, 2265 + DRV_TYPE_IO_1V8_ONLY, 2266 + DRV_TYPE_IO_1V8_ONLY, 2267 + DRV_TYPE_IO_DEFAULT, 2268 + DRV_TYPE_IO_DEFAULT, 2269 + 0x0, 2270 + 0x8, 2271 + -1, 2272 + -1 2273 + ), 2274 + PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU, 2275 + IOMUX_SOURCE_PMU, 2276 + IOMUX_SOURCE_PMU, 2277 + IOMUX_SOURCE_PMU, 2278 + DRV_TYPE_IO_1V8_OR_3V0, 2279 + DRV_TYPE_IO_1V8_OR_3V0, 2280 + DRV_TYPE_IO_1V8_OR_3V0, 2281 + DRV_TYPE_IO_1V8_OR_3V0, 2282 + 0x20, 2283 + 0x28, 2284 + 0x30, 2285 + 0x38 2286 + ), 2287 + PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0, 2288 + DRV_TYPE_IO_1V8_OR_3V0, 2289 + DRV_TYPE_IO_1V8_ONLY, 2290 + DRV_TYPE_IO_1V8_ONLY 2291 + ), 2292 + PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY, 2293 + DRV_TYPE_IO_3V3_ONLY, 2294 + DRV_TYPE_IO_3V3_ONLY, 2295 + DRV_TYPE_IO_1V8_OR_3V0 2296 + ), 2297 + PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0, 2298 + DRV_TYPE_IO_1V8_3V0_AUTO, 2299 + DRV_TYPE_IO_1V8_OR_3V0, 2300 + DRV_TYPE_IO_1V8_OR_3V0 2301 + ), 2302 + }; 2303 + 2304 + static struct rockchip_pin_ctrl rk3399_pin_ctrl = { 2305 + .pin_banks = rk3399_pin_banks, 2306 + .nr_banks = ARRAY_SIZE(rk3399_pin_banks), 2307 + .label = "RK3399-GPIO", 2308 + .type = RK3399, 2309 + .grf_mux_offset = 0xe000, 2310 + .pmu_mux_offset = 0x0, 2311 + .grf_drv_offset = 0xe100, 2312 + .pmu_drv_offset = 0x80, 2313 + .pull_calc_reg = rk3399_calc_pull_reg_and_bit, 2314 + .drv_calc_reg = rk3399_calc_drv_reg_and_bit, 2315 + }; 2543 2316 2544 2317 static const struct of_device_id rockchip_pinctrl_dt_match[] = { 2545 2318 { .compatible = "rockchip,rk2928-pinctrl", ··· 2614 2275 .data = (void *)&rk3288_pin_ctrl }, 2615 2276 { .compatible = "rockchip,rk3368-pinctrl", 2616 2277 .data = (void *)&rk3368_pin_ctrl }, 2278 + { .compatible = "rockchip,rk3399-pinctrl", 2279 + .data = (void *)&rk3399_pin_ctrl }, 2617 2280 {}, 2618 2281 }; 2619 2282 MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);