diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/sunxi_gpio.c | 130 | ||||
-rw-r--r-- | drivers/i2c/sun6i_p2wi.c | 27 | ||||
-rw-r--r-- | drivers/i2c/sun8i_rsb.c | 61 | ||||
-rw-r--r-- | drivers/net/sun8i_emac.c | 90 | ||||
-rw-r--r-- | drivers/net/sunxi_emac.c | 7 | ||||
-rw-r--r-- | drivers/pinctrl/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 2 | ||||
-rw-r--r-- | drivers/pinctrl/sunxi/Kconfig | 127 | ||||
-rw-r--r-- | drivers/pinctrl/sunxi/Makefile | 3 | ||||
-rw-r--r-- | drivers/pinctrl/sunxi/pinctrl-sunxi.c | 897 | ||||
-rw-r--r-- | drivers/pwm/sunxi_pwm.c | 11 | ||||
-rw-r--r-- | drivers/spi/spi-sunxi.c | 84 |
12 files changed, 1085 insertions, 355 deletions
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 6c3c10862c..1e85db179a 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -16,15 +16,8 @@ #include <malloc.h> #include <asm/io.h> #include <asm/gpio.h> -#include <dm/device-internal.h> #include <dt-bindings/gpio/gpio.h> -struct sunxi_gpio_plat { - struct sunxi_gpio *regs; - const char *bank_name; /* Name of bank, e.g. "B" */ - int gpio_count; -}; - #if !CONFIG_IS_ENABLED(DM_GPIO) static int sunxi_gpio_output(u32 pin, u32 val) { @@ -211,28 +204,6 @@ static const struct dm_gpio_ops gpio_sunxi_ops = { .set_flags = sunxi_gpio_set_flags, }; -/** - * Returns the name of a GPIO bank - * - * GPIO banks are named A, B, C, ... - * - * @bank: Bank number (0, 1..n-1) - * Return: allocated string containing the name - */ -static char *gpio_bank_name(int bank) -{ - char *name; - - name = malloc(3); - if (name) { - name[0] = 'P'; - name[1] = 'A' + bank; - name[2] = '\0'; - } - - return name; -} - static int gpio_sunxi_probe(struct udevice *dev) { struct sunxi_gpio_plat *plat = dev_get_plat(dev); @@ -240,114 +211,17 @@ static int gpio_sunxi_probe(struct udevice *dev) /* Tell the uclass how many GPIOs we have */ if (plat) { - uc_priv->gpio_count = plat->gpio_count; + uc_priv->gpio_count = SUNXI_GPIOS_PER_BANK; uc_priv->bank_name = plat->bank_name; } return 0; } -struct sunxi_gpio_soc_data { - int start; - int no_banks; -}; - -/** - * We have a top-level GPIO device with no actual GPIOs. It has a child - * device for each Sunxi bank. - */ -static int gpio_sunxi_bind(struct udevice *parent) -{ - struct sunxi_gpio_soc_data *soc_data = - (struct sunxi_gpio_soc_data *)dev_get_driver_data(parent); - struct sunxi_gpio_plat *plat = dev_get_plat(parent); - struct sunxi_gpio_reg *ctlr; - int bank, ret; - - /* If this is a child device, there is nothing to do here */ - if (plat) - return 0; - - ctlr = dev_read_addr_ptr(parent); - for (bank = 0; bank < soc_data->no_banks; bank++) { - struct sunxi_gpio_plat *plat; - struct udevice *dev; - - plat = calloc(1, sizeof(*plat)); - if (!plat) - return -ENOMEM; - plat->regs = &ctlr->gpio_bank[bank]; - plat->bank_name = gpio_bank_name(soc_data->start + bank); - plat->gpio_count = SUNXI_GPIOS_PER_BANK; - - ret = device_bind(parent, parent->driver, plat->bank_name, plat, - dev_ofnode(parent), &dev); - if (ret) - return ret; - } - - return 0; -} - -static const struct sunxi_gpio_soc_data soc_data_a_all = { - .start = 0, - .no_banks = SUNXI_GPIO_BANKS, -}; - -static const struct sunxi_gpio_soc_data soc_data_l_1 = { - .start = 'L' - 'A', - .no_banks = 1, -}; - -static const struct sunxi_gpio_soc_data soc_data_l_2 = { - .start = 'L' - 'A', - .no_banks = 2, -}; - -static const struct sunxi_gpio_soc_data soc_data_l_3 = { - .start = 'L' - 'A', - .no_banks = 3, -}; - -#define ID(_compat_, _soc_data_) \ - { .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ } - -static const struct udevice_id sunxi_gpio_ids[] = { - ID("allwinner,sun4i-a10-pinctrl", a_all), - ID("allwinner,sun5i-a10s-pinctrl", a_all), - ID("allwinner,sun5i-a13-pinctrl", a_all), - ID("allwinner,sun50i-h5-pinctrl", a_all), - ID("allwinner,sun6i-a31-pinctrl", a_all), - ID("allwinner,sun6i-a31s-pinctrl", a_all), - ID("allwinner,sun7i-a20-pinctrl", a_all), - ID("allwinner,sun8i-a23-pinctrl", a_all), - ID("allwinner,sun8i-a33-pinctrl", a_all), - ID("allwinner,sun8i-a83t-pinctrl", a_all), - ID("allwinner,sun8i-h3-pinctrl", a_all), - ID("allwinner,sun8i-r40-pinctrl", a_all), - ID("allwinner,sun8i-v3-pinctrl", a_all), - ID("allwinner,sun8i-v3s-pinctrl", a_all), - ID("allwinner,sun9i-a80-pinctrl", a_all), - ID("allwinner,sun50i-a64-pinctrl", a_all), - ID("allwinner,sun50i-h6-pinctrl", a_all), - ID("allwinner,sun50i-h616-pinctrl", a_all), - ID("allwinner,sun6i-a31-r-pinctrl", l_2), - ID("allwinner,sun8i-a23-r-pinctrl", l_1), - ID("allwinner,sun8i-a83t-r-pinctrl", l_1), - ID("allwinner,sun8i-h3-r-pinctrl", l_1), - ID("allwinner,sun9i-a80-r-pinctrl", l_3), - ID("allwinner,sun50i-a64-r-pinctrl", l_1), - ID("allwinner,sun50i-h6-r-pinctrl", l_2), - ID("allwinner,sun50i-h616-r-pinctrl", l_1), - { } -}; - U_BOOT_DRIVER(gpio_sunxi) = { .name = "gpio_sunxi", .id = UCLASS_GPIO, - .ops = &gpio_sunxi_ops, - .of_match = sunxi_gpio_ids, - .bind = gpio_sunxi_bind, .probe = gpio_sunxi_probe, + .ops = &gpio_sunxi_ops, }; #endif /* DM_GPIO */ diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c index c9e1b3fcd5..d221323295 100644 --- a/drivers/i2c/sun6i_p2wi.c +++ b/drivers/i2c/sun6i_p2wi.c @@ -14,10 +14,12 @@ */ #include <axp_pmic.h> +#include <clk.h> #include <common.h> #include <dm.h> #include <errno.h> #include <i2c.h> +#include <reset.h> #include <time.h> #include <asm/io.h> #include <asm/arch/cpu.h> @@ -102,12 +104,6 @@ static int sun6i_p2wi_change_to_p2wi_mode(struct sunxi_p2wi_reg *base, static void sun6i_p2wi_init(struct sunxi_p2wi_reg *base) { - /* Enable p2wi and PIO clk, and de-assert their resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI); - - sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK); - sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA); - /* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */ writel(P2WI_CTRL_RESET, &base->ctrl); sdelay(0x100); @@ -142,6 +138,12 @@ void p2wi_init(void) { struct sunxi_p2wi_reg *base = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; + /* Enable p2wi and PIO clk, and de-assert their resets */ + prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI); + + sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK); + sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA); + sun6i_p2wi_init(base); } #endif @@ -180,9 +182,19 @@ static int sun6i_p2wi_probe_chip(struct udevice *bus, uint chip_addr, static int sun6i_p2wi_probe(struct udevice *bus) { struct sun6i_p2wi_priv *priv = dev_get_priv(bus); + struct reset_ctl *reset; + struct clk *clk; priv->base = dev_read_addr_ptr(bus); + reset = devm_reset_control_get(bus, NULL); + if (!IS_ERR(reset)) + reset_deassert(reset); + + clk = devm_clk_get(bus, NULL); + if (!IS_ERR(clk)) + clk_enable(clk); + sun6i_p2wi_init(priv->base); return 0; @@ -191,11 +203,12 @@ static int sun6i_p2wi_probe(struct udevice *bus) static int sun6i_p2wi_child_pre_probe(struct udevice *child) { struct dm_i2c_chip *chip = dev_get_parent_plat(child); + struct udevice *bus = child->parent; /* Ensure each transfer is for a single register. */ chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS; - return 0; + return sun6i_p2wi_probe_chip(bus, chip->chip_addr, 0); } static const struct dm_i2c_ops sun6i_p2wi_ops = { diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c index 716b245a00..47fa05b6d1 100644 --- a/drivers/i2c/sun8i_rsb.c +++ b/drivers/i2c/sun8i_rsb.c @@ -9,10 +9,12 @@ */ #include <axp_pmic.h> +#include <clk.h> #include <common.h> #include <dm.h> #include <errno.h> #include <i2c.h> +#include <reset.h> #include <time.h> #include <asm/arch/cpu.h> #include <asm/arch/gpio.h> @@ -95,27 +97,6 @@ static int sun8i_rsb_set_device_address(struct sunxi_rsb_reg *base, return sun8i_rsb_do_trans(base); } -static void sun8i_rsb_cfg_io(void) -{ -#ifdef CONFIG_MACH_SUN8I - sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB); - sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB); - sunxi_gpio_set_pull(SUNXI_GPL(0), 1); - sunxi_gpio_set_pull(SUNXI_GPL(1), 1); - sunxi_gpio_set_drv(SUNXI_GPL(0), 2); - sunxi_gpio_set_drv(SUNXI_GPL(1), 2); -#elif defined CONFIG_MACH_SUN9I - sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB); - sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB); - sunxi_gpio_set_pull(SUNXI_GPN(0), 1); - sunxi_gpio_set_pull(SUNXI_GPN(1), 1); - sunxi_gpio_set_drv(SUNXI_GPN(0), 2); - sunxi_gpio_set_drv(SUNXI_GPN(1), 2); -#else -#error unsupported MACH_SUNXI -#endif -} - static void sun8i_rsb_set_clk(struct sunxi_rsb_reg *base) { u32 div = 0; @@ -147,12 +128,6 @@ static int sun8i_rsb_set_device_mode(struct sunxi_rsb_reg *base) static int sun8i_rsb_init(struct sunxi_rsb_reg *base) { - /* Enable RSB and PIO clk, and de-assert their resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB); - - /* Setup external pins */ - sun8i_rsb_cfg_io(); - writel(RSB_CTRL_SOFT_RST, &base->ctrl); sun8i_rsb_set_clk(base); @@ -185,6 +160,25 @@ int rsb_init(void) { struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; + /* Enable RSB and PIO clk, and de-assert their resets */ + prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB); + + if (IS_ENABLED(CONFIG_MACH_SUN9I)) { + sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB); + sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB); + sunxi_gpio_set_pull(SUNXI_GPN(0), 1); + sunxi_gpio_set_pull(SUNXI_GPN(1), 1); + sunxi_gpio_set_drv(SUNXI_GPN(0), 2); + sunxi_gpio_set_drv(SUNXI_GPN(1), 2); + } else { + sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB); + sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB); + sunxi_gpio_set_pull(SUNXI_GPL(0), 1); + sunxi_gpio_set_pull(SUNXI_GPL(1), 1); + sunxi_gpio_set_drv(SUNXI_GPL(0), 2); + sunxi_gpio_set_drv(SUNXI_GPL(1), 2); + } + return sun8i_rsb_init(base); } #endif @@ -243,20 +237,31 @@ static int sun8i_rsb_probe_chip(struct udevice *bus, uint chip_addr, static int sun8i_rsb_probe(struct udevice *bus) { struct sun8i_rsb_priv *priv = dev_get_priv(bus); + struct reset_ctl *reset; + struct clk *clk; priv->base = dev_read_addr_ptr(bus); + reset = devm_reset_control_get(bus, NULL); + if (!IS_ERR(reset)) + reset_deassert(reset); + + clk = devm_clk_get(bus, NULL); + if (!IS_ERR(clk)) + clk_enable(clk); + return sun8i_rsb_init(priv->base); } static int sun8i_rsb_child_pre_probe(struct udevice *child) { struct dm_i2c_chip *chip = dev_get_parent_plat(child); + struct udevice *bus = child->parent; /* Ensure each transfer is for a single register. */ chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS; - return 0; + return sun8i_rsb_probe_chip(bus, chip->chip_addr, 0); } static const struct dm_i2c_ops sun8i_rsb_ops = { diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index 2e24d12214..b23faa228e 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -29,7 +29,6 @@ #include <miiphy.h> #include <net.h> #include <reset.h> -#include <dt-bindings/pinctrl/sun4i-a10.h> #include <wait_bit.h> #define MDIO_CMD_MII_BUSY BIT(0) @@ -81,13 +80,6 @@ #define AHB_GATE_OFFSET_EPHY 0 -/* IO mux settings */ -#define SUN8I_IOMUX_H3 2 -#define SUN8I_IOMUX_R40 5 -#define SUN8I_IOMUX_H6 5 -#define SUN8I_IOMUX_H616 2 -#define SUN8I_IOMUX 4 - /* H3/A64 EMAC Register's offset */ #define EMAC_CTL0 0x00 #define EMAC_CTL0_FULL_DUPLEX BIT(0) @@ -519,85 +511,6 @@ static int sun8i_emac_eth_start(struct udevice *dev) return 0; } -static int parse_phy_pins(struct udevice *dev) -{ - int offset; - const char *pin_name; - int drive, pull = SUN4I_PINCTRL_NO_PULL, i; - u32 iomux; - - offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), - "pinctrl-0"); - if (offset < 0) { - printf("WARNING: emac: cannot find pinctrl-0 node\n"); - return offset; - } - - drive = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0, - "drive-strength", ~0); - if (drive != ~0) { - if (drive <= 10) - drive = SUN4I_PINCTRL_10_MA; - else if (drive <= 20) - drive = SUN4I_PINCTRL_20_MA; - else if (drive <= 30) - drive = SUN4I_PINCTRL_30_MA; - else - drive = SUN4I_PINCTRL_40_MA; - } - - if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-up", NULL)) - pull = SUN4I_PINCTRL_PULL_UP; - else if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-down", NULL)) - pull = SUN4I_PINCTRL_PULL_DOWN; - - /* - * The GPIO pinmux value is an integration choice, so depends on the - * SoC, not the EMAC variant. - */ - if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5)) - iomux = SUN8I_IOMUX_H3; - else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) - iomux = SUN8I_IOMUX_R40; - else if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) - iomux = SUN8I_IOMUX_H6; - else if (IS_ENABLED(CONFIG_MACH_SUN50I_H616)) - iomux = SUN8I_IOMUX_H616; - else if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T)) - iomux = SUN8I_IOMUX; - else if (IS_ENABLED(CONFIG_MACH_SUN50I)) - iomux = SUN8I_IOMUX; - else - BUILD_BUG_ON_MSG(1, "missing pinmux value for Ethernet pins"); - - for (i = 0; ; i++) { - int pin; - - pin_name = fdt_stringlist_get(gd->fdt_blob, offset, - "pins", i, NULL); - if (!pin_name) - break; - - pin = sunxi_name_to_gpio(pin_name); - if (pin < 0) - continue; - - sunxi_gpio_set_cfgpin(pin, iomux); - - if (drive != ~0) - sunxi_gpio_set_drv(pin, drive); - if (pull != ~0) - sunxi_gpio_set_pull(pin, pull); - } - - if (!i) { - printf("WARNING: emac: cannot find pins property\n"); - return -2; - } - - return 0; -} - static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp) { struct emac_eth_dev *priv = dev_get_priv(dev); @@ -965,9 +878,6 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev) priv->interface = pdata->phy_interface; - if (!priv->use_internal_phy) - parse_phy_pins(dev); - sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node, "allwinner,tx-delay-ps", 0); if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700) diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index 17ad88e732..d15b0add7c 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -17,7 +17,6 @@ #include <net.h> #include <asm/io.h> #include <asm/arch/clock.h> -#include <asm/arch/gpio.h> /* EMAC register */ struct emac_regs { @@ -511,15 +510,11 @@ static int sunxi_emac_board_setup(struct udevice *dev, struct sunxi_sramc_regs *sram = (struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE; struct emac_regs *regs = priv->regs; - int pin, ret; + int ret; /* Map SRAM to EMAC */ setbits_le32(&sram->ctrl1, 0x5 << 2); - /* Configure pin mux settings for MII Ethernet */ - for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++) - sunxi_gpio_set_cfgpin(pin, SUNXI_GPA_EMAC); - /* Set up clock gating */ ret = clk_enable(&priv->clk); if (ret) { diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index d7477d7c33..13033198f9 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -342,6 +342,7 @@ source "drivers/pinctrl/nexell/Kconfig" source "drivers/pinctrl/nxp/Kconfig" source "drivers/pinctrl/renesas/Kconfig" source "drivers/pinctrl/rockchip/Kconfig" +source "drivers/pinctrl/sunxi/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" endmenu diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 030c38f5cc..9b4978253b 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -14,7 +14,7 @@ obj-$(CONFIG_PINCTRL_INTEL) += intel/ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ obj-$(CONFIG_ARCH_RMOBILE) += renesas/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o - +obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig new file mode 100644 index 0000000000..77da90836b --- /dev/null +++ b/drivers/pinctrl/sunxi/Kconfig @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: GPL-2.0 + +if ARCH_SUNXI + +config PINCTRL_SUNXI + select PINCTRL_FULL + select PINCTRL_GENERIC + select PINCONF + select PINMUX + bool + +config PINCTRL_SUNIV_F1C100S + bool "Support for the Allwinner F1C100s PIO" + default MACH_SUNIV + select PINCTRL_SUNXI + +config PINCTRL_SUN4I_A10 + bool "Support for the Allwinner A10 PIO" + default MACH_SUN4I + select PINCTRL_SUNXI + +config PINCTRL_SUN5I_A13 + bool "Support for the Allwinner A10s/A13 PIO" + default MACH_SUN5I + select PINCTRL_SUNXI + +config PINCTRL_SUN6I_A31 + bool "Support for the Allwinner A31 PIO" + default MACH_SUN6I + select PINCTRL_SUNXI + +config PINCTRL_SUN6I_A31_R + bool "Support for the Allwinner A31 R-PIO" + default MACH_SUN6I + select PINCTRL_SUNXI + +config PINCTRL_SUN7I_A20 + bool "Support for the Allwinner A20/R40 PIO" + default MACH_SUN7I || MACH_SUN8I_R40 + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_A23 + bool "Support for the Allwinner A23 PIO" + default MACH_SUN8I_A23 + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_A23_R + bool "Support for the Allwinner A23/A33 R-PIO" + default MACH_SUN8I_A23 || MACH_SUN8I_A33 + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_A33 + bool "Support for the Allwinner A33 PIO" + default MACH_SUN8I_A33 + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_A83T + bool "Support for the Allwinner A83T PIO" + default MACH_SUN8I_A83T + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_A83T_R + bool "Support for the Allwinner A83T R-PIO" + default MACH_SUN8I_A83T + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_H3 + bool "Support for the Allwinner H3 PIO" + default MACH_SUN8I_H3 + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_H3_R + bool "Support for the Allwinner H3/H5 R-PIO" + default MACH_SUN8I_H3 || MACH_SUN50I_H5 + select PINCTRL_SUNXI + +config PINCTRL_SUN8I_V3S + bool "Support for the Allwinner V3s PIO" + default MACH_SUN8I_V3S + select PINCTRL_SUNXI + +config PINCTRL_SUN9I_A80 + bool "Support for the Allwinner A80 PIO" + default MACH_SUN9I + select PINCTRL_SUNXI + +config PINCTRL_SUN9I_A80_R + bool "Support for the Allwinner A80 R-PIO" + default MACH_SUN9I + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_A64 + bool "Support for the Allwinner A64 PIO" + default MACH_SUN50I + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_A64_R + bool "Support for the Allwinner A64 R-PIO" + default MACH_SUN50I + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_H5 + bool "Support for the Allwinner H5 PIO" + default MACH_SUN50I_H5 + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_H6 + bool "Support for the Allwinner H6 PIO" + default MACH_SUN50I_H6 + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_H6_R + bool "Support for the Allwinner H6 R-PIO" + default MACH_SUN50I_H6 + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_H616 + bool "Support for the Allwinner H616 PIO" + default MACH_SUN50I_H616 + select PINCTRL_SUNXI + +config PINCTRL_SUN50I_H616_R + bool "Support for the Allwinner H616 R-PIO" + default MACH_SUN50I_H616 + select PINCTRL_SUNXI + +endif diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile new file mode 100644 index 0000000000..6a8c01f372 --- /dev/null +++ b/drivers/pinctrl/sunxi/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-y += pinctrl-sunxi.o diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c new file mode 100644 index 0000000000..9ce2bc1b3a --- /dev/null +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -0,0 +1,897 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <clk.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <errno.h> +#include <malloc.h> + +#include <asm/gpio.h> + +extern U_BOOT_DRIVER(gpio_sunxi); + +/* + * This structure implements a simplified view of the possible pinmux settings: + * Each mux value is assumed to be the same for a given function, across the + * pins in each group (almost universally true, with same rare exceptions not + * relevant to U-Boot), but also across different ports (not true in many + * cases). We ignore the first problem, and work around the latter by just + * supporting one particular port for a each function. This works fine for all + * board configurations so far. If this would need to be revisited, we could + * add a "u8 port;" below and match that, with 0 encoding the "don't care" case. + */ +struct sunxi_pinctrl_function { + const char name[sizeof("gpio_out")]; + u8 mux; +}; + +struct sunxi_pinctrl_desc { + const struct sunxi_pinctrl_function *functions; + u8 num_functions; + u8 first_bank; + u8 num_banks; +}; + +struct sunxi_pinctrl_plat { + struct sunxi_gpio __iomem *base; +}; + +static int sunxi_pinctrl_get_pins_count(struct udevice *dev) +{ + const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev); + + return desc->num_banks * SUNXI_GPIOS_PER_BANK; +} + +static const char *sunxi_pinctrl_get_pin_name(struct udevice *dev, + uint pin_selector) +{ + const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev); + static char pin_name[sizeof("PN31")]; + + snprintf(pin_name, sizeof(pin_name), "P%c%d", + pin_selector / SUNXI_GPIOS_PER_BANK + desc->first_bank + 'A', + pin_selector % SUNXI_GPIOS_PER_BANK); + + return pin_name; +} + +static int sunxi_pinctrl_get_functions_count(struct udevice *dev) +{ + const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev); + + return desc->num_functions; +} + +static const char *sunxi_pinctrl_get_function_name(struct udevice *dev, + uint func_selector) +{ + const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev); + + return desc->functions[func_selector].name; +} + +static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector, + uint func_selector) +{ + const struct sunxi_pinctrl_desc *desc = dev_get_priv(dev); + struct sunxi_pinctrl_plat *plat = dev_get_plat(dev); + int bank = pin_selector / SUNXI_GPIOS_PER_BANK; + int pin = pin_selector % SUNXI_GPIOS_PER_BANK; + + debug("set mux: %-4s => %s (%d)\n", + sunxi_pinctrl_get_pin_name(dev, pin_selector), + sunxi_pinctrl_get_function_name(dev, func_selector), + desc->functions[func_selector].mux); + + sunxi_gpio_set_cfgbank(plat->base + bank, pin, + desc->functions[func_selector].mux); + + return 0; +} + +static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 2 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 10 }, +}; + +static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat, + uint bank, uint pin, uint bias) +{ + struct sunxi_gpio *regs = &plat->base[bank]; + + sunxi_gpio_set_pull_bank(regs, pin, bias); + + return 0; +} + +static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat, + uint bank, uint pin, uint drive) +{ + struct sunxi_gpio *regs = &plat->base[bank]; + + if (drive < 10 || drive > 40) + return -EINVAL; + + /* Convert mA to the register value, rounding down. */ + sunxi_gpio_set_drv_bank(regs, pin, drive / 10 - 1); + + return 0; +} + +static int sunxi_pinctrl_pinconf_set(struct udevice *dev, uint pin_selector, + uint param, uint val) +{ + struct sunxi_pinctrl_plat *plat = dev_get_plat(dev); + int bank = pin_selector / SUNXI_GPIOS_PER_BANK; + int pin = pin_selector % SUNXI_GPIOS_PER_BANK; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + return sunxi_pinctrl_pinconf_set_pull(plat, bank, pin, val); + case PIN_CONFIG_DRIVE_STRENGTH: + return sunxi_pinctrl_pinconf_set_drive(plat, bank, pin, val); + } + + return -EINVAL; +} + +static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector, + char *buf, int size) +{ + struct sunxi_pinctrl_plat *plat = dev_get_plat(dev); + int bank = pin_selector / SUNXI_GPIOS_PER_BANK; + int pin = pin_selector % SUNXI_GPIOS_PER_BANK; + int mux = sunxi_gpio_get_cfgbank(plat->base + bank, pin); + + switch (mux) { + case SUNXI_GPIO_INPUT: + strlcpy(buf, "gpio input", size); + break; + case SUNXI_GPIO_OUTPUT: + strlcpy(buf, "gpio output", size); + break; + case SUNXI_GPIO_DISABLE: + strlcpy(buf, "disabled", size); + break; + default: + snprintf(buf, size, "function %d", mux); + break; + } + + return 0; +} + +static const struct pinctrl_ops sunxi_pinctrl_ops = { + .get_pins_count = sunxi_pinctrl_get_pins_count, + .get_pin_name = sunxi_pinctrl_get_pin_name, + .get_functions_count = sunxi_pinctrl_get_functions_count, + .get_function_name = sunxi_pinctrl_get_function_name, + .pinmux_set = sunxi_pinctrl_pinmux_set, + .pinconf_num_params = ARRAY_SIZE(sunxi_pinctrl_pinconf_params), + .pinconf_params = sunxi_pinctrl_pinconf_params, + .pinconf_set = sunxi_pinctrl_pinconf_set, + .set_state = pinctrl_generic_set_state, + .get_pin_muxing = sunxi_pinctrl_get_pin_muxing, +}; + +static int sunxi_pinctrl_bind(struct udevice *dev) +{ + struct sunxi_pinctrl_plat *plat = dev_get_plat(dev); + struct sunxi_pinctrl_desc *desc; + struct sunxi_gpio_plat *gpio_plat; + struct udevice *gpio_dev; + int i, ret; + + desc = (void *)dev_get_driver_data(dev); + if (!desc) + return -EINVAL; + dev_set_priv(dev, desc); + + plat->base = dev_read_addr_ptr(dev); + + ret = device_bind_driver_to_node(dev, "gpio_sunxi", dev->name, + dev_ofnode(dev), &gpio_dev); + if (ret) + return ret; + + for (i = 0; i < desc->num_banks; ++i) { + gpio_plat = malloc(sizeof(*gpio_plat)); + if (!gpio_plat) + return -ENOMEM; + + gpio_plat->regs = plat->base + i; + gpio_plat->bank_name[0] = 'P'; + gpio_plat->bank_name[1] = 'A' + desc->first_bank + i; + gpio_plat->bank_name[2] = '\0'; + + ret = device_bind(gpio_dev, DM_DRIVER_REF(gpio_sunxi), + gpio_plat->bank_name, gpio_plat, + ofnode_null(), NULL); + if (ret) + return ret; + } + + return 0; +} + +static int sunxi_pinctrl_probe(struct udevice *dev) +{ + struct clk *apb_clk; + + apb_clk = devm_clk_get(dev, "apb"); + if (!IS_ERR(apb_clk)) + clk_enable(apb_clk); + + return 0; +} + +static const struct sunxi_pinctrl_function suniv_f1c100s_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 3 }, /* PE11-PE12 */ + { "i2c1", 3 }, /* PD5-PD6 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 3 }, /* PC0-PC2 */ + { "spi0", 2 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 5 }, /* PE0-PE1 */ +#endif +}; + +static const struct sunxi_pinctrl_desc __maybe_unused suniv_f1c100s_pinctrl_desc = { + .functions = suniv_f1c100s_pinctrl_functions, + .num_functions = ARRAY_SIZE(suniv_f1c100s_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 6, +}; + +static const struct sunxi_pinctrl_function sun4i_a10_pinctrl_functions[] = { + { "emac", 2 }, /* PA0-PA17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PB0-PB1 */ + { "i2c1", 2 }, /* PB18-PB19 */ + { "mmc0", 2 }, /* PF0-PF5 */ +#if IS_ENABLED(CONFIG_MMC1_PINS_PH) + { "mmc1", 5 }, /* PH22-PH27 */ +#else + { "mmc1", 4 }, /* PG0-PG5 */ +#endif + { "mmc2", 3 }, /* PC6-PC15 */ + { "mmc3", 2 }, /* PI4-PI9 */ + { "spi0", 3 }, /* PC0-PC2, PC23 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 4 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PB22-PB23 */ +#endif +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun4i_a10_pinctrl_desc = { + .functions = sun4i_a10_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun4i_a10_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 9, +}; + +static const struct sunxi_pinctrl_function sun5i_a13_pinctrl_functions[] = { + { "emac", 2 }, /* PA0-PA17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PB0-PB1 */ + { "i2c1", 2 }, /* PB15-PB16 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG3-PG8 */ + { "mmc2", 3 }, /* PC6-PC15 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 4 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PB19-PB20 */ +#endif + { "uart1", 4 }, /* PG3-PG4 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun5i_a13_pinctrl_desc = { + .functions = sun5i_a13_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun5i_a13_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 7, +}; + +static const struct sunxi_pinctrl_function sun6i_a31_pinctrl_functions[] = { + { "gmac", 2 }, /* PA0-PA27 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PH14-PH15 */ + { "i2c1", 2 }, /* PH16-PH17 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC6-PC15, PC24 */ + { "mmc3", 4 }, /* PC6-PC15, PC24 */ + { "spi0", 3 }, /* PC0-PC2, PC27 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PH20-PH21 */ +#endif +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun6i_a31_pinctrl_desc = { + .functions = sun6i_a31_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun6i_a31_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun6i_a31_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 2 }, /* PL0-PL1 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun6i_a31_r_pinctrl_desc = { + .functions = sun6i_a31_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun6i_a31_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 2, +}; + +static const struct sunxi_pinctrl_function sun7i_a20_pinctrl_functions[] = { + { "emac", 2 }, /* PA0-PA17 */ + { "gmac", 5 }, /* PA0-PA17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PB0-PB1 */ + { "i2c1", 2 }, /* PB18-PB19 */ + { "mmc0", 2 }, /* PF0-PF5 */ +#if IS_ENABLED(CONFIG_MMC1_PINS_PH) + { "mmc1", 5 }, /* PH22-PH27 */ +#else + { "mmc1", 4 }, /* PG0-PG5 */ +#endif + { "mmc2", 3 }, /* PC5-PC15, PC24 */ + { "spi0", 3 }, /* PC0-PC2, PC23 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 4 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PB22-PB23 */ +#endif +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun7i_a20_pinctrl_desc = { + .functions = sun7i_a20_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun7i_a20_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 9, +}; + +static const struct sunxi_pinctrl_function sun8i_a23_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PH2-PH3 */ + { "i2c1", 2 }, /* PH4-PH5 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC5-PC16 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PB0-PB1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a23_pinctrl_desc = { + .functions = sun8i_a23_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_a23_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun8i_a23_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 3 }, /* PL0-PL1 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a23_r_pinctrl_desc = { + .functions = sun8i_a23_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_a23_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 1, +}; + +static const struct sunxi_pinctrl_function sun8i_a33_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PH2-PH3 */ + { "i2c1", 2 }, /* PH4-PH5 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC5-PC16 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 3 }, /* PB0-PB1 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PB0-PB1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a33_pinctrl_desc = { + .functions = sun8i_a33_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_a33_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun8i_a83t_pinctrl_functions[] = { + { "gmac", 4 }, /* PD2-PD23 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PH0-PH1 */ + { "i2c1", 2 }, /* PH2-PH3 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC5-PC16 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PB9-PB10 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PB0-PB1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a83t_pinctrl_desc = { + .functions = sun8i_a83t_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_a83t_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun8i_a83t_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 2 }, /* PL8-PL9 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a83t_r_pinctrl_desc = { + .functions = sun8i_a83t_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_a83t_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 1, +}; + +static const struct sunxi_pinctrl_function sun8i_h3_pinctrl_functions[] = { + { "emac", 2 }, /* PD0-PD17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PA11-PA12 */ + { "i2c1", 3 }, /* PA18-PA19 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC5-PC16 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PA4-PA5 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PA0-PA1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_h3_pinctrl_desc = { + .functions = sun8i_h3_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_h3_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 7, +}; + +static const struct sunxi_pinctrl_function sun8i_h3_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 2 }, /* PL0-PL1 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_h3_r_pinctrl_desc = { + .functions = sun8i_h3_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_h3_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 1, +}; + +static const struct sunxi_pinctrl_function sun8i_v3s_pinctrl_functions[] = { + { "emac", 4 }, /* PD0-PD17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PB6-PB7 */ + { "i2c1", 2 }, /* PB8-PB9 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 2 }, /* PC0-PC10 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 3 }, /* PB8-PB9 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PB0-PB1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun8i_v3s_pinctrl_desc = { + .functions = sun8i_v3s_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun8i_v3s_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 7, +}; + +static const struct sunxi_pinctrl_function sun9i_a80_pinctrl_functions[] = { + { "gmac", 2 }, /* PA0-PA17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PH0-PH1 */ + { "i2c1", 2 }, /* PH2-PH3 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC6-PC16 */ + { "spi0", 3 }, /* PC0-PC2, PC19 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 4 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PH12-PH13 */ +#endif +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_pinctrl_desc = { + .functions = sun9i_a80_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun9i_a80_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun9i_a80_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c0", 2 }, /* PN0-PN1 */ + { "s_i2c1", 3 }, /* PM8-PM9 */ + { "s_uart", 3 }, /* PL0-PL1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_r_pinctrl_desc = { + .functions = sun9i_a80_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun9i_a80_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 3, +}; + +static const struct sunxi_pinctrl_function sun50i_a64_pinctrl_functions[] = { + { "emac", 4 }, /* PD8-PD23 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PH0-PH1 */ + { "i2c1", 2 }, /* PH2-PH3 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC1-PC16 */ + { "pwm", 2 }, /* PD22 */ + { "spi0", 4 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 4 }, /* PB8-PB9 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PB0-PB1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a64_pinctrl_desc = { + .functions = sun50i_a64_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_a64_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun50i_a64_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 2 }, /* PL8-PL9 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a64_r_pinctrl_desc = { + .functions = sun50i_a64_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_a64_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 1, +}; + +static const struct sunxi_pinctrl_function sun50i_h5_pinctrl_functions[] = { + { "emac", 2 }, /* PD0-PD17 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PA11-PA12 */ + { "i2c1", 3 }, /* PA18-PA19 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC1-PC16 */ + { "spi0", 3 }, /* PC0-PC3 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PA4-PA5 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ + { "uart2", 2 }, /* PA0-PA1 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h5_pinctrl_desc = { + .functions = sun50i_h5_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_h5_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 7, +}; + +static const struct sunxi_pinctrl_function sun50i_h6_pinctrl_functions[] = { + { "emac", 5 }, /* PD0-PD20 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "i2c0", 2 }, /* PD25-PD26 */ + { "i2c1", 4 }, /* PH5-PH6 */ + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC1-PC14 */ + { "spi0", 4 }, /* PC0-PC7 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PH0-PH1 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_pinctrl_desc = { + .functions = sun50i_h6_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_h6_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 8, +}; + +static const struct sunxi_pinctrl_function sun50i_h6_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 3 }, /* PL0-PL1 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_r_pinctrl_desc = { + .functions = sun50i_h6_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_h6_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 2, +}; + +static const struct sunxi_pinctrl_function sun50i_h616_pinctrl_functions[] = { + { "emac0", 2 }, /* PI0-PI16 */ + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "mmc0", 2 }, /* PF0-PF5 */ + { "mmc1", 2 }, /* PG0-PG5 */ + { "mmc2", 3 }, /* PC0-PC16 */ + { "spi0", 4 }, /* PC0-PC7, PC15-PC16 */ +#if IS_ENABLED(CONFIG_UART0_PORT_F) + { "uart0", 3 }, /* PF2-PF4 */ +#else + { "uart0", 2 }, /* PH0-PH1 */ +#endif + { "uart1", 2 }, /* PG6-PG7 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_pinctrl_desc = { + .functions = sun50i_h616_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_h616_pinctrl_functions), + .first_bank = SUNXI_GPIO_A, + .num_banks = 9, +}; + +static const struct sunxi_pinctrl_function sun50i_h616_r_pinctrl_functions[] = { + { "gpio_in", 0 }, + { "gpio_out", 1 }, + { "s_i2c", 3 }, /* PL0-PL1 */ + { "s_uart", 2 }, /* PL2-PL3 */ +}; + +static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc = { + .functions = sun50i_h616_r_pinctrl_functions, + .num_functions = ARRAY_SIZE(sun50i_h616_r_pinctrl_functions), + .first_bank = SUNXI_GPIO_L, + .num_banks = 1, +}; + +static const struct udevice_id sunxi_pinctrl_ids[] = { +#ifdef CONFIG_PINCTRL_SUNIV_F1C100S + { + .compatible = "allwinner,suniv-f1c100s-pinctrl", + .data = (ulong)&suniv_f1c100s_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN4I_A10 + { + .compatible = "allwinner,sun4i-a10-pinctrl", + .data = (ulong)&sun4i_a10_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN5I_A13 + { + .compatible = "allwinner,sun5i-a10s-pinctrl", + .data = (ulong)&sun5i_a13_pinctrl_desc, + }, + { + .compatible = "allwinner,sun5i-a13-pinctrl", + .data = (ulong)&sun5i_a13_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN6I_A31 + { + .compatible = "allwinner,sun6i-a31-pinctrl", + .data = (ulong)&sun6i_a31_pinctrl_desc, + }, + { + .compatible = "allwinner,sun6i-a31s-pinctrl", + .data = (ulong)&sun6i_a31_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN6I_A31_R + { + .compatible = "allwinner,sun6i-a31-r-pinctrl", + .data = (ulong)&sun6i_a31_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN7I_A20 + { + .compatible = "allwinner,sun7i-a20-pinctrl", + .data = (ulong)&sun7i_a20_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_A23 + { + .compatible = "allwinner,sun8i-a23-pinctrl", + .data = (ulong)&sun8i_a23_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_A23_R + { + .compatible = "allwinner,sun8i-a23-r-pinctrl", + .data = (ulong)&sun8i_a23_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_A33 + { + .compatible = "allwinner,sun8i-a33-pinctrl", + .data = (ulong)&sun8i_a33_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_A83T + { + .compatible = "allwinner,sun8i-a83t-pinctrl", + .data = (ulong)&sun8i_a83t_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_A83T_R + { + .compatible = "allwinner,sun8i-a83t-r-pinctrl", + .data = (ulong)&sun8i_a83t_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_H3 + { + .compatible = "allwinner,sun8i-h3-pinctrl", + .data = (ulong)&sun8i_h3_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_H3_R + { + .compatible = "allwinner,sun8i-h3-r-pinctrl", + .data = (ulong)&sun8i_h3_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN7I_A20 + { + .compatible = "allwinner,sun8i-r40-pinctrl", + .data = (ulong)&sun7i_a20_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN8I_V3S + { + .compatible = "allwinner,sun8i-v3-pinctrl", + .data = (ulong)&sun8i_v3s_pinctrl_desc, + }, + { + .compatible = "allwinner,sun8i-v3s-pinctrl", + .data = (ulong)&sun8i_v3s_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN9I_A80 + { + .compatible = "allwinner,sun9i-a80-pinctrl", + .data = (ulong)&sun9i_a80_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN9I_A80_R + { + .compatible = "allwinner,sun9i-a80-r-pinctrl", + .data = (ulong)&sun9i_a80_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_A64 + { + .compatible = "allwinner,sun50i-a64-pinctrl", + .data = (ulong)&sun50i_a64_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_A64_R + { + .compatible = "allwinner,sun50i-a64-r-pinctrl", + .data = (ulong)&sun50i_a64_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_H5 + { + .compatible = "allwinner,sun50i-h5-pinctrl", + .data = (ulong)&sun50i_h5_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_H6 + { + .compatible = "allwinner,sun50i-h6-pinctrl", + .data = (ulong)&sun50i_h6_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_H6_R + { + .compatible = "allwinner,sun50i-h6-r-pinctrl", + .data = (ulong)&sun50i_h6_r_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_H616 + { + .compatible = "allwinner,sun50i-h616-pinctrl", + .data = (ulong)&sun50i_h616_pinctrl_desc, + }, +#endif +#ifdef CONFIG_PINCTRL_SUN50I_H616_R + { + .compatible = "allwinner,sun50i-h616-r-pinctrl", + .data = (ulong)&sun50i_h616_r_pinctrl_desc, + }, +#endif + {} +}; + +U_BOOT_DRIVER(sunxi_pinctrl) = { + .name = "sunxi-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = sunxi_pinctrl_ids, + .bind = sunxi_pinctrl_bind, + .probe = sunxi_pinctrl_probe, + .plat_auto = sizeof(struct sunxi_pinctrl_plat), + .ops = &sunxi_pinctrl_ops, +}; diff --git a/drivers/pwm/sunxi_pwm.c b/drivers/pwm/sunxi_pwm.c index e3d5ee456b..bb1bec05ec 100644 --- a/drivers/pwm/sunxi_pwm.c +++ b/drivers/pwm/sunxi_pwm.c @@ -13,7 +13,6 @@ #include <asm/global_data.h> #include <asm/io.h> #include <asm/arch/pwm.h> -#include <asm/arch/gpio.h> #include <power/regulator.h> DECLARE_GLOBAL_DATA_PTR; @@ -45,14 +44,6 @@ static const u32 prescaler_table[] = { 1, /* 1111 */ }; -static int sunxi_pwm_config_pinmux(void) -{ -#ifdef CONFIG_MACH_SUN50I - sunxi_gpio_set_cfgpin(SUNXI_GPD(22), SUNXI_GPD_PWM); -#endif - return 0; -} - static int sunxi_pwm_set_invert(struct udevice *dev, uint channel, bool polarity) { @@ -137,8 +128,6 @@ static int sunxi_pwm_set_enable(struct udevice *dev, uint channel, bool enable) return 0; } - sunxi_pwm_config_pinmux(); - if (priv->invert) v &= ~SUNXI_PWM_CTRL_CH0_ACT_STA; else diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index d62355ec6f..b6cd7ddafa 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -32,7 +32,6 @@ #include <linux/bitops.h> #include <asm/bitops.h> -#include <asm/gpio.h> #include <asm/io.h> #include <linux/iopoll.h> @@ -180,87 +179,6 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable) writel(reg, SPI_REG(priv, SPI_TCR)); } -static int sun4i_spi_parse_pins(struct udevice *dev) -{ - const void *fdt = gd->fdt_blob; - const char *pin_name; - const fdt32_t *list; - u32 phandle; - int drive, pull = 0, pin, i; - int offset; - int size; - - list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size); - if (!list) { - printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n"); - return -EINVAL; - } - - while (size) { - phandle = fdt32_to_cpu(*list++); - size -= sizeof(*list); - - offset = fdt_node_offset_by_phandle(fdt, phandle); - if (offset < 0) - return offset; - - drive = fdt_getprop_u32_default_node(fdt, offset, 0, - "drive-strength", 0); - if (drive) { - if (drive <= 10) - drive = 0; - else if (drive <= 20) - drive = 1; - else if (drive <= 30) - drive = 2; - else - drive = 3; - } else { - drive = fdt_getprop_u32_default_node(fdt, offset, 0, - "allwinner,drive", - 0); - drive = min(drive, 3); - } - - if (fdt_get_property(fdt, offset, "bias-disable", NULL)) - pull = 0; - else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL)) - pull = 1; - else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL)) - pull = 2; - else - pull = fdt_getprop_u32_default_node(fdt, offset, 0, - "allwinner,pull", - 0); - pull = min(pull, 2); - - for (i = 0; ; i++) { - pin_name = fdt_stringlist_get(fdt, offset, - "pins", i, NULL); - if (!pin_name) { - pin_name = fdt_stringlist_get(fdt, offset, - "allwinner,pins", - i, NULL); - if (!pin_name) - break; - } - - pin = sunxi_name_to_gpio(pin_name); - if (pin < 0) - break; - - if (IS_ENABLED(CONFIG_MACH_SUN50I) || - IS_ENABLED(CONFIG_SUN50I_GEN_H6)) - sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0); - else - sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0); - sunxi_gpio_set_drv(pin, drive); - sunxi_gpio_set_pull(pin, pull); - } - } - return 0; -} - static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable) { struct sun4i_spi_priv *priv = dev_get_priv(dev); @@ -507,8 +425,6 @@ static int sun4i_spi_probe(struct udevice *bus) return ret; } - sun4i_spi_parse_pins(bus); - priv->variant = plat->variant; priv->base = plat->base; priv->freq = plat->max_hz; |