> Feedback-ID: i5cf14421:Fastmail > From: joshua stein <j...@jcs.org> > > --- > sys/dev/fdt/rkpinctrl.c | 305 +++++++++++++++++++++++++++++++++++++++- > 1 file changed, 303 insertions(+), 2 deletions(-)
A few comments on this one. > > diff --git a/sys/dev/fdt/rkpinctrl.c b/sys/dev/fdt/rkpinctrl.c > index 6e747d5987b..18353e9bdfe 100644 > --- a/sys/dev/fdt/rkpinctrl.c > +++ b/sys/dev/fdt/rkpinctrl.c > @@ -65,6 +65,10 @@ > #define RK_PD6 30 > #define RK_PD7 31 > > +/* RK3128 registers */ > +#define RK3128_GRF_GPIO0A_IOMUX 0x00a8 > +#define RK3128_GRF_GPIO0L_PULL 0x0118 > + > /* RK3288 registers */ > #define RK3288_GRF_GPIO1A_IOMUX 0x0000 > #define RK3288_PMUGRF_GPIO0A_IOMUX 0x0084 > @@ -141,6 +145,7 @@ struct cfdriver rkpinctrl_cd = { > NULL, "rkpinctrl", DV_DULL > }; > > +int rk3128_pinctrl(uint32_t, void *); > int rk3288_pinctrl(uint32_t, void *); > int rk3308_pinctrl(uint32_t, void *); > int rk3328_pinctrl(uint32_t, void *); > @@ -154,7 +159,8 @@ rkpinctrl_match(struct device *parent, void *match, void > *aux) > { > struct fdt_attach_args *faa = aux; > > - return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") || > + return (OF_is_compatible(faa->fa_node, "rockchip,rk3128-pinctrl") || > + OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") || > OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl") || > OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") || > OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl") || > @@ -180,7 +186,9 @@ rkpinctrl_attach(struct device *parent, struct device > *self, void *aux) > return; > } > > - if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl")) > + if (OF_is_compatible(faa->fa_node, "rockchip,rk3128-pinctrl")) > + pinctrl_register(faa->fa_node, rk3128_pinctrl, sc); > + else if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl")) > pinctrl_register(faa->fa_node, rk3288_pinctrl, sc); > else if (OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl")) > pinctrl_register(faa->fa_node, rk3308_pinctrl, sc); > @@ -199,6 +207,299 @@ rkpinctrl_attach(struct device *parent, struct device > *self, void *aux) > simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa); > } > > +/* > + * Rockchip RK3128 > + */ > + > +int > +rk3128_pull(uint32_t bank, uint32_t idx, uint32_t phandle) > +{ > + int node; > + > + node = OF_getnodebyphandle(phandle); > + if (node == 0) > + return -1; > + > + if (OF_getproplen(node, "bias-pull-pin-default") == 0) > + return -1; This one isn't really needed, and we don't include it for the other SoCs. > + if (OF_getproplen(node, "bias-disable") == 0) > + return 0; > + if (OF_getproplen(node, "bias-pull-up") == 0) > + return 1; > + if (OF_getproplen(node, "bias-pull-down") == 0) > + return 2; There is only 1 "pull" bit per pin. So you can't return 2 here. It seems that the hardware doesn't let you control up or down. So this should probably return 1 for pull-down. > + > + return -1; > +} > + > +static struct rk3128_gpio_pin { > + int bank; > + int pin; > + int func; > + int start; > + int bits; > +} rk3128_gpio_pins[] = { > + /* GRF_GPIO0A_IOMUX */ > + { 0, RK_PA0, 1, 0, 1 }, /* i2c0_scl */ > + { 0, RK_PA1, 1, 2, 1 }, /* i2c0_sda */ > + { 0, RK_PA2, 1, 4, 1 }, /* i2c1_scl */ > + { 0, RK_PA3, 1, 6, 2 }, /* i2c1_sda */ > + { 0, RK_PA3, 2, 6, 2 }, /* mmc1_cmd */ > + { 0, RK_PA6, 1, 12, 2 }, /* i2c3_scl */ > + { 0, RK_PA6, 2, 12, 2 }, /* hdmi_ddcscl */ > + { 0, RK_PA7, 1, 14, 2 }, /* i2c3_sda */ > + { 0, RK_PA7, 2, 14, 2 }, /* hdmi_ddcsda */ > + /* GRF_GPIO0B_IOMUX */ > + { 0, RK_PB0, 1, 0, 1 }, /* i2s_mclk */ > + { 0, RK_PB1, 1, 2, 2 }, /* i2s_sclk */ > + { 0, RK_PB1, 2, 2, 2 }, /* spi_clk */ > + { 0, RK_PB3, 1, 6, 2 }, /* i2s_lrckrx */ > + { 0, RK_PB3, 2, 6, 2 }, /* spi_txd */ > + { 0, RK_PB4, 1, 8, 1 }, /* i2s_lrcktx */ > + { 0, RK_PB5, 1, 10, 2 }, /* i2s_sdo */ > + { 0, RK_PB5, 1, 10, 2 }, /* spi_rxd */ > + { 0, RK_PB6, 1, 12, 2 }, /* i2s_sdi */ > + { 0, RK_PB6, 2, 12, 2 }, /* spi_csn0 */ > + { 0, RK_PB7, 1, 14, 1 }, /* hdmi_hotplugin */ > + /* GRF_GPIO0C_IOMUX */ > + { 0, RK_PC1, 1, 2, 2 }, /* sc_io */ > + { 0, RK_PC1, 2, 2, 2 }, /* uart0_rstn */ > + { 0, RK_PC4, 1, 8, 1 }, /* hdmi_cecsda */ > + { 0, RK_PC7, 1, 14, 1 }, /* nand_cs1 */ > + /* GRF_GPIO0D_IOMUX */ > + { 0, RK_PD0, 1, 0, 2 }, /* uart2_rtsn */ > + { 0, RK_PD0, 2, 0, 2 }, /* pmic_sleep */ > + { 0, RK_PD1, 1, 2, 1 }, /* uart2_ctsn */ > + { 0, RK_PD2, 1, 4, 1 }, /* pwm_0 */ > + { 0, RK_PD3, 1, 6, 1 }, /* pwm_1 */ > + { 0, RK_PD4, 1, 8, 1 }, /* pwm_2 */ > + { 0, RK_PD6, 1, 12, 1 }, /* mmc1_pwren */ > + > + /* GRF_GPIO1A_IOMUX */ > + { 1, RK_PA0, 1, 0, 2 }, /* i2s_mclk */ > + { 1, RK_PA0, 2, 0, 2 }, /* sdmmc_clkout */ > + { 1, RK_PA0, 3, 0, 2 }, /* xin32k */ > + { 1, RK_PA1, 1, 2, 2 }, /* i2s_sclk */ > + { 1, RK_PA1, 2, 2, 2 }, /* sdmmc_data0 */ > + { 1, RK_PA1, 3, 2, 2 }, /* pmic_sleep */ > + { 1, RK_PA2, 1, 4, 2 }, /* i2s_lrckrx */ > + { 1, RK_PA2, 2, 4, 2 }, /* sdmmc_data1 */ > + { 1, RK_PA3, 1, 6, 1 }, /* i2s_lrcktx */ > + { 1, RK_PA4, 1, 8, 2 }, /* i2s_sdo */ > + { 1, RK_PA4, 2, 8, 2 }, /* sdmmc_data2 */ > + { 1, RK_PA5, 1, 10, 2 }, /* i2s_sdi */ > + { 1, RK_PA5, 2, 10, 2 }, /* sdmmc_data3 */ > + { 1, RK_PA7, 1, 14, 1 }, /* mmc0_wrprt */ > + /* GRF_GPIO1B_IOMUX */ > + { 1, RK_PB0, 1, 0, 2 }, /* spi_clk */ > + { 1, RK_PB0, 2, 0, 2 }, /* uart1_ctsn */ > + { 1, RK_PB1, 1, 2, 2 }, /* spi_txd */ > + { 1, RK_PB1, 2, 2, 2 }, /* uart1_sout */ > + { 1, RK_PB2, 1, 4, 2 }, /* spi_rxd */ > + { 1, RK_PB2, 2, 4, 2 }, /* uart1_sin */ > + { 1, RK_PB3, 1, 6, 2 }, /* spi_csn0 */ > + { 1, RK_PB3, 2, 6, 2 }, /* uart1_rtsn */ > + { 1, RK_PB4, 1, 8, 1 }, /* spi_csn1 */ > + { 1, RK_PB6, 1, 12, 1 }, /* mmc0_pwren */ > + { 1, RK_PB7, 1, 14, 1 }, /* mmc0_cmd */ > + /* GRF_GPIO1C_IOMUX */ > + { 1, RK_PC0, 1, 0, 1 }, /* mmc0_clkout */ > + { 1, RK_PC1, 1, 2, 1 }, /* mmc0_detn */ > + { 1, RK_PC2, 1, 4, 2 }, /* mmc0_d0 */ > + { 1, RK_PC2, 2, 4, 2 }, /* uart2_tx */ > + { 1, RK_PC3, 1, 6, 2 }, /* mmc0_d1 */ > + { 1, RK_PC3, 2, 6, 2 }, /* uart2_rx */ > + { 1, RK_PC4, 1, 8, 2 }, /* jtag_tck */ > + { 1, RK_PC4, 2, 8, 2 }, /* mmc0_d2 */ > + { 1, RK_PC5, 1, 10, 2 }, /* jtag_tms */ > + { 1, RK_PC5, 2, 10, 2 }, /* mmc0_d3 */ > + { 1, RK_PC6, 1, 12, 2 }, /* nand_cs2 */ > + { 1, RK_PC6, 2, 12, 2 }, /* emmc_cmd */ > + { 1, RK_PC7, 1, 14, 2 }, /* nand_cs3 */ > + { 1, RK_PC7, 2, 14, 2 }, /* emmc_rstnout */ > + /* GRF_GPIO1D_IOMUX */ > + { 1, RK_PD0, 1, 0, 2 }, /* nand_d0 */ > + { 1, RK_PD0, 2, 0, 2 }, /* emmc_d0 */ > + { 1, RK_PD0, 3, 0, 2 }, /* sfc_d0 */ > + { 1, RK_PD1, 1, 2, 2 }, /* nand_d1 */ > + { 1, RK_PD1, 2, 2, 2 }, /* emmc_d1 */ > + { 1, RK_PD1, 3, 2, 2 }, /* sfc_d1 */ > + { 1, RK_PD2, 1, 4, 2 }, /* nand_d2 */ > + { 1, RK_PD2, 2, 4, 2 }, /* emmc_d2 */ > + { 1, RK_PD2, 3, 4, 2 }, /* sfc_d2 */ > + { 1, RK_PD3, 1, 6, 2 }, /* nand_d3 */ > + { 1, RK_PD3, 2, 6, 2 }, /* emmc_d3 */ > + { 1, RK_PD3, 3, 6, 2 }, /* sfc_d3 */ > + { 1, RK_PD4, 1, 8, 2 }, /* nand_d4 */ > + { 1, RK_PD4, 2, 8, 2 }, /* emmc_d4 */ > + { 1, RK_PD4, 3, 8, 2 }, /* spi_rxd1 */ > + { 1, RK_PD5, 1, 10, 2 }, /* nand_d5 */ > + { 1, RK_PD5, 2, 10, 2 }, /* emmc_d5 */ > + { 1, RK_PD5, 3, 10, 2 }, /* spi_txd1 */ > + { 1, RK_PD6, 1, 12, 2 }, /* nand_d6 */ > + { 1, RK_PD6, 2, 12, 2 }, /* emmc_d6 */ > + { 1, RK_PD6, 3, 12, 2 }, /* spi_csn0 */ > + { 1, RK_PD7, 1, 14, 2 }, /* nand_d7 */ > + { 1, RK_PD7, 2, 14, 2 }, /* emmc_d7 */ > + { 1, RK_PD7, 3, 14, 2 }, /* spi_csn1 */ > + > + /* GRF_GPIO2A_IOMUX */ > + { 2, RK_PA0, 1, 0, 2 }, /* nand_ale */ > + { 2, RK_PA0, 2, 0, 2 }, /* spi_clk */ > + { 2, RK_PA1, 1, 2, 2 }, /* nand_cle */ > + { 2, RK_PA2, 1, 4, 2 }, /* nand_wrn */ > + { 2, RK_PA2, 2, 4, 2 }, /* sfc_csn0 */ > + { 2, RK_PA3, 1, 6, 2 }, /* nand_rdn */ > + { 2, RK_PA3, 2, 6, 2 }, /* sfc_csn1 */ > + { 2, RK_PA4, 1, 8, 2 }, /* nand_rdy */ > + { 2, RK_PA4, 2, 8, 2 }, /* emmc_cmd */ > + { 2, RK_PA4, 3, 8, 2 }, /* sfc_clk */ > + { 2, RK_PA5, 1, 10, 2 }, /* nand_wp */ > + { 2, RK_PA5, 2, 10, 2 }, /* emmc_pwren */ > + { 2, RK_PA6, 1, 12, 1 }, /* nand_cs0 */ > + { 2, RK_PA7, 1, 14, 2 }, /* nand_dqs */ > + { 2, RK_PA7, 2, 14, 2 }, /* emmc_clkout */ > + /* GRF_GPIO2B_IOMUX */ > + { 2, RK_PB0, 1, 0, 2 }, /* lcdc0_dclk */ > + { 2, RK_PB0, 2, 0, 2 }, /* ebc_sdclk */ > + { 2, RK_PB0, 3, 0, 2 }, /* gmac_rxdv */ > + { 2, RK_PB1, 1, 2, 2 }, /* lcdc0_hsync */ > + { 2, RK_PB1, 2, 2, 2 }, /* ebc_sdle */ > + { 2, RK_PB1, 3, 2, 2 }, /* gmac_txclk */ > + { 2, RK_PB2, 1, 4, 2 }, /* lcdc0_vsync */ > + { 2, RK_PB2, 2, 4, 2 }, /* ebc_sdoe */ > + { 2, RK_PB2, 3, 4, 2 }, /* gmac_crs */ > + { 2, RK_PB3, 1, 6, 2 }, /* lcdc0_den */ > + { 2, RK_PB3, 2, 6, 2 }, /* ebc_gdclk */ > + { 2, RK_PB3, 3, 6, 2 }, /* gmac_rxclk */ > + { 2, RK_PB4, 1, 8, 2 }, /* lcdc0_d10 */ > + { 2, RK_PB4, 2, 8, 2 }, /* ebc_sdce2 */ > + { 2, RK_PB4, 3, 8, 2 }, /* gmac_mdio */ > + { 2, RK_PB5, 1, 10, 2 }, /* lcdc0_d11 */ > + { 2, RK_PB5, 2, 10, 2 }, /* ebc_sdce3 */ > + { 2, RK_PB5, 3, 10, 2 }, /* gmac_txen */ > + { 2, RK_PB6, 1, 12, 2 }, /* lcdc0_d12 */ > + { 2, RK_PB6, 2, 12, 2 }, /* ebc_sdce4 */ > + { 2, RK_PB6, 3, 12, 2 }, /* gmac_clk */ > + { 2, RK_PB7, 1, 14, 2 }, /* lcdc0_d13 */ > + { 2, RK_PB7, 2, 14, 2 }, /* ebc_sdce5 */ > + { 2, RK_PB7, 3, 14, 2 }, /* gmac_rxer */ > + /* GRF_GPIO2C_IOMUX */ > + { 2, RK_PC0, 1, 0, 2 }, /* lcdc0_d14 */ > + { 2, RK_PC0, 2, 0, 2 }, /* ebc_vcom */ > + { 2, RK_PC0, 3, 0, 2 }, /* gmac_rxd1 */ > + { 2, RK_PC1, 1, 2, 2 }, /* lcdc0_d15 */ > + { 2, RK_PC1, 2, 2, 2 }, /* ebc_gdoe */ > + { 2, RK_PC1, 3, 2, 2 }, /* gmac_rxd0 */ > + { 2, RK_PC2, 1, 4, 2 }, /* lcdc0_d16 */ > + { 2, RK_PC2, 2, 4, 2 }, /* ebc_gdsp */ > + { 2, RK_PC2, 3, 4, 2 }, /* gmac_txd1 */ > + { 2, RK_PC3, 1, 6, 2 }, /* lcdc0_d17 */ > + { 2, RK_PC3, 2, 6, 2 }, /* ebc_gdpwr0 */ > + { 2, RK_PC3, 3, 6, 2 }, /* gmac_txd0 */ > + /* GRF_GPIO2D_IOMUX */ > + { 2, RK_PD1, 1, 2, 2 }, /* lcdc0_d23 */ > + { 2, RK_PD1, 1, 2, 2 }, /* lcdc0_d23 */ > + { 2, RK_PD1, 2, 2, 2 }, /* ebc_gdpwr2 */ > + { 2, RK_PD1, 3, 2, 2 }, /* gmac_mdc */ > + { 2, RK_PD2, 1, 4, 2 }, /* sc_rst */ > + { 2, RK_PD2, 2, 4, 2 }, /* uart0_sout */ > + { 2, RK_PD3, 1, 6, 2 }, /* sc_clk */ > + { 2, RK_PD3, 2, 6, 2 }, /* uart0_sin */ > + { 2, RK_PD4, 1, 10, 2 }, /* sc_det */ > + { 2, RK_PD4, 2, 10, 2 }, /* uart0_ctsn */ > + { 2, RK_PD0, 1, 12, 3 }, /* lcdc0_d22 */ > + { 2, RK_PD0, 2, 12, 3 }, /* ebc_gdpwr1 */ > + { 2, RK_PD0, 3, 12, 3 }, /* gps_clk */ > + { 2, RK_PD0, 4, 12, 3 }, /* gmac_col */ > + > + /* GRF_GPIO3A_IOMUX */ > + /* GRF_GPIO3B_IOMUX */ > + { 3, RK_PA3, 1, 6, 2 }, /* testclk_out, why A3 on gpioB? */ > + /* GRF_GPIO3C_IOMUX */ > + { 3, RK_PC1, 1, 2, 2 }, /* otg_drvvbus */ > + /* GRF_GPIO3D_IOMUX */ > + { 3, RK_PD2, 1, 4, 1 }, /* pwm_irin */ > + { 3, RK_PD3, 1, 6, 1 }, /* spdif_tx */ > +}; This large table does not really provide much benefit; if we're setting an unsupported value that just means the device tree is wrong. It is true that there are a few "weird" muxes in there that don't follow the standard pattern of having 2 bits per pin. But I think those could be handled with a few lines of code. Or a smaller table that just has the exceptions. > + > +int > +rk3128_pinctrl(uint32_t phandle, void *cookie) > +{ > + struct rkpinctrl_softc *sc = cookie; > + uint32_t *pins; > + int node, len, i; > + > + KASSERT(sc->sc_grf); > + > + node = OF_getnodebyphandle(phandle); > + if (node == 0) > + return -1; > + > + len = OF_getproplen(node, "rockchip,pins"); > + if (len <= 0) > + return -1; > + > + pins = malloc(len, M_TEMP, M_WAITOK); > + if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) > + goto fail; > + > + for (i = 0; i < len / sizeof(uint32_t); i += 4) { > + struct regmap *rm = sc->sc_grf; > + struct rk3128_gpio_pin *pin = NULL; > + bus_size_t off; > + uint32_t bank, idx, func; > + int pull, s, n; > + > + bank = pins[i]; > + idx = pins[i + 1]; > + func = pins[i + 2]; > + > + pin = NULL; > + for (n = 0; n < nitems(rk3128_gpio_pins); n++) { > + if (rk3128_gpio_pins[n].bank == bank && > + rk3128_gpio_pins[n].pin == idx && > + rk3128_gpio_pins[n].func == func) { > + pin = &rk3128_gpio_pins[n]; > + break; > + } > + } > + > + if (!pin) { > + printf("%s: missing def for bank %d pin %d func %d\n", > + __func__, bank, idx, func); > + continue; > + } > + > + off = RK3128_GRF_GPIO0A_IOMUX + (bank * 0x10) + > + ((idx / 8) * 0x04); > + pull = rk3128_pull(bank, func, pins[i + 3]); > + > + s = splhigh(); > + > + /* 3@5:4 -> 0b0000000000110000 0000000000110000 */ Leftover note-to-self? > + regmap_write_4(rm, off, > + (((1 << pin->bits) - 1) << pin->start) << 16 | > + (pin->func << pin->start)); > + > + /* GPIO pad pull down and pull up control */ > + if (pull >= 0) > + /* 2 pin 17 (pc1) -> 0b00000010 0b000000?0 */ Likewise? > + regmap_write_4(rm, RK3128_GRF_GPIO0L_PULL + > + ((idx / 16) * 0x4), > + ((idx % 16) << 16) | (pull << (idx % 16))); > + > + splx(s); > + } > + > + free(pins, M_TEMP, len); > + return 0; > + > +fail: > + free(pins, M_TEMP, len); > + return -1; > +} > + > /* > * Rockchip RK3288 > */ > -- > 2.47.1 > >