()On Tue, Nov 11, 2014 at 1:38 PM, Hongzhou Yang <hongzhou.yang@xxxxxxxxxxxx> wrote: > From: Hongzhou Yang <hongzhou.yang@xxxxxxxxxxxx> > > The mediatek SoCs have GPIO controller that handle both the muxing and GPIOs. > > The GPIO controller have pinmux, pull enable, pull select, direction and output high/low control. > > This driver include common driver and mt8135 part. > The common driver include the pinctrl driver and GPIO driver. > The mt8135 part contain its special device data. > > Signed-off-by: Hongzhou Yang <hongzhou.yang@xxxxxxxxxxxx> (...) > menuconfig ARCH_MEDIATEK > bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7 > select ARM_GIC > + select PINCTRL Should it not also select PINCTRL_MTK8135 for the right SoC? (...) > +++ b/drivers/pinctrl/mediatek/Kconfig > @@ -0,0 +1,12 @@ > +if ARCH_MEDIATEK > + > +config PINCTRL_MTK_COMMON > + bool > + select PINMUX > + select GENERIC_PINCONF This is also a GPIO driver but it fails to select GPIOLIB, OF_GPIO and also possibly GPIOLIB_IRQCHIP. (...) > +static int mtk_pctrl_dt_node_to_map_config(struct mtk_pinctrl *pctl, u32 pin, > + unsigned long *configs, unsigned num_configs, > + struct pinctrl_map **map, unsigned *cnt_maps, > + unsigned *num_maps) > +{ > + struct mtk_pinctrl_group *grp; > + unsigned long *cfgs; > + > + if (*num_maps == *cnt_maps) > + return -ENOSPC; > + > + cfgs = kmemdup(configs, num_configs * sizeof(*cfgs), > + GFP_KERNEL); > + if (cfgs == NULL) > + return -ENOMEM; > + > + grp = mtk_pctrl_find_group_by_pin(pctl, pin); > + if (!grp) { > + dev_err(pctl->dev, "unable to match pin %d to group\n", pin); > + return -EINVAL; > + } > + > + (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP; > + (*map)[*num_maps].data.configs.group_or_pin = grp->name; > + (*map)[*num_maps].data.configs.configs = cfgs; > + (*map)[*num_maps].data.configs.num_configs = num_configs; > + (*num_maps)++; > + > + return 0; > +} Can't this use pinctrl_utils_add_map_configs()? > +static void mtk_pctrl_dt_free_map(struct pinctrl_dev *pctldev, > + struct pinctrl_map *map, > + unsigned num_maps) > +{ > + int i; > + > + for (i = 0; i < num_maps; i++) { > + if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) > + kfree(map[i].data.configs.configs); > + } > + > + kfree(map); > +} Use pinctrl_utils_dt_free_map() instead. > +static int mtk_dt_cnt_map(struct pinctrl_map **map, unsigned *cnt_maps, > + unsigned *num_maps, unsigned cnt) > +{ > + unsigned old_num = *cnt_maps; > + unsigned new_num = *num_maps + cnt; > + struct pinctrl_map *new_map; > + > + if (old_num >= new_num) > + return 0; > + > + new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); > + if (!new_map) > + return -ENOMEM; > + > + memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); > + > + *map = new_map; > + *cnt_maps = new_num; > + > + return 0; > +} Use pinctrl_utils_reserve_map() instead. > +static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, > + struct device_node *node, > + struct pinctrl_map **map, > + unsigned *num_maps, unsigned *cnt_maps) > +{ > + struct property *pins; > + u32 pinfunc, pin, func; > + int num_pins, num_funcs, maps_per_pin; > + unsigned long *configs; > + unsigned int num_configs; > + bool has_config = 0; > + int i, err; > + unsigned cnt = 0; > + struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); > + > + pins = of_find_property(node, "mediatek,pins", NULL); > + if (!pins) { > + dev_err(pctl->dev, "missing mediatek,pins property in node %s .\n", > + node->name); > + return -EINVAL; > + } > + > + err = pinconf_generic_parse_dt_config(node, &configs, &num_configs); > + if (num_configs) > + has_config = 1; I'd prefer we first identify if it's a config or mux subnode, then go on to parse it as mux or config. See comments on patch 2/3. > + > + num_pins = pins->length / sizeof(u32); > + num_funcs = num_pins; > + maps_per_pin = 0; > + if (num_funcs) > + maps_per_pin++; > + if (has_config && num_pins >= 1) > + maps_per_pin++; > + > + if (!num_pins || !maps_per_pin) > + return -EINVAL; > + > + cnt = num_pins * maps_per_pin; > + > + err = mtk_dt_cnt_map(map, cnt_maps, num_maps, cnt); > + if (err < 0) > + goto fail; > + > + for (i = 0; i < num_pins; i++) { > + err = of_property_read_u32_index(node, "mediatek,pins", > + i, &pinfunc); As mentioned use just "pins" and let's figure out how to handle this in a generic way. > +static int mtk_gpio_request(struct gpio_chip *chip, unsigned offset) > +{ > + return pinctrl_request_gpio(chip->base + offset); > +} > + > +static void mtk_gpio_free(struct gpio_chip *chip, unsigned offset) > +{ > + pinctrl_free_gpio(chip->base + offset); > +} > + > +static int mtk_gpio_direction_input(struct gpio_chip *chip, > + unsigned offset) > +{ > + return pinctrl_gpio_direction_input(chip->base + offset); > +} > + > +static int mtk_gpio_direction_output(struct gpio_chip *chip, > + unsigned offset, int value) > +{ > + mtk_gpio_set(chip, offset, value); > + return pinctrl_gpio_direction_output(chip->base + offset); > +} This is kinda nice! > +static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) > +{ > + struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev); > + struct mtk_pinctrl_group *g = pctl->groups + offset; > + struct mtk_desc_function *desc = > + mtk_pctrl_desc_find_irq_function_from_name( > + pctl, g->name); > + if (!desc) > + return -EINVAL; > + > + return desc->irqnum; > +} I don't quite get this still. Does this mean every single GPIO line potentially has it's own unique IRQ line? Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html