10e37f88dSMaxime Ripard /* 20e37f88dSMaxime Ripard * Allwinner A1X SoCs pinctrl driver. 30e37f88dSMaxime Ripard * 40e37f88dSMaxime Ripard * Copyright (C) 2012 Maxime Ripard 50e37f88dSMaxime Ripard * 60e37f88dSMaxime Ripard * Maxime Ripard <maxime.ripard@free-electrons.com> 70e37f88dSMaxime Ripard * 80e37f88dSMaxime Ripard * This file is licensed under the terms of the GNU General Public 90e37f88dSMaxime Ripard * License version 2. This program is licensed "as is" without any 100e37f88dSMaxime Ripard * warranty of any kind, whether express or implied. 110e37f88dSMaxime Ripard */ 120e37f88dSMaxime Ripard 130e37f88dSMaxime Ripard #include <linux/io.h> 14950707c0SEmilio López #include <linux/clk.h> 1508e9e614SMaxime Ripard #include <linux/gpio.h> 1660242db1SMaxime Ripard #include <linux/irqdomain.h> 17905a5117SChen-Yu Tsai #include <linux/irqchip/chained_irq.h> 180e37f88dSMaxime Ripard #include <linux/module.h> 190e37f88dSMaxime Ripard #include <linux/of.h> 200e37f88dSMaxime Ripard #include <linux/of_address.h> 210e37f88dSMaxime Ripard #include <linux/of_device.h> 2260242db1SMaxime Ripard #include <linux/of_irq.h> 230e37f88dSMaxime Ripard #include <linux/pinctrl/consumer.h> 240e37f88dSMaxime Ripard #include <linux/pinctrl/machine.h> 250e37f88dSMaxime Ripard #include <linux/pinctrl/pinctrl.h> 260e37f88dSMaxime Ripard #include <linux/pinctrl/pinconf-generic.h> 270e37f88dSMaxime Ripard #include <linux/pinctrl/pinmux.h> 280e37f88dSMaxime Ripard #include <linux/platform_device.h> 290e37f88dSMaxime Ripard #include <linux/slab.h> 300e37f88dSMaxime Ripard 315f910777SMaxime Ripard #include "../core.h" 320e37f88dSMaxime Ripard #include "pinctrl-sunxi.h" 33eaa3d848SMaxime Ripard 34*f4c51c10SHans de Goede static struct irq_chip sunxi_pinctrl_edge_irq_chip; 35*f4c51c10SHans de Goede static struct irq_chip sunxi_pinctrl_level_irq_chip; 36*f4c51c10SHans de Goede 370e37f88dSMaxime Ripard static struct sunxi_pinctrl_group * 380e37f88dSMaxime Ripard sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group) 390e37f88dSMaxime Ripard { 400e37f88dSMaxime Ripard int i; 410e37f88dSMaxime Ripard 420e37f88dSMaxime Ripard for (i = 0; i < pctl->ngroups; i++) { 430e37f88dSMaxime Ripard struct sunxi_pinctrl_group *grp = pctl->groups + i; 440e37f88dSMaxime Ripard 450e37f88dSMaxime Ripard if (!strcmp(grp->name, group)) 460e37f88dSMaxime Ripard return grp; 470e37f88dSMaxime Ripard } 480e37f88dSMaxime Ripard 490e37f88dSMaxime Ripard return NULL; 500e37f88dSMaxime Ripard } 510e37f88dSMaxime Ripard 520e37f88dSMaxime Ripard static struct sunxi_pinctrl_function * 530e37f88dSMaxime Ripard sunxi_pinctrl_find_function_by_name(struct sunxi_pinctrl *pctl, 540e37f88dSMaxime Ripard const char *name) 550e37f88dSMaxime Ripard { 560e37f88dSMaxime Ripard struct sunxi_pinctrl_function *func = pctl->functions; 570e37f88dSMaxime Ripard int i; 580e37f88dSMaxime Ripard 590e37f88dSMaxime Ripard for (i = 0; i < pctl->nfunctions; i++) { 600e37f88dSMaxime Ripard if (!func[i].name) 610e37f88dSMaxime Ripard break; 620e37f88dSMaxime Ripard 630e37f88dSMaxime Ripard if (!strcmp(func[i].name, name)) 640e37f88dSMaxime Ripard return func + i; 650e37f88dSMaxime Ripard } 660e37f88dSMaxime Ripard 670e37f88dSMaxime Ripard return NULL; 680e37f88dSMaxime Ripard } 690e37f88dSMaxime Ripard 700e37f88dSMaxime Ripard static struct sunxi_desc_function * 710e37f88dSMaxime Ripard sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl, 720e37f88dSMaxime Ripard const char *pin_name, 730e37f88dSMaxime Ripard const char *func_name) 740e37f88dSMaxime Ripard { 750e37f88dSMaxime Ripard int i; 760e37f88dSMaxime Ripard 770e37f88dSMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) { 780e37f88dSMaxime Ripard const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 790e37f88dSMaxime Ripard 800e37f88dSMaxime Ripard if (!strcmp(pin->pin.name, pin_name)) { 810e37f88dSMaxime Ripard struct sunxi_desc_function *func = pin->functions; 820e37f88dSMaxime Ripard 830e37f88dSMaxime Ripard while (func->name) { 840e37f88dSMaxime Ripard if (!strcmp(func->name, func_name)) 850e37f88dSMaxime Ripard return func; 860e37f88dSMaxime Ripard 870e37f88dSMaxime Ripard func++; 880e37f88dSMaxime Ripard } 890e37f88dSMaxime Ripard } 900e37f88dSMaxime Ripard } 910e37f88dSMaxime Ripard 920e37f88dSMaxime Ripard return NULL; 930e37f88dSMaxime Ripard } 940e37f88dSMaxime Ripard 95814d4f2eSMaxime Ripard static struct sunxi_desc_function * 96814d4f2eSMaxime Ripard sunxi_pinctrl_desc_find_function_by_pin(struct sunxi_pinctrl *pctl, 97814d4f2eSMaxime Ripard const u16 pin_num, 98814d4f2eSMaxime Ripard const char *func_name) 99814d4f2eSMaxime Ripard { 100814d4f2eSMaxime Ripard int i; 101814d4f2eSMaxime Ripard 102814d4f2eSMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) { 103814d4f2eSMaxime Ripard const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 104814d4f2eSMaxime Ripard 105814d4f2eSMaxime Ripard if (pin->pin.number == pin_num) { 106814d4f2eSMaxime Ripard struct sunxi_desc_function *func = pin->functions; 107814d4f2eSMaxime Ripard 108814d4f2eSMaxime Ripard while (func->name) { 109814d4f2eSMaxime Ripard if (!strcmp(func->name, func_name)) 110814d4f2eSMaxime Ripard return func; 111814d4f2eSMaxime Ripard 112814d4f2eSMaxime Ripard func++; 113814d4f2eSMaxime Ripard } 114814d4f2eSMaxime Ripard } 115814d4f2eSMaxime Ripard } 116814d4f2eSMaxime Ripard 117814d4f2eSMaxime Ripard return NULL; 118814d4f2eSMaxime Ripard } 119814d4f2eSMaxime Ripard 1200e37f88dSMaxime Ripard static int sunxi_pctrl_get_groups_count(struct pinctrl_dev *pctldev) 1210e37f88dSMaxime Ripard { 1220e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 1230e37f88dSMaxime Ripard 1240e37f88dSMaxime Ripard return pctl->ngroups; 1250e37f88dSMaxime Ripard } 1260e37f88dSMaxime Ripard 1270e37f88dSMaxime Ripard static const char *sunxi_pctrl_get_group_name(struct pinctrl_dev *pctldev, 1280e37f88dSMaxime Ripard unsigned group) 1290e37f88dSMaxime Ripard { 1300e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 1310e37f88dSMaxime Ripard 1320e37f88dSMaxime Ripard return pctl->groups[group].name; 1330e37f88dSMaxime Ripard } 1340e37f88dSMaxime Ripard 1350e37f88dSMaxime Ripard static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev, 1360e37f88dSMaxime Ripard unsigned group, 1370e37f88dSMaxime Ripard const unsigned **pins, 1380e37f88dSMaxime Ripard unsigned *num_pins) 1390e37f88dSMaxime Ripard { 1400e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 1410e37f88dSMaxime Ripard 1420e37f88dSMaxime Ripard *pins = (unsigned *)&pctl->groups[group].pin; 1430e37f88dSMaxime Ripard *num_pins = 1; 1440e37f88dSMaxime Ripard 1450e37f88dSMaxime Ripard return 0; 1460e37f88dSMaxime Ripard } 1470e37f88dSMaxime Ripard 1480e37f88dSMaxime Ripard static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, 1490e37f88dSMaxime Ripard struct device_node *node, 1500e37f88dSMaxime Ripard struct pinctrl_map **map, 1510e37f88dSMaxime Ripard unsigned *num_maps) 1520e37f88dSMaxime Ripard { 1530e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 1540e37f88dSMaxime Ripard unsigned long *pinconfig; 1550e37f88dSMaxime Ripard struct property *prop; 1560e37f88dSMaxime Ripard const char *function; 1570e37f88dSMaxime Ripard const char *group; 1580e37f88dSMaxime Ripard int ret, nmaps, i = 0; 1590e37f88dSMaxime Ripard u32 val; 1600e37f88dSMaxime Ripard 1610e37f88dSMaxime Ripard *map = NULL; 1620e37f88dSMaxime Ripard *num_maps = 0; 1630e37f88dSMaxime Ripard 1640e37f88dSMaxime Ripard ret = of_property_read_string(node, "allwinner,function", &function); 1650e37f88dSMaxime Ripard if (ret) { 1660e37f88dSMaxime Ripard dev_err(pctl->dev, 1670e37f88dSMaxime Ripard "missing allwinner,function property in node %s\n", 1680e37f88dSMaxime Ripard node->name); 1690e37f88dSMaxime Ripard return -EINVAL; 1700e37f88dSMaxime Ripard } 1710e37f88dSMaxime Ripard 1720e37f88dSMaxime Ripard nmaps = of_property_count_strings(node, "allwinner,pins") * 2; 1730e37f88dSMaxime Ripard if (nmaps < 0) { 1740e37f88dSMaxime Ripard dev_err(pctl->dev, 1750e37f88dSMaxime Ripard "missing allwinner,pins property in node %s\n", 1760e37f88dSMaxime Ripard node->name); 1770e37f88dSMaxime Ripard return -EINVAL; 1780e37f88dSMaxime Ripard } 1790e37f88dSMaxime Ripard 1800e37f88dSMaxime Ripard *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); 1813efa921dSSachin Kamat if (!*map) 1820e37f88dSMaxime Ripard return -ENOMEM; 1830e37f88dSMaxime Ripard 1840e37f88dSMaxime Ripard of_property_for_each_string(node, "allwinner,pins", prop, group) { 1850e37f88dSMaxime Ripard struct sunxi_pinctrl_group *grp = 1860e37f88dSMaxime Ripard sunxi_pinctrl_find_group_by_name(pctl, group); 1870e37f88dSMaxime Ripard int j = 0, configlen = 0; 1880e37f88dSMaxime Ripard 1890e37f88dSMaxime Ripard if (!grp) { 1900e37f88dSMaxime Ripard dev_err(pctl->dev, "unknown pin %s", group); 1910e37f88dSMaxime Ripard continue; 1920e37f88dSMaxime Ripard } 1930e37f88dSMaxime Ripard 1940e37f88dSMaxime Ripard if (!sunxi_pinctrl_desc_find_function_by_name(pctl, 1950e37f88dSMaxime Ripard grp->name, 1960e37f88dSMaxime Ripard function)) { 1970e37f88dSMaxime Ripard dev_err(pctl->dev, "unsupported function %s on pin %s", 1980e37f88dSMaxime Ripard function, group); 1990e37f88dSMaxime Ripard continue; 2000e37f88dSMaxime Ripard } 2010e37f88dSMaxime Ripard 2020e37f88dSMaxime Ripard (*map)[i].type = PIN_MAP_TYPE_MUX_GROUP; 2030e37f88dSMaxime Ripard (*map)[i].data.mux.group = group; 2040e37f88dSMaxime Ripard (*map)[i].data.mux.function = function; 2050e37f88dSMaxime Ripard 2060e37f88dSMaxime Ripard i++; 2070e37f88dSMaxime Ripard 2080e37f88dSMaxime Ripard (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; 2090e37f88dSMaxime Ripard (*map)[i].data.configs.group_or_pin = group; 2100e37f88dSMaxime Ripard 2110e37f88dSMaxime Ripard if (of_find_property(node, "allwinner,drive", NULL)) 2120e37f88dSMaxime Ripard configlen++; 2130e37f88dSMaxime Ripard if (of_find_property(node, "allwinner,pull", NULL)) 2140e37f88dSMaxime Ripard configlen++; 2150e37f88dSMaxime Ripard 2160e37f88dSMaxime Ripard pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); 2170e37f88dSMaxime Ripard 2180e37f88dSMaxime Ripard if (!of_property_read_u32(node, "allwinner,drive", &val)) { 2190e37f88dSMaxime Ripard u16 strength = (val + 1) * 10; 2200e37f88dSMaxime Ripard pinconfig[j++] = 2210e37f88dSMaxime Ripard pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, 2220e37f88dSMaxime Ripard strength); 2230e37f88dSMaxime Ripard } 2240e37f88dSMaxime Ripard 2250e37f88dSMaxime Ripard if (!of_property_read_u32(node, "allwinner,pull", &val)) { 2260e37f88dSMaxime Ripard enum pin_config_param pull = PIN_CONFIG_END; 2270e37f88dSMaxime Ripard if (val == 1) 2280e37f88dSMaxime Ripard pull = PIN_CONFIG_BIAS_PULL_UP; 2290e37f88dSMaxime Ripard else if (val == 2) 2300e37f88dSMaxime Ripard pull = PIN_CONFIG_BIAS_PULL_DOWN; 2310e37f88dSMaxime Ripard pinconfig[j++] = pinconf_to_config_packed(pull, 0); 2320e37f88dSMaxime Ripard } 2330e37f88dSMaxime Ripard 2340e37f88dSMaxime Ripard (*map)[i].data.configs.configs = pinconfig; 2350e37f88dSMaxime Ripard (*map)[i].data.configs.num_configs = configlen; 2360e37f88dSMaxime Ripard 2370e37f88dSMaxime Ripard i++; 2380e37f88dSMaxime Ripard } 2390e37f88dSMaxime Ripard 2400e37f88dSMaxime Ripard *num_maps = nmaps; 2410e37f88dSMaxime Ripard 2420e37f88dSMaxime Ripard return 0; 2430e37f88dSMaxime Ripard } 2440e37f88dSMaxime Ripard 2450e37f88dSMaxime Ripard static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev, 2460e37f88dSMaxime Ripard struct pinctrl_map *map, 2470e37f88dSMaxime Ripard unsigned num_maps) 2480e37f88dSMaxime Ripard { 2490e37f88dSMaxime Ripard int i; 2500e37f88dSMaxime Ripard 2510e37f88dSMaxime Ripard for (i = 0; i < num_maps; i++) { 2520e37f88dSMaxime Ripard if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) 2530e37f88dSMaxime Ripard kfree(map[i].data.configs.configs); 2540e37f88dSMaxime Ripard } 2550e37f88dSMaxime Ripard 2560e37f88dSMaxime Ripard kfree(map); 2570e37f88dSMaxime Ripard } 2580e37f88dSMaxime Ripard 259022ab148SLaurent Pinchart static const struct pinctrl_ops sunxi_pctrl_ops = { 2600e37f88dSMaxime Ripard .dt_node_to_map = sunxi_pctrl_dt_node_to_map, 2610e37f88dSMaxime Ripard .dt_free_map = sunxi_pctrl_dt_free_map, 2620e37f88dSMaxime Ripard .get_groups_count = sunxi_pctrl_get_groups_count, 2630e37f88dSMaxime Ripard .get_group_name = sunxi_pctrl_get_group_name, 2640e37f88dSMaxime Ripard .get_group_pins = sunxi_pctrl_get_group_pins, 2650e37f88dSMaxime Ripard }; 2660e37f88dSMaxime Ripard 2670e37f88dSMaxime Ripard static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev, 2680e37f88dSMaxime Ripard unsigned group, 2690e37f88dSMaxime Ripard unsigned long *config) 2700e37f88dSMaxime Ripard { 2710e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 2720e37f88dSMaxime Ripard 2730e37f88dSMaxime Ripard *config = pctl->groups[group].config; 2740e37f88dSMaxime Ripard 2750e37f88dSMaxime Ripard return 0; 2760e37f88dSMaxime Ripard } 2770e37f88dSMaxime Ripard 2780e37f88dSMaxime Ripard static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, 2790e37f88dSMaxime Ripard unsigned group, 28003b054e9SSherman Yin unsigned long *configs, 28103b054e9SSherman Yin unsigned num_configs) 2820e37f88dSMaxime Ripard { 2830e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 2840e37f88dSMaxime Ripard struct sunxi_pinctrl_group *g = &pctl->groups[group]; 2851bee963dSMaxime Ripard unsigned long flags; 286b4575c69SChen-Yu Tsai unsigned pin = g->pin - pctl->desc->pin_base; 2870e37f88dSMaxime Ripard u32 val, mask; 2880e37f88dSMaxime Ripard u16 strength; 2890e37f88dSMaxime Ripard u8 dlevel; 29003b054e9SSherman Yin int i; 2910e37f88dSMaxime Ripard 2926ad30ce0SLinus Walleij spin_lock_irqsave(&pctl->lock, flags); 2936ad30ce0SLinus Walleij 29403b054e9SSherman Yin for (i = 0; i < num_configs; i++) { 29503b054e9SSherman Yin switch (pinconf_to_config_param(configs[i])) { 2960e37f88dSMaxime Ripard case PIN_CONFIG_DRIVE_STRENGTH: 29703b054e9SSherman Yin strength = pinconf_to_config_argument(configs[i]); 29807b7eb92SLinus Walleij if (strength > 40) { 29907b7eb92SLinus Walleij spin_unlock_irqrestore(&pctl->lock, flags); 3000e37f88dSMaxime Ripard return -EINVAL; 30107b7eb92SLinus Walleij } 3020e37f88dSMaxime Ripard /* 3030e37f88dSMaxime Ripard * We convert from mA to what the register expects: 3040e37f88dSMaxime Ripard * 0: 10mA 3050e37f88dSMaxime Ripard * 1: 20mA 3060e37f88dSMaxime Ripard * 2: 30mA 3070e37f88dSMaxime Ripard * 3: 40mA 3080e37f88dSMaxime Ripard */ 3090e37f88dSMaxime Ripard dlevel = strength / 10 - 1; 310b4575c69SChen-Yu Tsai val = readl(pctl->membase + sunxi_dlevel_reg(pin)); 311b4575c69SChen-Yu Tsai mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(pin); 31203b054e9SSherman Yin writel((val & ~mask) 313b4575c69SChen-Yu Tsai | dlevel << sunxi_dlevel_offset(pin), 314b4575c69SChen-Yu Tsai pctl->membase + sunxi_dlevel_reg(pin)); 3150e37f88dSMaxime Ripard break; 3160e37f88dSMaxime Ripard case PIN_CONFIG_BIAS_PULL_UP: 317b4575c69SChen-Yu Tsai val = readl(pctl->membase + sunxi_pull_reg(pin)); 318b4575c69SChen-Yu Tsai mask = PULL_PINS_MASK << sunxi_pull_offset(pin); 319b4575c69SChen-Yu Tsai writel((val & ~mask) | 1 << sunxi_pull_offset(pin), 320b4575c69SChen-Yu Tsai pctl->membase + sunxi_pull_reg(pin)); 3210e37f88dSMaxime Ripard break; 3220e37f88dSMaxime Ripard case PIN_CONFIG_BIAS_PULL_DOWN: 323b4575c69SChen-Yu Tsai val = readl(pctl->membase + sunxi_pull_reg(pin)); 324b4575c69SChen-Yu Tsai mask = PULL_PINS_MASK << sunxi_pull_offset(pin); 325b4575c69SChen-Yu Tsai writel((val & ~mask) | 2 << sunxi_pull_offset(pin), 326b4575c69SChen-Yu Tsai pctl->membase + sunxi_pull_reg(pin)); 3270e37f88dSMaxime Ripard break; 3280e37f88dSMaxime Ripard default: 3290e37f88dSMaxime Ripard break; 3300e37f88dSMaxime Ripard } 3310e37f88dSMaxime Ripard /* cache the config value */ 33203b054e9SSherman Yin g->config = configs[i]; 33303b054e9SSherman Yin } /* for each config */ 3340e37f88dSMaxime Ripard 3356ad30ce0SLinus Walleij spin_unlock_irqrestore(&pctl->lock, flags); 3360e37f88dSMaxime Ripard 3370e37f88dSMaxime Ripard return 0; 3380e37f88dSMaxime Ripard } 3390e37f88dSMaxime Ripard 340022ab148SLaurent Pinchart static const struct pinconf_ops sunxi_pconf_ops = { 3410e37f88dSMaxime Ripard .pin_config_group_get = sunxi_pconf_group_get, 3420e37f88dSMaxime Ripard .pin_config_group_set = sunxi_pconf_group_set, 3430e37f88dSMaxime Ripard }; 3440e37f88dSMaxime Ripard 3450e37f88dSMaxime Ripard static int sunxi_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) 3460e37f88dSMaxime Ripard { 3470e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 3480e37f88dSMaxime Ripard 3490e37f88dSMaxime Ripard return pctl->nfunctions; 3500e37f88dSMaxime Ripard } 3510e37f88dSMaxime Ripard 3520e37f88dSMaxime Ripard static const char *sunxi_pmx_get_func_name(struct pinctrl_dev *pctldev, 3530e37f88dSMaxime Ripard unsigned function) 3540e37f88dSMaxime Ripard { 3550e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 3560e37f88dSMaxime Ripard 3570e37f88dSMaxime Ripard return pctl->functions[function].name; 3580e37f88dSMaxime Ripard } 3590e37f88dSMaxime Ripard 3600e37f88dSMaxime Ripard static int sunxi_pmx_get_func_groups(struct pinctrl_dev *pctldev, 3610e37f88dSMaxime Ripard unsigned function, 3620e37f88dSMaxime Ripard const char * const **groups, 3630e37f88dSMaxime Ripard unsigned * const num_groups) 3640e37f88dSMaxime Ripard { 3650e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 3660e37f88dSMaxime Ripard 3670e37f88dSMaxime Ripard *groups = pctl->functions[function].groups; 3680e37f88dSMaxime Ripard *num_groups = pctl->functions[function].ngroups; 3690e37f88dSMaxime Ripard 3700e37f88dSMaxime Ripard return 0; 3710e37f88dSMaxime Ripard } 3720e37f88dSMaxime Ripard 3730e37f88dSMaxime Ripard static void sunxi_pmx_set(struct pinctrl_dev *pctldev, 3740e37f88dSMaxime Ripard unsigned pin, 3750e37f88dSMaxime Ripard u8 config) 3760e37f88dSMaxime Ripard { 3770e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 3781bee963dSMaxime Ripard unsigned long flags; 3791bee963dSMaxime Ripard u32 val, mask; 3800e37f88dSMaxime Ripard 3811bee963dSMaxime Ripard spin_lock_irqsave(&pctl->lock, flags); 3821bee963dSMaxime Ripard 383b4575c69SChen-Yu Tsai pin -= pctl->desc->pin_base; 3841bee963dSMaxime Ripard val = readl(pctl->membase + sunxi_mux_reg(pin)); 3851bee963dSMaxime Ripard mask = MUX_PINS_MASK << sunxi_mux_offset(pin); 3860e37f88dSMaxime Ripard writel((val & ~mask) | config << sunxi_mux_offset(pin), 3870e37f88dSMaxime Ripard pctl->membase + sunxi_mux_reg(pin)); 3881bee963dSMaxime Ripard 3891bee963dSMaxime Ripard spin_unlock_irqrestore(&pctl->lock, flags); 3900e37f88dSMaxime Ripard } 3910e37f88dSMaxime Ripard 3920e37f88dSMaxime Ripard static int sunxi_pmx_enable(struct pinctrl_dev *pctldev, 3930e37f88dSMaxime Ripard unsigned function, 3940e37f88dSMaxime Ripard unsigned group) 3950e37f88dSMaxime Ripard { 3960e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 3970e37f88dSMaxime Ripard struct sunxi_pinctrl_group *g = pctl->groups + group; 3980e37f88dSMaxime Ripard struct sunxi_pinctrl_function *func = pctl->functions + function; 3990e37f88dSMaxime Ripard struct sunxi_desc_function *desc = 4000e37f88dSMaxime Ripard sunxi_pinctrl_desc_find_function_by_name(pctl, 4010e37f88dSMaxime Ripard g->name, 4020e37f88dSMaxime Ripard func->name); 4030e37f88dSMaxime Ripard 4040e37f88dSMaxime Ripard if (!desc) 4050e37f88dSMaxime Ripard return -EINVAL; 4060e37f88dSMaxime Ripard 4070e37f88dSMaxime Ripard sunxi_pmx_set(pctldev, g->pin, desc->muxval); 4080e37f88dSMaxime Ripard 4090e37f88dSMaxime Ripard return 0; 4100e37f88dSMaxime Ripard } 4110e37f88dSMaxime Ripard 41208e9e614SMaxime Ripard static int 41308e9e614SMaxime Ripard sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, 41408e9e614SMaxime Ripard struct pinctrl_gpio_range *range, 41508e9e614SMaxime Ripard unsigned offset, 41608e9e614SMaxime Ripard bool input) 41708e9e614SMaxime Ripard { 41808e9e614SMaxime Ripard struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 41908e9e614SMaxime Ripard struct sunxi_desc_function *desc; 42008e9e614SMaxime Ripard const char *func; 42108e9e614SMaxime Ripard 42208e9e614SMaxime Ripard if (input) 42308e9e614SMaxime Ripard func = "gpio_in"; 42408e9e614SMaxime Ripard else 42508e9e614SMaxime Ripard func = "gpio_out"; 42608e9e614SMaxime Ripard 427814d4f2eSMaxime Ripard desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, func); 428814d4f2eSMaxime Ripard if (!desc) 429814d4f2eSMaxime Ripard return -EINVAL; 43008e9e614SMaxime Ripard 43108e9e614SMaxime Ripard sunxi_pmx_set(pctldev, offset, desc->muxval); 43208e9e614SMaxime Ripard 433814d4f2eSMaxime Ripard return 0; 43408e9e614SMaxime Ripard } 43508e9e614SMaxime Ripard 436022ab148SLaurent Pinchart static const struct pinmux_ops sunxi_pmx_ops = { 4370e37f88dSMaxime Ripard .get_functions_count = sunxi_pmx_get_funcs_cnt, 4380e37f88dSMaxime Ripard .get_function_name = sunxi_pmx_get_func_name, 4390e37f88dSMaxime Ripard .get_function_groups = sunxi_pmx_get_func_groups, 4400e37f88dSMaxime Ripard .enable = sunxi_pmx_enable, 44108e9e614SMaxime Ripard .gpio_set_direction = sunxi_pmx_gpio_set_direction, 4420e37f88dSMaxime Ripard }; 4430e37f88dSMaxime Ripard 44408e9e614SMaxime Ripard static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset) 44508e9e614SMaxime Ripard { 44608e9e614SMaxime Ripard return pinctrl_request_gpio(chip->base + offset); 44708e9e614SMaxime Ripard } 44808e9e614SMaxime Ripard 44908e9e614SMaxime Ripard static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset) 45008e9e614SMaxime Ripard { 45108e9e614SMaxime Ripard pinctrl_free_gpio(chip->base + offset); 45208e9e614SMaxime Ripard } 45308e9e614SMaxime Ripard 45408e9e614SMaxime Ripard static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip, 45508e9e614SMaxime Ripard unsigned offset) 45608e9e614SMaxime Ripard { 45708e9e614SMaxime Ripard return pinctrl_gpio_direction_input(chip->base + offset); 45808e9e614SMaxime Ripard } 45908e9e614SMaxime Ripard 46008e9e614SMaxime Ripard static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset) 46108e9e614SMaxime Ripard { 46208e9e614SMaxime Ripard struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev); 46308e9e614SMaxime Ripard 46408e9e614SMaxime Ripard u32 reg = sunxi_data_reg(offset); 46508e9e614SMaxime Ripard u8 index = sunxi_data_offset(offset); 46608e9e614SMaxime Ripard u32 val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK; 46708e9e614SMaxime Ripard 46808e9e614SMaxime Ripard return val; 46908e9e614SMaxime Ripard } 47008e9e614SMaxime Ripard 47108e9e614SMaxime Ripard static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip, 47208e9e614SMaxime Ripard unsigned offset, int value) 47308e9e614SMaxime Ripard { 47408e9e614SMaxime Ripard struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev); 47508e9e614SMaxime Ripard u32 reg = sunxi_data_reg(offset); 47608e9e614SMaxime Ripard u8 index = sunxi_data_offset(offset); 4771bee963dSMaxime Ripard unsigned long flags; 4781bee963dSMaxime Ripard u32 regval; 47908e9e614SMaxime Ripard 4801bee963dSMaxime Ripard spin_lock_irqsave(&pctl->lock, flags); 4811bee963dSMaxime Ripard 4821bee963dSMaxime Ripard regval = readl(pctl->membase + reg); 48308e9e614SMaxime Ripard 484df7b34f4SMaxime Ripard if (value) 485df7b34f4SMaxime Ripard regval |= BIT(index); 486df7b34f4SMaxime Ripard else 487df7b34f4SMaxime Ripard regval &= ~(BIT(index)); 488df7b34f4SMaxime Ripard 489df7b34f4SMaxime Ripard writel(regval, pctl->membase + reg); 4901bee963dSMaxime Ripard 4911bee963dSMaxime Ripard spin_unlock_irqrestore(&pctl->lock, flags); 49208e9e614SMaxime Ripard } 49308e9e614SMaxime Ripard 494fa8cf57cSChen-Yu Tsai static int sunxi_pinctrl_gpio_direction_output(struct gpio_chip *chip, 495fa8cf57cSChen-Yu Tsai unsigned offset, int value) 496fa8cf57cSChen-Yu Tsai { 497fa8cf57cSChen-Yu Tsai sunxi_pinctrl_gpio_set(chip, offset, value); 498fa8cf57cSChen-Yu Tsai return pinctrl_gpio_direction_output(chip->base + offset); 499fa8cf57cSChen-Yu Tsai } 500fa8cf57cSChen-Yu Tsai 501a0d72094SMaxime Ripard static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc, 502a0d72094SMaxime Ripard const struct of_phandle_args *gpiospec, 503a0d72094SMaxime Ripard u32 *flags) 504a0d72094SMaxime Ripard { 505a0d72094SMaxime Ripard int pin, base; 506a0d72094SMaxime Ripard 507a0d72094SMaxime Ripard base = PINS_PER_BANK * gpiospec->args[0]; 508a0d72094SMaxime Ripard pin = base + gpiospec->args[1]; 509a0d72094SMaxime Ripard 510a0d72094SMaxime Ripard if (pin > (gc->base + gc->ngpio)) 511a0d72094SMaxime Ripard return -EINVAL; 512a0d72094SMaxime Ripard 513a0d72094SMaxime Ripard if (flags) 514a0d72094SMaxime Ripard *flags = gpiospec->args[2]; 515a0d72094SMaxime Ripard 516a0d72094SMaxime Ripard return pin; 517a0d72094SMaxime Ripard } 518a0d72094SMaxime Ripard 51960242db1SMaxime Ripard static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 52060242db1SMaxime Ripard { 52160242db1SMaxime Ripard struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev); 52260242db1SMaxime Ripard struct sunxi_desc_function *desc; 52360242db1SMaxime Ripard 524c9e3b2d8SAxel Lin if (offset >= chip->ngpio) 52560242db1SMaxime Ripard return -ENXIO; 52660242db1SMaxime Ripard 52760242db1SMaxime Ripard desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq"); 52860242db1SMaxime Ripard if (!desc) 52960242db1SMaxime Ripard return -EINVAL; 53060242db1SMaxime Ripard 53160242db1SMaxime Ripard dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", 53260242db1SMaxime Ripard chip->label, offset + chip->base, desc->irqnum); 53360242db1SMaxime Ripard 53460242db1SMaxime Ripard return irq_find_mapping(pctl->domain, desc->irqnum); 53560242db1SMaxime Ripard } 53660242db1SMaxime Ripard 537fea6d8efSHans de Goede static int sunxi_pinctrl_irq_request_resources(struct irq_data *d) 538fea6d8efSHans de Goede { 539fea6d8efSHans de Goede struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 540fea6d8efSHans de Goede struct sunxi_desc_function *func; 541fea6d8efSHans de Goede 542fea6d8efSHans de Goede func = sunxi_pinctrl_desc_find_function_by_pin(pctl, 543fea6d8efSHans de Goede pctl->irq_array[d->hwirq], "irq"); 544fea6d8efSHans de Goede if (!func) 545fea6d8efSHans de Goede return -EINVAL; 546fea6d8efSHans de Goede 547fea6d8efSHans de Goede /* Change muxing to INT mode */ 548fea6d8efSHans de Goede sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval); 549fea6d8efSHans de Goede 550fea6d8efSHans de Goede return 0; 551fea6d8efSHans de Goede } 55208e9e614SMaxime Ripard 553*f4c51c10SHans de Goede static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type) 55460242db1SMaxime Ripard { 55560242db1SMaxime Ripard struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 556*f4c51c10SHans de Goede struct irq_desc *desc = container_of(d, struct irq_desc, irq_data); 55760242db1SMaxime Ripard u32 reg = sunxi_irq_cfg_reg(d->hwirq); 55860242db1SMaxime Ripard u8 index = sunxi_irq_cfg_offset(d->hwirq); 5591bee963dSMaxime Ripard unsigned long flags; 5602aaaddffSMaxime Ripard u32 regval; 56160242db1SMaxime Ripard u8 mode; 56260242db1SMaxime Ripard 56360242db1SMaxime Ripard switch (type) { 56460242db1SMaxime Ripard case IRQ_TYPE_EDGE_RISING: 56560242db1SMaxime Ripard mode = IRQ_EDGE_RISING; 56660242db1SMaxime Ripard break; 56760242db1SMaxime Ripard case IRQ_TYPE_EDGE_FALLING: 56860242db1SMaxime Ripard mode = IRQ_EDGE_FALLING; 56960242db1SMaxime Ripard break; 57060242db1SMaxime Ripard case IRQ_TYPE_EDGE_BOTH: 57160242db1SMaxime Ripard mode = IRQ_EDGE_BOTH; 57260242db1SMaxime Ripard break; 57360242db1SMaxime Ripard case IRQ_TYPE_LEVEL_HIGH: 57460242db1SMaxime Ripard mode = IRQ_LEVEL_HIGH; 57560242db1SMaxime Ripard break; 57660242db1SMaxime Ripard case IRQ_TYPE_LEVEL_LOW: 57760242db1SMaxime Ripard mode = IRQ_LEVEL_LOW; 57860242db1SMaxime Ripard break; 57960242db1SMaxime Ripard default: 58060242db1SMaxime Ripard return -EINVAL; 58160242db1SMaxime Ripard } 58260242db1SMaxime Ripard 583*f4c51c10SHans de Goede if (type & IRQ_TYPE_LEVEL_MASK) { 584*f4c51c10SHans de Goede d->chip = &sunxi_pinctrl_level_irq_chip; 585*f4c51c10SHans de Goede desc->handle_irq = handle_fasteoi_irq; 586*f4c51c10SHans de Goede } else { 587*f4c51c10SHans de Goede d->chip = &sunxi_pinctrl_edge_irq_chip; 588*f4c51c10SHans de Goede desc->handle_irq = handle_edge_irq; 589*f4c51c10SHans de Goede } 590*f4c51c10SHans de Goede 5911bee963dSMaxime Ripard spin_lock_irqsave(&pctl->lock, flags); 5921bee963dSMaxime Ripard 5932aaaddffSMaxime Ripard regval = readl(pctl->membase + reg); 594d82f9401SHans de Goede regval &= ~(IRQ_CFG_IRQ_MASK << index); 5952aaaddffSMaxime Ripard writel(regval | (mode << index), pctl->membase + reg); 59660242db1SMaxime Ripard 5971bee963dSMaxime Ripard spin_unlock_irqrestore(&pctl->lock, flags); 59860242db1SMaxime Ripard 59960242db1SMaxime Ripard return 0; 60060242db1SMaxime Ripard } 60160242db1SMaxime Ripard 602645ec714SMaxime Ripard static void sunxi_pinctrl_irq_ack(struct irq_data *d) 60360242db1SMaxime Ripard { 60460242db1SMaxime Ripard struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 60560242db1SMaxime Ripard u32 status_reg = sunxi_irq_status_reg(d->hwirq); 60660242db1SMaxime Ripard u8 status_idx = sunxi_irq_status_offset(d->hwirq); 60760242db1SMaxime Ripard 60860242db1SMaxime Ripard /* Clear the IRQ */ 60960242db1SMaxime Ripard writel(1 << status_idx, pctl->membase + status_reg); 61060242db1SMaxime Ripard } 61160242db1SMaxime Ripard 61260242db1SMaxime Ripard static void sunxi_pinctrl_irq_mask(struct irq_data *d) 61360242db1SMaxime Ripard { 61460242db1SMaxime Ripard struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 61560242db1SMaxime Ripard u32 reg = sunxi_irq_ctrl_reg(d->hwirq); 61660242db1SMaxime Ripard u8 idx = sunxi_irq_ctrl_offset(d->hwirq); 6171bee963dSMaxime Ripard unsigned long flags; 61860242db1SMaxime Ripard u32 val; 61960242db1SMaxime Ripard 6201bee963dSMaxime Ripard spin_lock_irqsave(&pctl->lock, flags); 6211bee963dSMaxime Ripard 62260242db1SMaxime Ripard /* Mask the IRQ */ 62360242db1SMaxime Ripard val = readl(pctl->membase + reg); 62460242db1SMaxime Ripard writel(val & ~(1 << idx), pctl->membase + reg); 6251bee963dSMaxime Ripard 6261bee963dSMaxime Ripard spin_unlock_irqrestore(&pctl->lock, flags); 62760242db1SMaxime Ripard } 62860242db1SMaxime Ripard 62960242db1SMaxime Ripard static void sunxi_pinctrl_irq_unmask(struct irq_data *d) 63060242db1SMaxime Ripard { 63160242db1SMaxime Ripard struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 63260242db1SMaxime Ripard u32 reg = sunxi_irq_ctrl_reg(d->hwirq); 63360242db1SMaxime Ripard u8 idx = sunxi_irq_ctrl_offset(d->hwirq); 6341bee963dSMaxime Ripard unsigned long flags; 63560242db1SMaxime Ripard u32 val; 63660242db1SMaxime Ripard 6371bee963dSMaxime Ripard spin_lock_irqsave(&pctl->lock, flags); 6381bee963dSMaxime Ripard 63960242db1SMaxime Ripard /* Unmask the IRQ */ 64060242db1SMaxime Ripard val = readl(pctl->membase + reg); 64160242db1SMaxime Ripard writel(val | (1 << idx), pctl->membase + reg); 6421bee963dSMaxime Ripard 6431bee963dSMaxime Ripard spin_unlock_irqrestore(&pctl->lock, flags); 64460242db1SMaxime Ripard } 64560242db1SMaxime Ripard 646*f4c51c10SHans de Goede static struct irq_chip sunxi_pinctrl_edge_irq_chip = { 647645ec714SMaxime Ripard .irq_ack = sunxi_pinctrl_irq_ack, 64860242db1SMaxime Ripard .irq_mask = sunxi_pinctrl_irq_mask, 64960242db1SMaxime Ripard .irq_unmask = sunxi_pinctrl_irq_unmask, 650fea6d8efSHans de Goede .irq_request_resources = sunxi_pinctrl_irq_request_resources, 65160242db1SMaxime Ripard .irq_set_type = sunxi_pinctrl_irq_set_type, 652578c0a87SChen-Yu Tsai .flags = IRQCHIP_SKIP_SET_WAKE, 65360242db1SMaxime Ripard }; 65460242db1SMaxime Ripard 655*f4c51c10SHans de Goede static struct irq_chip sunxi_pinctrl_level_irq_chip = { 656*f4c51c10SHans de Goede .irq_eoi = sunxi_pinctrl_irq_ack, 657*f4c51c10SHans de Goede .irq_mask = sunxi_pinctrl_irq_mask, 658*f4c51c10SHans de Goede .irq_unmask = sunxi_pinctrl_irq_unmask, 659*f4c51c10SHans de Goede .irq_request_resources = sunxi_pinctrl_irq_request_resources, 660*f4c51c10SHans de Goede .irq_set_type = sunxi_pinctrl_irq_set_type, 661*f4c51c10SHans de Goede .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED | 662*f4c51c10SHans de Goede IRQCHIP_EOI_IF_HANDLED, 663*f4c51c10SHans de Goede }; 664*f4c51c10SHans de Goede 66560242db1SMaxime Ripard static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) 66660242db1SMaxime Ripard { 667905a5117SChen-Yu Tsai struct irq_chip *chip = irq_get_chip(irq); 66860242db1SMaxime Ripard struct sunxi_pinctrl *pctl = irq_get_handler_data(irq); 669aebdc8abSMaxime Ripard unsigned long bank, reg, val; 670aebdc8abSMaxime Ripard 671aebdc8abSMaxime Ripard for (bank = 0; bank < pctl->desc->irq_banks; bank++) 672aebdc8abSMaxime Ripard if (irq == pctl->irq[bank]) 673aebdc8abSMaxime Ripard break; 674aebdc8abSMaxime Ripard 675aebdc8abSMaxime Ripard if (bank == pctl->desc->irq_banks) 676aebdc8abSMaxime Ripard return; 677aebdc8abSMaxime Ripard 678aebdc8abSMaxime Ripard reg = sunxi_irq_status_reg_from_bank(bank); 679aebdc8abSMaxime Ripard val = readl(pctl->membase + reg); 68060242db1SMaxime Ripard 681aebdc8abSMaxime Ripard if (val) { 68260242db1SMaxime Ripard int irqoffset; 68360242db1SMaxime Ripard 684905a5117SChen-Yu Tsai chained_irq_enter(chip, desc); 685aebdc8abSMaxime Ripard for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) { 686aebdc8abSMaxime Ripard int pin_irq = irq_find_mapping(pctl->domain, 687aebdc8abSMaxime Ripard bank * IRQ_PER_BANK + irqoffset); 68860242db1SMaxime Ripard generic_handle_irq(pin_irq); 68960242db1SMaxime Ripard } 690905a5117SChen-Yu Tsai chained_irq_exit(chip, desc); 69160242db1SMaxime Ripard } 69260242db1SMaxime Ripard } 69360242db1SMaxime Ripard 6940e37f88dSMaxime Ripard static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl, 6950e37f88dSMaxime Ripard const char *name) 6960e37f88dSMaxime Ripard { 6970e37f88dSMaxime Ripard struct sunxi_pinctrl_function *func = pctl->functions; 6980e37f88dSMaxime Ripard 6990e37f88dSMaxime Ripard while (func->name) { 7000e37f88dSMaxime Ripard /* function already there */ 7010e37f88dSMaxime Ripard if (strcmp(func->name, name) == 0) { 7020e37f88dSMaxime Ripard func->ngroups++; 7030e37f88dSMaxime Ripard return -EEXIST; 7040e37f88dSMaxime Ripard } 7050e37f88dSMaxime Ripard func++; 7060e37f88dSMaxime Ripard } 7070e37f88dSMaxime Ripard 7080e37f88dSMaxime Ripard func->name = name; 7090e37f88dSMaxime Ripard func->ngroups = 1; 7100e37f88dSMaxime Ripard 7110e37f88dSMaxime Ripard pctl->nfunctions++; 7120e37f88dSMaxime Ripard 7130e37f88dSMaxime Ripard return 0; 7140e37f88dSMaxime Ripard } 7150e37f88dSMaxime Ripard 7160e37f88dSMaxime Ripard static int sunxi_pinctrl_build_state(struct platform_device *pdev) 7170e37f88dSMaxime Ripard { 7180e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev); 7190e37f88dSMaxime Ripard int i; 7200e37f88dSMaxime Ripard 7210e37f88dSMaxime Ripard pctl->ngroups = pctl->desc->npins; 7220e37f88dSMaxime Ripard 7230e37f88dSMaxime Ripard /* Allocate groups */ 7240e37f88dSMaxime Ripard pctl->groups = devm_kzalloc(&pdev->dev, 7250e37f88dSMaxime Ripard pctl->ngroups * sizeof(*pctl->groups), 7260e37f88dSMaxime Ripard GFP_KERNEL); 7270e37f88dSMaxime Ripard if (!pctl->groups) 7280e37f88dSMaxime Ripard return -ENOMEM; 7290e37f88dSMaxime Ripard 7300e37f88dSMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) { 7310e37f88dSMaxime Ripard const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 7320e37f88dSMaxime Ripard struct sunxi_pinctrl_group *group = pctl->groups + i; 7330e37f88dSMaxime Ripard 7340e37f88dSMaxime Ripard group->name = pin->pin.name; 7350e37f88dSMaxime Ripard group->pin = pin->pin.number; 7360e37f88dSMaxime Ripard } 7370e37f88dSMaxime Ripard 7380e37f88dSMaxime Ripard /* 7390e37f88dSMaxime Ripard * We suppose that we won't have any more functions than pins, 7400e37f88dSMaxime Ripard * we'll reallocate that later anyway 7410e37f88dSMaxime Ripard */ 7420e37f88dSMaxime Ripard pctl->functions = devm_kzalloc(&pdev->dev, 7430e37f88dSMaxime Ripard pctl->desc->npins * sizeof(*pctl->functions), 7440e37f88dSMaxime Ripard GFP_KERNEL); 7450e37f88dSMaxime Ripard if (!pctl->functions) 7460e37f88dSMaxime Ripard return -ENOMEM; 7470e37f88dSMaxime Ripard 7480e37f88dSMaxime Ripard /* Count functions and their associated groups */ 7490e37f88dSMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) { 7500e37f88dSMaxime Ripard const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 7510e37f88dSMaxime Ripard struct sunxi_desc_function *func = pin->functions; 7520e37f88dSMaxime Ripard 7530e37f88dSMaxime Ripard while (func->name) { 754d54e9a28SChen-Yu Tsai /* Create interrupt mapping while we're at it */ 755aebdc8abSMaxime Ripard if (!strcmp(func->name, "irq")) { 756aebdc8abSMaxime Ripard int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK; 757aebdc8abSMaxime Ripard pctl->irq_array[irqnum] = pin->pin.number; 758aebdc8abSMaxime Ripard } 759aebdc8abSMaxime Ripard 7600e37f88dSMaxime Ripard sunxi_pinctrl_add_function(pctl, func->name); 7610e37f88dSMaxime Ripard func++; 7620e37f88dSMaxime Ripard } 7630e37f88dSMaxime Ripard } 7640e37f88dSMaxime Ripard 7650e37f88dSMaxime Ripard pctl->functions = krealloc(pctl->functions, 7660e37f88dSMaxime Ripard pctl->nfunctions * sizeof(*pctl->functions), 7670e37f88dSMaxime Ripard GFP_KERNEL); 7680e37f88dSMaxime Ripard 7690e37f88dSMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) { 7700e37f88dSMaxime Ripard const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 7710e37f88dSMaxime Ripard struct sunxi_desc_function *func = pin->functions; 7720e37f88dSMaxime Ripard 7730e37f88dSMaxime Ripard while (func->name) { 7740e37f88dSMaxime Ripard struct sunxi_pinctrl_function *func_item; 7750e37f88dSMaxime Ripard const char **func_grp; 7760e37f88dSMaxime Ripard 7770e37f88dSMaxime Ripard func_item = sunxi_pinctrl_find_function_by_name(pctl, 7780e37f88dSMaxime Ripard func->name); 7790e37f88dSMaxime Ripard if (!func_item) 7800e37f88dSMaxime Ripard return -EINVAL; 7810e37f88dSMaxime Ripard 7820e37f88dSMaxime Ripard if (!func_item->groups) { 7830e37f88dSMaxime Ripard func_item->groups = 7840e37f88dSMaxime Ripard devm_kzalloc(&pdev->dev, 7850e37f88dSMaxime Ripard func_item->ngroups * sizeof(*func_item->groups), 7860e37f88dSMaxime Ripard GFP_KERNEL); 7870e37f88dSMaxime Ripard if (!func_item->groups) 7880e37f88dSMaxime Ripard return -ENOMEM; 7890e37f88dSMaxime Ripard } 7900e37f88dSMaxime Ripard 7910e37f88dSMaxime Ripard func_grp = func_item->groups; 7920e37f88dSMaxime Ripard while (*func_grp) 7930e37f88dSMaxime Ripard func_grp++; 7940e37f88dSMaxime Ripard 7950e37f88dSMaxime Ripard *func_grp = pin->pin.name; 7960e37f88dSMaxime Ripard func++; 7970e37f88dSMaxime Ripard } 7980e37f88dSMaxime Ripard } 7990e37f88dSMaxime Ripard 8000e37f88dSMaxime Ripard return 0; 8010e37f88dSMaxime Ripard } 8020e37f88dSMaxime Ripard 8032284ba6bSMaxime Ripard int sunxi_pinctrl_init(struct platform_device *pdev, 8042284ba6bSMaxime Ripard const struct sunxi_pinctrl_desc *desc) 8050e37f88dSMaxime Ripard { 8060e37f88dSMaxime Ripard struct device_node *node = pdev->dev.of_node; 807ba6764d5SMaxime Ripard struct pinctrl_desc *pctrl_desc; 8080e37f88dSMaxime Ripard struct pinctrl_pin_desc *pins; 8090e37f88dSMaxime Ripard struct sunxi_pinctrl *pctl; 8104409cafcSMaxime Ripard struct resource *res; 81108e9e614SMaxime Ripard int i, ret, last_pin; 812950707c0SEmilio López struct clk *clk; 8130e37f88dSMaxime Ripard 8140e37f88dSMaxime Ripard pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); 8150e37f88dSMaxime Ripard if (!pctl) 8160e37f88dSMaxime Ripard return -ENOMEM; 8170e37f88dSMaxime Ripard platform_set_drvdata(pdev, pctl); 8180e37f88dSMaxime Ripard 8191bee963dSMaxime Ripard spin_lock_init(&pctl->lock); 8201bee963dSMaxime Ripard 8214409cafcSMaxime Ripard res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8224409cafcSMaxime Ripard pctl->membase = devm_ioremap_resource(&pdev->dev, res); 8234409cafcSMaxime Ripard if (IS_ERR(pctl->membase)) 8244409cafcSMaxime Ripard return PTR_ERR(pctl->membase); 8250e37f88dSMaxime Ripard 826ba6764d5SMaxime Ripard pctl->dev = &pdev->dev; 8272284ba6bSMaxime Ripard pctl->desc = desc; 8280e37f88dSMaxime Ripard 829aebdc8abSMaxime Ripard pctl->irq_array = devm_kcalloc(&pdev->dev, 830aebdc8abSMaxime Ripard IRQ_PER_BANK * pctl->desc->irq_banks, 831aebdc8abSMaxime Ripard sizeof(*pctl->irq_array), 832aebdc8abSMaxime Ripard GFP_KERNEL); 833aebdc8abSMaxime Ripard if (!pctl->irq_array) 834aebdc8abSMaxime Ripard return -ENOMEM; 835aebdc8abSMaxime Ripard 8360e37f88dSMaxime Ripard ret = sunxi_pinctrl_build_state(pdev); 8370e37f88dSMaxime Ripard if (ret) { 8380e37f88dSMaxime Ripard dev_err(&pdev->dev, "dt probe failed: %d\n", ret); 8390e37f88dSMaxime Ripard return ret; 8400e37f88dSMaxime Ripard } 8410e37f88dSMaxime Ripard 8420e37f88dSMaxime Ripard pins = devm_kzalloc(&pdev->dev, 8430e37f88dSMaxime Ripard pctl->desc->npins * sizeof(*pins), 8440e37f88dSMaxime Ripard GFP_KERNEL); 8450e37f88dSMaxime Ripard if (!pins) 8460e37f88dSMaxime Ripard return -ENOMEM; 8470e37f88dSMaxime Ripard 8480e37f88dSMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) 8490e37f88dSMaxime Ripard pins[i] = pctl->desc->pins[i].pin; 8500e37f88dSMaxime Ripard 851ba6764d5SMaxime Ripard pctrl_desc = devm_kzalloc(&pdev->dev, 852ba6764d5SMaxime Ripard sizeof(*pctrl_desc), 853ba6764d5SMaxime Ripard GFP_KERNEL); 854ba6764d5SMaxime Ripard if (!pctrl_desc) 855ba6764d5SMaxime Ripard return -ENOMEM; 856ba6764d5SMaxime Ripard 857ba6764d5SMaxime Ripard pctrl_desc->name = dev_name(&pdev->dev); 858ba6764d5SMaxime Ripard pctrl_desc->owner = THIS_MODULE; 859ba6764d5SMaxime Ripard pctrl_desc->pins = pins; 860ba6764d5SMaxime Ripard pctrl_desc->npins = pctl->desc->npins; 861ba6764d5SMaxime Ripard pctrl_desc->confops = &sunxi_pconf_ops; 862ba6764d5SMaxime Ripard pctrl_desc->pctlops = &sunxi_pctrl_ops; 863ba6764d5SMaxime Ripard pctrl_desc->pmxops = &sunxi_pmx_ops; 864ba6764d5SMaxime Ripard 865ba6764d5SMaxime Ripard pctl->pctl_dev = pinctrl_register(pctrl_desc, 8660e37f88dSMaxime Ripard &pdev->dev, pctl); 8670e37f88dSMaxime Ripard if (!pctl->pctl_dev) { 8680e37f88dSMaxime Ripard dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); 8690e37f88dSMaxime Ripard return -EINVAL; 8700e37f88dSMaxime Ripard } 8710e37f88dSMaxime Ripard 87208e9e614SMaxime Ripard pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL); 87308e9e614SMaxime Ripard if (!pctl->chip) { 87408e9e614SMaxime Ripard ret = -ENOMEM; 87508e9e614SMaxime Ripard goto pinctrl_error; 87608e9e614SMaxime Ripard } 87708e9e614SMaxime Ripard 87808e9e614SMaxime Ripard last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number; 879d83c82ceSBoris BREZILLON pctl->chip->owner = THIS_MODULE; 880d83c82ceSBoris BREZILLON pctl->chip->request = sunxi_pinctrl_gpio_request, 881d83c82ceSBoris BREZILLON pctl->chip->free = sunxi_pinctrl_gpio_free, 882d83c82ceSBoris BREZILLON pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input, 883d83c82ceSBoris BREZILLON pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output, 884d83c82ceSBoris BREZILLON pctl->chip->get = sunxi_pinctrl_gpio_get, 885d83c82ceSBoris BREZILLON pctl->chip->set = sunxi_pinctrl_gpio_set, 886d83c82ceSBoris BREZILLON pctl->chip->of_xlate = sunxi_pinctrl_gpio_of_xlate, 887d83c82ceSBoris BREZILLON pctl->chip->to_irq = sunxi_pinctrl_gpio_to_irq, 888d83c82ceSBoris BREZILLON pctl->chip->of_gpio_n_cells = 3, 889d83c82ceSBoris BREZILLON pctl->chip->can_sleep = false, 890d83c82ceSBoris BREZILLON pctl->chip->ngpio = round_up(last_pin, PINS_PER_BANK) - 891d83c82ceSBoris BREZILLON pctl->desc->pin_base; 89208e9e614SMaxime Ripard pctl->chip->label = dev_name(&pdev->dev); 89308e9e614SMaxime Ripard pctl->chip->dev = &pdev->dev; 894d83c82ceSBoris BREZILLON pctl->chip->base = pctl->desc->pin_base; 89508e9e614SMaxime Ripard 89608e9e614SMaxime Ripard ret = gpiochip_add(pctl->chip); 89708e9e614SMaxime Ripard if (ret) 89808e9e614SMaxime Ripard goto pinctrl_error; 89908e9e614SMaxime Ripard 90008e9e614SMaxime Ripard for (i = 0; i < pctl->desc->npins; i++) { 90108e9e614SMaxime Ripard const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 90208e9e614SMaxime Ripard 90308e9e614SMaxime Ripard ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev), 90408e9e614SMaxime Ripard pin->pin.number, 90508e9e614SMaxime Ripard pin->pin.number, 1); 90608e9e614SMaxime Ripard if (ret) 90708e9e614SMaxime Ripard goto gpiochip_error; 90808e9e614SMaxime Ripard } 90908e9e614SMaxime Ripard 910950707c0SEmilio López clk = devm_clk_get(&pdev->dev, NULL); 911d72f88a4SWei Yongjun if (IS_ERR(clk)) { 912d72f88a4SWei Yongjun ret = PTR_ERR(clk); 913950707c0SEmilio López goto gpiochip_error; 914d72f88a4SWei Yongjun } 915950707c0SEmilio López 9166415093fSBoris BREZILLON ret = clk_prepare_enable(clk); 9176415093fSBoris BREZILLON if (ret) 9186415093fSBoris BREZILLON goto gpiochip_error; 919950707c0SEmilio López 920aebdc8abSMaxime Ripard pctl->irq = devm_kcalloc(&pdev->dev, 921aebdc8abSMaxime Ripard pctl->desc->irq_banks, 922aebdc8abSMaxime Ripard sizeof(*pctl->irq), 923aebdc8abSMaxime Ripard GFP_KERNEL); 92460242db1SMaxime Ripard if (!pctl->irq) { 925aebdc8abSMaxime Ripard ret = -ENOMEM; 926dc969106SMaxime Ripard goto clk_error; 92760242db1SMaxime Ripard } 92860242db1SMaxime Ripard 929aebdc8abSMaxime Ripard for (i = 0; i < pctl->desc->irq_banks; i++) { 930aebdc8abSMaxime Ripard pctl->irq[i] = platform_get_irq(pdev, i); 931aebdc8abSMaxime Ripard if (pctl->irq[i] < 0) { 932aebdc8abSMaxime Ripard ret = pctl->irq[i]; 933aebdc8abSMaxime Ripard goto clk_error; 934aebdc8abSMaxime Ripard } 935aebdc8abSMaxime Ripard } 936aebdc8abSMaxime Ripard 937aebdc8abSMaxime Ripard pctl->domain = irq_domain_add_linear(node, 938aebdc8abSMaxime Ripard pctl->desc->irq_banks * IRQ_PER_BANK, 939aebdc8abSMaxime Ripard &irq_domain_simple_ops, 940aebdc8abSMaxime Ripard NULL); 94160242db1SMaxime Ripard if (!pctl->domain) { 94260242db1SMaxime Ripard dev_err(&pdev->dev, "Couldn't register IRQ domain\n"); 94360242db1SMaxime Ripard ret = -ENOMEM; 944dc969106SMaxime Ripard goto clk_error; 94560242db1SMaxime Ripard } 94660242db1SMaxime Ripard 947aebdc8abSMaxime Ripard for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) { 94860242db1SMaxime Ripard int irqno = irq_create_mapping(pctl->domain, i); 94960242db1SMaxime Ripard 950*f4c51c10SHans de Goede irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip, 951*f4c51c10SHans de Goede handle_edge_irq); 95260242db1SMaxime Ripard irq_set_chip_data(irqno, pctl); 95360242db1SMaxime Ripard }; 95460242db1SMaxime Ripard 955aebdc8abSMaxime Ripard for (i = 0; i < pctl->desc->irq_banks; i++) { 956*f4c51c10SHans de Goede /* Mask and clear all IRQs before registering a handler */ 957*f4c51c10SHans de Goede writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i)); 958*f4c51c10SHans de Goede writel(0xffffffff, 959*f4c51c10SHans de Goede pctl->membase + sunxi_irq_status_reg_from_bank(i)); 960*f4c51c10SHans de Goede 961aebdc8abSMaxime Ripard irq_set_chained_handler(pctl->irq[i], 962aebdc8abSMaxime Ripard sunxi_pinctrl_irq_handler); 963aebdc8abSMaxime Ripard irq_set_handler_data(pctl->irq[i], pctl); 964aebdc8abSMaxime Ripard } 96560242db1SMaxime Ripard 96608e9e614SMaxime Ripard dev_info(&pdev->dev, "initialized sunXi PIO driver\n"); 9670e37f88dSMaxime Ripard 9680e37f88dSMaxime Ripard return 0; 96908e9e614SMaxime Ripard 970e2bddc6aSBoris BREZILLON clk_error: 971e2bddc6aSBoris BREZILLON clk_disable_unprepare(clk); 97208e9e614SMaxime Ripard gpiochip_error: 97397fc4637SAxel Lin if (gpiochip_remove(pctl->chip)) 97497fc4637SAxel Lin dev_err(&pdev->dev, "failed to remove gpio chip\n"); 97508e9e614SMaxime Ripard pinctrl_error: 97608e9e614SMaxime Ripard pinctrl_unregister(pctl->pctl_dev); 97708e9e614SMaxime Ripard return ret; 9780e37f88dSMaxime Ripard } 979