diff options
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/Kconfig | 7 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/broadcom/pinctrl-bcm283x.c | 21 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-at91-pio4.c | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-qe-io.c | 255 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl_stm32.c | 48 | ||||
-rw-r--r-- | drivers/pinctrl/renesas/Kconfig | 20 |
7 files changed, 314 insertions, 39 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index cdbccfd285..048583f39b 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -205,6 +205,13 @@ config PINCTRL_QCA953X the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_QE + bool "QE based pinctrl driver, like on mpc83xx" + depends on DM + help + This option is to enable the QE pinctrl driver for QE based io + controller. + config PINCTRL_ROCKCHIP_RV1108 bool "Rockchip rv1108 pin control driver" depends on DM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 92cff1b100..507dd3a926 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_PINCTRL_MTK) += mediatek/ obj-$(CONFIG_PINCTRL_MSCC) += mscc/ obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_ARCH_NEXELL) += nexell/ +obj-$(CONFIG_PINCTRL_QE) += pinctrl-qe-io.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c index c22d534da9..41da814123 100644 --- a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c +++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c @@ -63,7 +63,7 @@ static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio) int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config) { u32 pin_arr[MAX_PINS_PER_BANK]; - u32 function; + int function; int i, len, pin_count = 0; if (!dev_read_prop(config, "brcm,pins", &len) || !len || @@ -104,17 +104,11 @@ static const struct udevice_id bcm2835_pinctrl_id[] = { {} }; -int bcm283x_pinctl_probe(struct udevice *dev) +int bcm283x_pinctl_ofdata_to_platdata(struct udevice *dev) { struct bcm283x_pinctrl_priv *priv; - int ret; - struct udevice *pdev; priv = dev_get_priv(dev); - if (!priv) { - debug("%s: Failed to get private\n", __func__); - return -EINVAL; - } priv->base_reg = dev_read_addr_ptr(dev); if (!priv->base_reg) { @@ -122,6 +116,14 @@ int bcm283x_pinctl_probe(struct udevice *dev) return -EINVAL; } + return 0; +} + +int bcm283x_pinctl_probe(struct udevice *dev) +{ + int ret; + struct udevice *pdev; + /* Create GPIO device as well */ ret = device_bind(dev, lists_driver_lookup_name("gpio_bcm2835"), "gpio_bcm2835", NULL, dev_of_offset(dev), &pdev); @@ -147,10 +149,11 @@ U_BOOT_DRIVER(pinctrl_bcm283x) = { .name = "bcm283x_pinctrl", .id = UCLASS_PINCTRL, .of_match = of_match_ptr(bcm2835_pinctrl_id), + .ofdata_to_platdata = bcm283x_pinctl_ofdata_to_platdata, .priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv), .ops = &bcm283x_pinctrl_ops, .probe = bcm283x_pinctl_probe, -#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_BOARD) +#if CONFIG_IS_ENABLED(OF_BOARD) .flags = DM_FLAG_PRE_RELOC, #endif }; diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index fdb7920b55..bf85cc916a 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -169,6 +169,7 @@ static int atmel_pinctrl_probe(struct udevice *dev) static const struct udevice_id atmel_pinctrl_match[] = { { .compatible = "atmel,sama5d2-pinctrl" }, + { .compatible = "microchip,sama7g5-pinctrl" }, {} }; diff --git a/drivers/pinctrl/pinctrl-qe-io.c b/drivers/pinctrl/pinctrl-qe-io.c new file mode 100644 index 0000000000..85521eabd4 --- /dev/null +++ b/drivers/pinctrl/pinctrl-qe-io.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2006 Freescale Semiconductor, Inc. + * + * Dave Liu <daveliu@freescale.com> + * based on source code of Shlomi Gridish + */ + +#include <common.h> +#include <linux/errno.h> +#include <asm/io.h> +#include <asm/immap_83xx.h> + +#if defined(CONFIG_PINCTRL) +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/pinctrl.h> +#include <linux/ioport.h> + +/** + * struct qe_io_platdata + * + * @base: Base register address + * @num_par_io_ports number of io ports + */ +struct qe_io_platdata { + qepio83xx_t *base; + u32 num_io_ports; +}; +#endif + +#define NUM_OF_PINS 32 + +/** qe_cfg_iopin configure one io pin setting + * + * @par_io: pointer to parallel I/O base + * @port: io pin port + * @pin: io pin number which get configured + * @dir: direction of io pin 2 bits valid + * 00 = pin disabled + * 01 = output + * 10 = input + * 11 = pin is I/O + * @open_drain: is pin open drain + * @assign: pin assignment registers select the function of the pin + */ +static void qe_cfg_iopin(qepio83xx_t *par_io, u8 port, u8 pin, int dir, + int open_drain, int assign) +{ + u32 dbit_mask; + u32 dbit_dir; + u32 dbit_asgn; + u32 bit_mask; + u32 tmp_val; + int offset; + + offset = (NUM_OF_PINS - (pin % (NUM_OF_PINS / 2) + 1) * 2); + + /* Calculate pin location and 2bit mask and dir */ + dbit_mask = (u32)(0x3 << offset); + dbit_dir = (u32)(dir << offset); + + /* Setup the direction */ + tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ? + in_be32(&par_io->ioport[port].dir2) : + in_be32(&par_io->ioport[port].dir1); + + if (pin > (NUM_OF_PINS / 2) - 1) { + out_be32(&par_io->ioport[port].dir2, ~dbit_mask & tmp_val); + out_be32(&par_io->ioport[port].dir2, dbit_dir | tmp_val); + } else { + out_be32(&par_io->ioport[port].dir1, ~dbit_mask & tmp_val); + out_be32(&par_io->ioport[port].dir1, dbit_dir | tmp_val); + } + + /* Calculate pin location for 1bit mask */ + bit_mask = (u32)(1 << (NUM_OF_PINS - (pin + 1))); + + /* Setup the open drain */ + tmp_val = in_be32(&par_io->ioport[port].podr); + if (open_drain) + out_be32(&par_io->ioport[port].podr, bit_mask | tmp_val); + else + out_be32(&par_io->ioport[port].podr, ~bit_mask & tmp_val); + + /* Setup the assignment */ + tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ? + in_be32(&par_io->ioport[port].ppar2) : + in_be32(&par_io->ioport[port].ppar1); + dbit_asgn = (u32)(assign << offset); + + /* Clear and set 2 bits mask */ + if (pin > (NUM_OF_PINS / 2) - 1) { + out_be32(&par_io->ioport[port].ppar2, ~dbit_mask & tmp_val); + out_be32(&par_io->ioport[port].ppar2, dbit_asgn | tmp_val); + } else { + out_be32(&par_io->ioport[port].ppar1, ~dbit_mask & tmp_val); + out_be32(&par_io->ioport[port].ppar1, dbit_asgn | tmp_val); + } +} + +#if !defined(CONFIG_PINCTRL) +/** qe_config_iopin configure one io pin setting + * + * @port: io pin port + * @pin: io pin number which get configured + * @dir: direction of io pin 2 bits valid + * 00 = pin disabled + * 01 = output + * 10 = input + * 11 = pin is I/O + * @open_drain: is pin open drain + * @assign: pin assignment registers select the function of the pin + */ +void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign) +{ + immap_t *im = (immap_t *)CONFIG_SYS_IMMR; + qepio83xx_t *par_io = (qepio83xx_t *)&im->qepio; + + qe_cfg_iopin(par_io, port, pin, dir, open_drain, assign); +} +#else +static int qe_io_ofdata_to_platdata(struct udevice *dev) +{ + struct qe_io_platdata *plat = dev->platdata; + fdt_addr_t addr; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->base = (qepio83xx_t *)addr; + if (dev_read_u32(dev, "num-ports", &plat->num_io_ports)) + return -EINVAL; + + return 0; +} + +/** + * par_io_of_config_node config + * @dev: pointer to pinctrl device + * @pio: ofnode of pinconfig property + */ +static int par_io_of_config_node(struct udevice *dev, ofnode pio) +{ + struct qe_io_platdata *plat = dev->platdata; + qepio83xx_t *par_io = plat->base; + const unsigned int *pio_map; + int pio_map_len; + + pio_map = ofnode_get_property(pio, "pio-map", &pio_map_len); + if (!pio_map) + return -ENOENT; + + pio_map_len /= sizeof(unsigned int); + if ((pio_map_len % 6) != 0) { + dev_err(dev, "%s: pio-map format wrong!\n", __func__); + return -EINVAL; + } + + while (pio_map_len > 0) { + /* + * column pio_map[5] from linux (has_irq) not + * supported in u-boot yet. + */ + qe_cfg_iopin(par_io, (u8)pio_map[0], (u8)pio_map[1], + (int)pio_map[2], (int)pio_map[3], + (int)pio_map[4]); + pio_map += 6; + pio_map_len -= 6; + } + return 0; +} + +int par_io_of_config(struct udevice *dev) +{ + u32 phandle; + ofnode pio; + int err; + + err = ofnode_read_u32(dev_ofnode(dev), "pio-handle", &phandle); + if (err) { + dev_err(dev, "%s: pio-handle not available\n", __func__); + return err; + } + + pio = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(pio)) { + dev_err(dev, "%s: unable to find node\n", __func__); + return -EINVAL; + } + + /* To Do: find pinctrl device and pass it */ + return par_io_of_config_node(NULL, pio); +} + +/* + * This is not nice! + * pinsettings should work with "pinctrl-" properties. + * Unfortunately on mpc83xx powerpc linux device trees + * devices handle this with "pio-handle" properties ... + * + * Even worser, old board code inits all par_io + * pins in one step, if U-Boot uses the device + * or not. So init all par_io definitions here too + * as linux does this also. + */ +static void config_qe_ioports(struct udevice *dev) +{ + ofnode ofn; + + for (ofn = dev_read_first_subnode(dev); ofnode_valid(ofn); + ofn = dev_read_next_subnode(ofn)) { + /* + * ignore errors here, as may the subnode + * has no pio-handle + */ + par_io_of_config_node(dev, ofn); + } +} + +static int par_io_pinctrl_probe(struct udevice *dev) +{ + config_qe_ioports(dev); + + return 0; +} + +static int par_io_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + return 0; +} + +const struct pinctrl_ops par_io_pinctrl_ops = { + .set_state = par_io_pinctrl_set_state, +}; + +static const struct udevice_id par_io_pinctrl_match[] = { + { .compatible = "fsl,mpc8360-par_io"}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(par_io_pinctrl) = { + .name = "par-io-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = of_match_ptr(par_io_pinctrl_match), + .probe = par_io_pinctrl_probe, + .ofdata_to_platdata = qe_io_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct qe_io_platdata), + .ops = &par_io_pinctrl_ops, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .flags = DM_FLAG_PRE_RELOC, +#endif +}; +#endif diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index 71fa29a389..dbea99532c 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -1,3 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017-2020 STMicroelectronics - All Rights Reserved + */ + #include <common.h> #include <dm.h> #include <hwspinlock.h> @@ -13,8 +18,6 @@ #include <linux/err.h> #include <linux/libfdt.h> -DECLARE_GLOBAL_DATA_PTR; - #define MAX_PINS_ONE_IP 70 #define MODE_BITS_MASK 3 #define OSPEED_MASK 3 @@ -308,7 +311,8 @@ static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin) return 0; } -static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node) +static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, + ofnode node) { gpio_fn &= 0x00FF; gpio_ctl->af = 0; @@ -329,16 +333,16 @@ static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node) break; } - gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0); + gpio_ctl->speed = ofnode_read_u32_default(node, "slew-rate", 0); - if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain")) + if (ofnode_read_bool(node, "drive-open-drain")) gpio_ctl->otype = STM32_GPIO_OTYPE_OD; else gpio_ctl->otype = STM32_GPIO_OTYPE_PP; - if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up")) + if (ofnode_read_bool(node, "bias-pull-up")) gpio_ctl->pupd = STM32_GPIO_PUPD_UP; - else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down")) + else if (ofnode_read_bool(node, "bias-pull-down")) gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN; else gpio_ctl->pupd = STM32_GPIO_PUPD_NO; @@ -350,32 +354,37 @@ static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node) return 0; } -static int stm32_pinctrl_config(int offset) +static int stm32_pinctrl_config(ofnode node) { u32 pin_mux[MAX_PINS_ONE_IP]; int rv, len; + ofnode subnode; /* * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for * usart1) of pin controller phandle "pinctrl-0" * */ - fdt_for_each_subnode(offset, gd->fdt_blob, offset) { + ofnode_for_each_subnode(subnode, node) { struct stm32_gpio_dsc gpio_dsc; struct stm32_gpio_ctl gpio_ctl; int i; - len = fdtdec_get_int_array_count(gd->fdt_blob, offset, - "pinmux", pin_mux, - ARRAY_SIZE(pin_mux)); + rv = ofnode_read_size(subnode, "pinmux"); + if (rv < 0) + return rv; + len = rv / sizeof(pin_mux[0]); debug("%s: no of pinmux entries= %d\n", __func__, len); - if (len < 0) + if (len > MAX_PINS_ONE_IP) return -EINVAL; + rv = ofnode_read_u32_array(subnode, "pinmux", pin_mux, len); + if (rv < 0) + return rv; for (i = 0; i < len; i++) { struct gpio_desc desc; debug("%s: pinmux = %x\n", __func__, *(pin_mux + i)); prep_gpio_dsc(&gpio_dsc, *(pin_mux + i)); - prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), offset); + prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), subnode); rv = uclass_get_device_by_seq(UCLASS_GPIO, gpio_dsc.port, &desc.dev); @@ -424,19 +433,18 @@ static int stm32_pinctrl_bind(struct udevice *dev) #if CONFIG_IS_ENABLED(PINCTRL_FULL) static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config) { - return stm32_pinctrl_config(dev_of_offset(config)); + return stm32_pinctrl_config(dev_ofnode(config)); } #else /* PINCTRL_FULL */ static int stm32_pinctrl_set_state_simple(struct udevice *dev, struct udevice *periph) { - const void *fdt = gd->fdt_blob; const fdt32_t *list; uint32_t phandle; - int config_node; + ofnode config_node; int size, i, ret; - list = fdt_getprop(fdt, dev_of_offset(periph), "pinctrl-0", &size); + list = ofnode_get_property(dev_ofnode(periph), "pinctrl-0", &size); if (!list) return -EINVAL; @@ -446,8 +454,8 @@ static int stm32_pinctrl_set_state_simple(struct udevice *dev, for (i = 0; i < size; i++) { phandle = fdt32_to_cpu(*list++); - config_node = fdt_node_offset_by_phandle(fdt, phandle); - if (config_node < 0) { + config_node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(config_node)) { pr_err("prop pinctrl-0 index %d invalid phandle\n", i); return -EINVAL; } diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig index 8327bcabd6..e14294b6e7 100644 --- a/drivers/pinctrl/renesas/Kconfig +++ b/drivers/pinctrl/renesas/Kconfig @@ -57,6 +57,16 @@ config PINCTRL_PFC_R8A7794 the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_PFC_R8A774A1 + bool "Renesas RZ/G2 R8A774A1 pin control driver" + depends on PINCTRL_PFC + help + Support pin multiplexing control on Renesas RZ/G2M R8A774A1 SoCs. + + The driver is controlled by a device tree node which contains both + the GPIO definitions and pin control functions for each available + multiplex function. + config PINCTRL_PFC_R8A7795 bool "Renesas RCar Gen3 R8A7795 pin control driver" depends on PINCTRL_PFC @@ -77,16 +87,6 @@ config PINCTRL_PFC_R8A7796 the GPIO definitions and pin control functions for each available multiplex function. -config PINCTRL_PFC_R8A774A1 - bool "Renesas RCar Gen3 R8A774A1 pin control driver" - depends on PINCTRL_PFC - help - Support pin multiplexing control on Renesas RZG2M R8A774A1 SoCs. - - The driver is controlled by a device tree node which contains both - the GPIO definitions and pin control functions for each available - multiplex function. - config PINCTRL_PFC_R8A77965 bool "Renesas RCar Gen3 R8A77965 pin control driver" depends on PINCTRL_PFC |