12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2170c6152STony Prisk /* 3170c6152STony Prisk * Pinctrl driver for the Wondermedia SoC's 4170c6152STony Prisk * 5170c6152STony Prisk * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> 6170c6152STony Prisk */ 7170c6152STony Prisk 8170c6152STony Prisk #include <linux/err.h> 95c809c63SLinus Walleij #include <linux/gpio/driver.h> 10170c6152STony Prisk #include <linux/interrupt.h> 11170c6152STony Prisk #include <linux/io.h> 12170c6152STony Prisk #include <linux/irq.h> 13170c6152STony Prisk #include <linux/of.h> 14170c6152STony Prisk #include <linux/of_irq.h> 15170c6152STony Prisk #include <linux/pinctrl/consumer.h> 16170c6152STony Prisk #include <linux/pinctrl/machine.h> 17170c6152STony Prisk #include <linux/pinctrl/pinconf.h> 18170c6152STony Prisk #include <linux/pinctrl/pinconf-generic.h> 19170c6152STony Prisk #include <linux/pinctrl/pinctrl.h> 20170c6152STony Prisk #include <linux/pinctrl/pinmux.h> 21170c6152STony Prisk #include <linux/platform_device.h> 22170c6152STony Prisk #include <linux/slab.h> 23170c6152STony Prisk 24170c6152STony Prisk #include "pinctrl-wmt.h" 25170c6152STony Prisk 26170c6152STony Prisk static inline void wmt_setbits(struct wmt_pinctrl_data *data, u32 reg, 27170c6152STony Prisk u32 mask) 28170c6152STony Prisk { 29170c6152STony Prisk u32 val; 30170c6152STony Prisk 31170c6152STony Prisk val = readl_relaxed(data->base + reg); 32170c6152STony Prisk val |= mask; 33170c6152STony Prisk writel_relaxed(val, data->base + reg); 34170c6152STony Prisk } 35170c6152STony Prisk 36170c6152STony Prisk static inline void wmt_clearbits(struct wmt_pinctrl_data *data, u32 reg, 37170c6152STony Prisk u32 mask) 38170c6152STony Prisk { 39170c6152STony Prisk u32 val; 40170c6152STony Prisk 41170c6152STony Prisk val = readl_relaxed(data->base + reg); 42170c6152STony Prisk val &= ~mask; 43170c6152STony Prisk writel_relaxed(val, data->base + reg); 44170c6152STony Prisk } 45170c6152STony Prisk 46170c6152STony Prisk enum wmt_func_sel { 47170c6152STony Prisk WMT_FSEL_GPIO_IN = 0, 48170c6152STony Prisk WMT_FSEL_GPIO_OUT = 1, 49170c6152STony Prisk WMT_FSEL_ALT = 2, 50170c6152STony Prisk WMT_FSEL_COUNT = 3, 51170c6152STony Prisk }; 52170c6152STony Prisk 53170c6152STony Prisk static const char * const wmt_functions[WMT_FSEL_COUNT] = { 54170c6152STony Prisk [WMT_FSEL_GPIO_IN] = "gpio_in", 55170c6152STony Prisk [WMT_FSEL_GPIO_OUT] = "gpio_out", 56170c6152STony Prisk [WMT_FSEL_ALT] = "alt", 57170c6152STony Prisk }; 58170c6152STony Prisk 59170c6152STony Prisk static int wmt_pmx_get_functions_count(struct pinctrl_dev *pctldev) 60170c6152STony Prisk { 61170c6152STony Prisk return WMT_FSEL_COUNT; 62170c6152STony Prisk } 63170c6152STony Prisk 64170c6152STony Prisk static const char *wmt_pmx_get_function_name(struct pinctrl_dev *pctldev, 65170c6152STony Prisk unsigned selector) 66170c6152STony Prisk { 67170c6152STony Prisk return wmt_functions[selector]; 68170c6152STony Prisk } 69170c6152STony Prisk 70170c6152STony Prisk static int wmt_pmx_get_function_groups(struct pinctrl_dev *pctldev, 71170c6152STony Prisk unsigned selector, 72170c6152STony Prisk const char * const **groups, 73170c6152STony Prisk unsigned * const num_groups) 74170c6152STony Prisk { 75170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 76170c6152STony Prisk 77170c6152STony Prisk /* every pin does every function */ 78170c6152STony Prisk *groups = data->groups; 79170c6152STony Prisk *num_groups = data->ngroups; 80170c6152STony Prisk 81170c6152STony Prisk return 0; 82170c6152STony Prisk } 83170c6152STony Prisk 84170c6152STony Prisk static int wmt_set_pinmux(struct wmt_pinctrl_data *data, unsigned func, 85170c6152STony Prisk unsigned pin) 86170c6152STony Prisk { 87170c6152STony Prisk u32 bank = WMT_BANK_FROM_PIN(pin); 88170c6152STony Prisk u32 bit = WMT_BIT_FROM_PIN(pin); 89170c6152STony Prisk u32 reg_en = data->banks[bank].reg_en; 90170c6152STony Prisk u32 reg_dir = data->banks[bank].reg_dir; 91170c6152STony Prisk 92170c6152STony Prisk if (reg_dir == NO_REG) { 93170c6152STony Prisk dev_err(data->dev, "pin:%d no direction register defined\n", 94170c6152STony Prisk pin); 95170c6152STony Prisk return -EINVAL; 96170c6152STony Prisk } 97170c6152STony Prisk 98170c6152STony Prisk /* 99170c6152STony Prisk * If reg_en == NO_REG, we assume it is a dedicated GPIO and cannot be 100170c6152STony Prisk * disabled (as on VT8500) and that no alternate function is available. 101170c6152STony Prisk */ 102170c6152STony Prisk switch (func) { 103170c6152STony Prisk case WMT_FSEL_GPIO_IN: 104170c6152STony Prisk if (reg_en != NO_REG) 105170c6152STony Prisk wmt_setbits(data, reg_en, BIT(bit)); 106170c6152STony Prisk wmt_clearbits(data, reg_dir, BIT(bit)); 107170c6152STony Prisk break; 108170c6152STony Prisk case WMT_FSEL_GPIO_OUT: 109170c6152STony Prisk if (reg_en != NO_REG) 110170c6152STony Prisk wmt_setbits(data, reg_en, BIT(bit)); 111170c6152STony Prisk wmt_setbits(data, reg_dir, BIT(bit)); 112170c6152STony Prisk break; 113170c6152STony Prisk case WMT_FSEL_ALT: 114170c6152STony Prisk if (reg_en == NO_REG) { 115170c6152STony Prisk dev_err(data->dev, "pin:%d no alt function available\n", 116170c6152STony Prisk pin); 117170c6152STony Prisk return -EINVAL; 118170c6152STony Prisk } 119170c6152STony Prisk wmt_clearbits(data, reg_en, BIT(bit)); 120170c6152STony Prisk } 121170c6152STony Prisk 122170c6152STony Prisk return 0; 123170c6152STony Prisk } 124170c6152STony Prisk 12503e9f0caSLinus Walleij static int wmt_pmx_set_mux(struct pinctrl_dev *pctldev, 126170c6152STony Prisk unsigned func_selector, 127170c6152STony Prisk unsigned group_selector) 128170c6152STony Prisk { 129170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 130170c6152STony Prisk u32 pinnum = data->pins[group_selector].number; 131170c6152STony Prisk 132170c6152STony Prisk return wmt_set_pinmux(data, func_selector, pinnum); 133170c6152STony Prisk } 134170c6152STony Prisk 135170c6152STony Prisk static void wmt_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, 136170c6152STony Prisk struct pinctrl_gpio_range *range, 137170c6152STony Prisk unsigned offset) 138170c6152STony Prisk { 139170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 140170c6152STony Prisk 141170c6152STony Prisk /* disable by setting GPIO_IN */ 142170c6152STony Prisk wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, offset); 143170c6152STony Prisk } 144170c6152STony Prisk 145170c6152STony Prisk static int wmt_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, 146170c6152STony Prisk struct pinctrl_gpio_range *range, 147170c6152STony Prisk unsigned offset, 148170c6152STony Prisk bool input) 149170c6152STony Prisk { 150170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 151170c6152STony Prisk 152170c6152STony Prisk wmt_set_pinmux(data, (input ? WMT_FSEL_GPIO_IN : WMT_FSEL_GPIO_OUT), 153170c6152STony Prisk offset); 154170c6152STony Prisk 155170c6152STony Prisk return 0; 156170c6152STony Prisk } 157170c6152STony Prisk 158a228d74fSJulia Lawall static const struct pinmux_ops wmt_pinmux_ops = { 159170c6152STony Prisk .get_functions_count = wmt_pmx_get_functions_count, 160170c6152STony Prisk .get_function_name = wmt_pmx_get_function_name, 161170c6152STony Prisk .get_function_groups = wmt_pmx_get_function_groups, 16203e9f0caSLinus Walleij .set_mux = wmt_pmx_set_mux, 163170c6152STony Prisk .gpio_disable_free = wmt_pmx_gpio_disable_free, 164170c6152STony Prisk .gpio_set_direction = wmt_pmx_gpio_set_direction, 165170c6152STony Prisk }; 166170c6152STony Prisk 167170c6152STony Prisk static int wmt_get_groups_count(struct pinctrl_dev *pctldev) 168170c6152STony Prisk { 169170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 170170c6152STony Prisk 171170c6152STony Prisk return data->ngroups; 172170c6152STony Prisk } 173170c6152STony Prisk 174170c6152STony Prisk static const char *wmt_get_group_name(struct pinctrl_dev *pctldev, 175170c6152STony Prisk unsigned selector) 176170c6152STony Prisk { 177170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 178170c6152STony Prisk 179170c6152STony Prisk return data->groups[selector]; 180170c6152STony Prisk } 181170c6152STony Prisk 182170c6152STony Prisk static int wmt_get_group_pins(struct pinctrl_dev *pctldev, 183170c6152STony Prisk unsigned selector, 184170c6152STony Prisk const unsigned **pins, 185170c6152STony Prisk unsigned *num_pins) 186170c6152STony Prisk { 187170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 188170c6152STony Prisk 189170c6152STony Prisk *pins = &data->pins[selector].number; 190170c6152STony Prisk *num_pins = 1; 191170c6152STony Prisk 192170c6152STony Prisk return 0; 193170c6152STony Prisk } 194170c6152STony Prisk 195170c6152STony Prisk static int wmt_pctl_find_group_by_pin(struct wmt_pinctrl_data *data, u32 pin) 196170c6152STony Prisk { 197170c6152STony Prisk int i; 198170c6152STony Prisk 199170c6152STony Prisk for (i = 0; i < data->npins; i++) { 200170c6152STony Prisk if (data->pins[i].number == pin) 201170c6152STony Prisk return i; 202170c6152STony Prisk } 203170c6152STony Prisk 204170c6152STony Prisk return -EINVAL; 205170c6152STony Prisk } 206170c6152STony Prisk 207170c6152STony Prisk static int wmt_pctl_dt_node_to_map_func(struct wmt_pinctrl_data *data, 208170c6152STony Prisk struct device_node *np, 209170c6152STony Prisk u32 pin, u32 fnum, 210170c6152STony Prisk struct pinctrl_map **maps) 211170c6152STony Prisk { 212170c6152STony Prisk int group; 213170c6152STony Prisk struct pinctrl_map *map = *maps; 214170c6152STony Prisk 215170c6152STony Prisk if (fnum >= ARRAY_SIZE(wmt_functions)) { 216170c6152STony Prisk dev_err(data->dev, "invalid wm,function %d\n", fnum); 217170c6152STony Prisk return -EINVAL; 218170c6152STony Prisk } 219170c6152STony Prisk 220170c6152STony Prisk group = wmt_pctl_find_group_by_pin(data, pin); 221170c6152STony Prisk if (group < 0) { 222170c6152STony Prisk dev_err(data->dev, "unable to match pin %d to group\n", pin); 223170c6152STony Prisk return group; 224170c6152STony Prisk } 225170c6152STony Prisk 226170c6152STony Prisk map->type = PIN_MAP_TYPE_MUX_GROUP; 227170c6152STony Prisk map->data.mux.group = data->groups[group]; 228170c6152STony Prisk map->data.mux.function = wmt_functions[fnum]; 229170c6152STony Prisk (*maps)++; 230170c6152STony Prisk 231170c6152STony Prisk return 0; 232170c6152STony Prisk } 233170c6152STony Prisk 234170c6152STony Prisk static int wmt_pctl_dt_node_to_map_pull(struct wmt_pinctrl_data *data, 235170c6152STony Prisk struct device_node *np, 236170c6152STony Prisk u32 pin, u32 pull, 237170c6152STony Prisk struct pinctrl_map **maps) 238170c6152STony Prisk { 239170c6152STony Prisk int group; 240170c6152STony Prisk unsigned long *configs; 241170c6152STony Prisk struct pinctrl_map *map = *maps; 242170c6152STony Prisk 243170c6152STony Prisk if (pull > 2) { 244170c6152STony Prisk dev_err(data->dev, "invalid wm,pull %d\n", pull); 245170c6152STony Prisk return -EINVAL; 246170c6152STony Prisk } 247170c6152STony Prisk 248170c6152STony Prisk group = wmt_pctl_find_group_by_pin(data, pin); 249170c6152STony Prisk if (group < 0) { 250170c6152STony Prisk dev_err(data->dev, "unable to match pin %d to group\n", pin); 251170c6152STony Prisk return group; 252170c6152STony Prisk } 253170c6152STony Prisk 254170c6152STony Prisk configs = kzalloc(sizeof(*configs), GFP_KERNEL); 255170c6152STony Prisk if (!configs) 256170c6152STony Prisk return -ENOMEM; 257170c6152STony Prisk 258f17248edSTony Prisk switch (pull) { 259f17248edSTony Prisk case 0: 260f17248edSTony Prisk configs[0] = PIN_CONFIG_BIAS_DISABLE; 261f17248edSTony Prisk break; 262f17248edSTony Prisk case 1: 263f17248edSTony Prisk configs[0] = PIN_CONFIG_BIAS_PULL_DOWN; 264f17248edSTony Prisk break; 265f17248edSTony Prisk case 2: 266f17248edSTony Prisk configs[0] = PIN_CONFIG_BIAS_PULL_UP; 267f17248edSTony Prisk break; 268f17248edSTony Prisk default: 269f17248edSTony Prisk configs[0] = PIN_CONFIG_BIAS_DISABLE; 270f17248edSTony Prisk dev_err(data->dev, "invalid pull state %d - disabling\n", pull); 271f17248edSTony Prisk } 272170c6152STony Prisk 273170c6152STony Prisk map->type = PIN_MAP_TYPE_CONFIGS_PIN; 274170c6152STony Prisk map->data.configs.group_or_pin = data->groups[group]; 275170c6152STony Prisk map->data.configs.configs = configs; 276170c6152STony Prisk map->data.configs.num_configs = 1; 277170c6152STony Prisk (*maps)++; 278170c6152STony Prisk 279170c6152STony Prisk return 0; 280170c6152STony Prisk } 281170c6152STony Prisk 282170c6152STony Prisk static void wmt_pctl_dt_free_map(struct pinctrl_dev *pctldev, 283170c6152STony Prisk struct pinctrl_map *maps, 284170c6152STony Prisk unsigned num_maps) 285170c6152STony Prisk { 286170c6152STony Prisk int i; 287170c6152STony Prisk 288170c6152STony Prisk for (i = 0; i < num_maps; i++) 289170c6152STony Prisk if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) 290170c6152STony Prisk kfree(maps[i].data.configs.configs); 291170c6152STony Prisk 292170c6152STony Prisk kfree(maps); 293170c6152STony Prisk } 294170c6152STony Prisk 295170c6152STony Prisk static int wmt_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, 296170c6152STony Prisk struct device_node *np, 297170c6152STony Prisk struct pinctrl_map **map, 298170c6152STony Prisk unsigned *num_maps) 299170c6152STony Prisk { 300170c6152STony Prisk struct pinctrl_map *maps, *cur_map; 301170c6152STony Prisk struct property *pins, *funcs, *pulls; 302170c6152STony Prisk u32 pin, func, pull; 303170c6152STony Prisk int num_pins, num_funcs, num_pulls, maps_per_pin; 304170c6152STony Prisk int i, err; 305170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 306170c6152STony Prisk 307170c6152STony Prisk pins = of_find_property(np, "wm,pins", NULL); 308170c6152STony Prisk if (!pins) { 309170c6152STony Prisk dev_err(data->dev, "missing wmt,pins property\n"); 310170c6152STony Prisk return -EINVAL; 311170c6152STony Prisk } 312170c6152STony Prisk 313170c6152STony Prisk funcs = of_find_property(np, "wm,function", NULL); 314170c6152STony Prisk pulls = of_find_property(np, "wm,pull", NULL); 315170c6152STony Prisk 316170c6152STony Prisk if (!funcs && !pulls) { 317170c6152STony Prisk dev_err(data->dev, "neither wm,function nor wm,pull specified\n"); 318170c6152STony Prisk return -EINVAL; 319170c6152STony Prisk } 320170c6152STony Prisk 321170c6152STony Prisk /* 322170c6152STony Prisk * The following lines calculate how many values are defined for each 323170c6152STony Prisk * of the properties. 324170c6152STony Prisk */ 325170c6152STony Prisk num_pins = pins->length / sizeof(u32); 326170c6152STony Prisk num_funcs = funcs ? (funcs->length / sizeof(u32)) : 0; 327170c6152STony Prisk num_pulls = pulls ? (pulls->length / sizeof(u32)) : 0; 328170c6152STony Prisk 329170c6152STony Prisk if (num_funcs > 1 && num_funcs != num_pins) { 330170c6152STony Prisk dev_err(data->dev, "wm,function must have 1 or %d entries\n", 331170c6152STony Prisk num_pins); 332170c6152STony Prisk return -EINVAL; 333170c6152STony Prisk } 334170c6152STony Prisk 335170c6152STony Prisk if (num_pulls > 1 && num_pulls != num_pins) { 336170c6152STony Prisk dev_err(data->dev, "wm,pull must have 1 or %d entries\n", 337170c6152STony Prisk num_pins); 338170c6152STony Prisk return -EINVAL; 339170c6152STony Prisk } 340170c6152STony Prisk 341170c6152STony Prisk maps_per_pin = 0; 342170c6152STony Prisk if (num_funcs) 343170c6152STony Prisk maps_per_pin++; 344170c6152STony Prisk if (num_pulls) 345170c6152STony Prisk maps_per_pin++; 346170c6152STony Prisk 3476396bb22SKees Cook cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps), 348170c6152STony Prisk GFP_KERNEL); 349170c6152STony Prisk if (!maps) 350170c6152STony Prisk return -ENOMEM; 351170c6152STony Prisk 352170c6152STony Prisk for (i = 0; i < num_pins; i++) { 353170c6152STony Prisk err = of_property_read_u32_index(np, "wm,pins", i, &pin); 354170c6152STony Prisk if (err) 355170c6152STony Prisk goto fail; 356170c6152STony Prisk 357170c6152STony Prisk if (pin >= (data->nbanks * 32)) { 358170c6152STony Prisk dev_err(data->dev, "invalid wm,pins value\n"); 359170c6152STony Prisk err = -EINVAL; 360170c6152STony Prisk goto fail; 361170c6152STony Prisk } 362170c6152STony Prisk 363170c6152STony Prisk if (num_funcs) { 364170c6152STony Prisk err = of_property_read_u32_index(np, "wm,function", 365170c6152STony Prisk (num_funcs > 1 ? i : 0), &func); 366170c6152STony Prisk if (err) 367170c6152STony Prisk goto fail; 368170c6152STony Prisk 369170c6152STony Prisk err = wmt_pctl_dt_node_to_map_func(data, np, pin, func, 370170c6152STony Prisk &cur_map); 371170c6152STony Prisk if (err) 372170c6152STony Prisk goto fail; 373170c6152STony Prisk } 374170c6152STony Prisk 375170c6152STony Prisk if (num_pulls) { 376170c6152STony Prisk err = of_property_read_u32_index(np, "wm,pull", 377170c6152STony Prisk (num_pulls > 1 ? i : 0), &pull); 378170c6152STony Prisk if (err) 379170c6152STony Prisk goto fail; 380170c6152STony Prisk 381170c6152STony Prisk err = wmt_pctl_dt_node_to_map_pull(data, np, pin, pull, 382170c6152STony Prisk &cur_map); 383170c6152STony Prisk if (err) 384170c6152STony Prisk goto fail; 385170c6152STony Prisk } 386170c6152STony Prisk } 387170c6152STony Prisk *map = maps; 388170c6152STony Prisk *num_maps = num_pins * maps_per_pin; 389170c6152STony Prisk return 0; 390170c6152STony Prisk 391170c6152STony Prisk /* 392170c6152STony Prisk * The fail path removes any maps that have been allocated. The fail path is 393170c6152STony Prisk * only called from code after maps has been kzalloc'd. It is also safe to 394170c6152STony Prisk * pass 'num_pins * maps_per_pin' as the map count even though we probably 395170c6152STony Prisk * failed before all the mappings were read as all maps are allocated at once, 396170c6152STony Prisk * and configs are only allocated for .type = PIN_MAP_TYPE_CONFIGS_PIN - there 397170c6152STony Prisk * is no failpath where a config can be allocated without .type being set. 398170c6152STony Prisk */ 399170c6152STony Prisk fail: 400170c6152STony Prisk wmt_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin); 401170c6152STony Prisk return err; 402170c6152STony Prisk } 403170c6152STony Prisk 404a228d74fSJulia Lawall static const struct pinctrl_ops wmt_pctl_ops = { 405170c6152STony Prisk .get_groups_count = wmt_get_groups_count, 406170c6152STony Prisk .get_group_name = wmt_get_group_name, 407170c6152STony Prisk .get_group_pins = wmt_get_group_pins, 408170c6152STony Prisk .dt_node_to_map = wmt_pctl_dt_node_to_map, 409170c6152STony Prisk .dt_free_map = wmt_pctl_dt_free_map, 410170c6152STony Prisk }; 411170c6152STony Prisk 412170c6152STony Prisk static int wmt_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, 413170c6152STony Prisk unsigned long *config) 414170c6152STony Prisk { 415170c6152STony Prisk return -ENOTSUPP; 416170c6152STony Prisk } 417170c6152STony Prisk 418170c6152STony Prisk static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, 41903b054e9SSherman Yin unsigned long *configs, unsigned num_configs) 420170c6152STony Prisk { 421170c6152STony Prisk struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); 42203b054e9SSherman Yin enum pin_config_param param; 42358957d2eSMika Westerberg u32 arg; 424170c6152STony Prisk u32 bank = WMT_BANK_FROM_PIN(pin); 425170c6152STony Prisk u32 bit = WMT_BIT_FROM_PIN(pin); 426170c6152STony Prisk u32 reg_pull_en = data->banks[bank].reg_pull_en; 427170c6152STony Prisk u32 reg_pull_cfg = data->banks[bank].reg_pull_cfg; 42803b054e9SSherman Yin int i; 429170c6152STony Prisk 430170c6152STony Prisk if ((reg_pull_en == NO_REG) || (reg_pull_cfg == NO_REG)) { 431170c6152STony Prisk dev_err(data->dev, "bias functions not supported on pin %d\n", 432170c6152STony Prisk pin); 433170c6152STony Prisk return -EINVAL; 434170c6152STony Prisk } 435170c6152STony Prisk 43603b054e9SSherman Yin for (i = 0; i < num_configs; i++) { 43703b054e9SSherman Yin param = pinconf_to_config_param(configs[i]); 43803b054e9SSherman Yin arg = pinconf_to_config_argument(configs[i]); 43903b054e9SSherman Yin 440170c6152STony Prisk if ((param == PIN_CONFIG_BIAS_PULL_DOWN) || 441170c6152STony Prisk (param == PIN_CONFIG_BIAS_PULL_UP)) { 442170c6152STony Prisk if (arg == 0) 443170c6152STony Prisk param = PIN_CONFIG_BIAS_DISABLE; 444170c6152STony Prisk } 445170c6152STony Prisk 446170c6152STony Prisk switch (param) { 447170c6152STony Prisk case PIN_CONFIG_BIAS_DISABLE: 448170c6152STony Prisk wmt_clearbits(data, reg_pull_en, BIT(bit)); 449170c6152STony Prisk break; 450170c6152STony Prisk case PIN_CONFIG_BIAS_PULL_DOWN: 451170c6152STony Prisk wmt_clearbits(data, reg_pull_cfg, BIT(bit)); 452170c6152STony Prisk wmt_setbits(data, reg_pull_en, BIT(bit)); 453170c6152STony Prisk break; 454170c6152STony Prisk case PIN_CONFIG_BIAS_PULL_UP: 455170c6152STony Prisk wmt_setbits(data, reg_pull_cfg, BIT(bit)); 456170c6152STony Prisk wmt_setbits(data, reg_pull_en, BIT(bit)); 457170c6152STony Prisk break; 458170c6152STony Prisk default: 459170c6152STony Prisk dev_err(data->dev, "unknown pinconf param\n"); 460170c6152STony Prisk return -EINVAL; 461170c6152STony Prisk } 46203b054e9SSherman Yin } /* for each config */ 463170c6152STony Prisk 464170c6152STony Prisk return 0; 465170c6152STony Prisk } 466170c6152STony Prisk 467a228d74fSJulia Lawall static const struct pinconf_ops wmt_pinconf_ops = { 468170c6152STony Prisk .pin_config_get = wmt_pinconf_get, 469170c6152STony Prisk .pin_config_set = wmt_pinconf_set, 470170c6152STony Prisk }; 471170c6152STony Prisk 472170c6152STony Prisk static struct pinctrl_desc wmt_desc = { 473170c6152STony Prisk .owner = THIS_MODULE, 474170c6152STony Prisk .name = "pinctrl-wmt", 475170c6152STony Prisk .pctlops = &wmt_pctl_ops, 476170c6152STony Prisk .pmxops = &wmt_pinmux_ops, 477170c6152STony Prisk .confops = &wmt_pinconf_ops, 478170c6152STony Prisk }; 479170c6152STony Prisk 480170c6152STony Prisk static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset) 481170c6152STony Prisk { 4825c809c63SLinus Walleij struct wmt_pinctrl_data *data = gpiochip_get_data(chip); 483170c6152STony Prisk u32 bank = WMT_BANK_FROM_PIN(offset); 484170c6152STony Prisk u32 bit = WMT_BIT_FROM_PIN(offset); 485170c6152STony Prisk u32 reg_dir = data->banks[bank].reg_dir; 486170c6152STony Prisk u32 val; 487170c6152STony Prisk 488170c6152STony Prisk val = readl_relaxed(data->base + reg_dir); 4893c827873SMatti Vaittinen if (val & BIT(bit)) 4903c827873SMatti Vaittinen return GPIO_LINE_DIRECTION_OUT; 4913c827873SMatti Vaittinen 4923c827873SMatti Vaittinen return GPIO_LINE_DIRECTION_IN; 493170c6152STony Prisk } 494170c6152STony Prisk 495170c6152STony Prisk static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset) 496170c6152STony Prisk { 4975c809c63SLinus Walleij struct wmt_pinctrl_data *data = gpiochip_get_data(chip); 498170c6152STony Prisk u32 bank = WMT_BANK_FROM_PIN(offset); 499170c6152STony Prisk u32 bit = WMT_BIT_FROM_PIN(offset); 500170c6152STony Prisk u32 reg_data_in = data->banks[bank].reg_data_in; 501170c6152STony Prisk 502170c6152STony Prisk if (reg_data_in == NO_REG) { 503170c6152STony Prisk dev_err(data->dev, "no data in register defined\n"); 504170c6152STony Prisk return -EINVAL; 505170c6152STony Prisk } 506170c6152STony Prisk 507170c6152STony Prisk return !!(readl_relaxed(data->base + reg_data_in) & BIT(bit)); 508170c6152STony Prisk } 509170c6152STony Prisk 510170c6152STony Prisk static void wmt_gpio_set_value(struct gpio_chip *chip, unsigned offset, 511170c6152STony Prisk int val) 512170c6152STony Prisk { 5135c809c63SLinus Walleij struct wmt_pinctrl_data *data = gpiochip_get_data(chip); 514170c6152STony Prisk u32 bank = WMT_BANK_FROM_PIN(offset); 515170c6152STony Prisk u32 bit = WMT_BIT_FROM_PIN(offset); 516170c6152STony Prisk u32 reg_data_out = data->banks[bank].reg_data_out; 517170c6152STony Prisk 518170c6152STony Prisk if (reg_data_out == NO_REG) { 519170c6152STony Prisk dev_err(data->dev, "no data out register defined\n"); 520170c6152STony Prisk return; 521170c6152STony Prisk } 522170c6152STony Prisk 523170c6152STony Prisk if (val) 524170c6152STony Prisk wmt_setbits(data, reg_data_out, BIT(bit)); 525170c6152STony Prisk else 526170c6152STony Prisk wmt_clearbits(data, reg_data_out, BIT(bit)); 527170c6152STony Prisk } 528170c6152STony Prisk 5297ea45643SAlexey Charkov static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 5307ea45643SAlexey Charkov { 5317ea45643SAlexey Charkov return pinctrl_gpio_direction_input(chip->base + offset); 5327ea45643SAlexey Charkov } 5337ea45643SAlexey Charkov 5347ea45643SAlexey Charkov static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 5357ea45643SAlexey Charkov int value) 5367ea45643SAlexey Charkov { 5377ea45643SAlexey Charkov wmt_gpio_set_value(chip, offset, value); 5387ea45643SAlexey Charkov return pinctrl_gpio_direction_output(chip->base + offset); 5397ea45643SAlexey Charkov } 5407ea45643SAlexey Charkov 5413d9c2563SGustavo A. R. Silva static const struct gpio_chip wmt_gpio_chip = { 542170c6152STony Prisk .label = "gpio-wmt", 543170c6152STony Prisk .owner = THIS_MODULE, 54498c85d58SJonas Gorski .request = gpiochip_generic_request, 54598c85d58SJonas Gorski .free = gpiochip_generic_free, 546170c6152STony Prisk .get_direction = wmt_gpio_get_direction, 547170c6152STony Prisk .direction_input = wmt_gpio_direction_input, 548170c6152STony Prisk .direction_output = wmt_gpio_direction_output, 549170c6152STony Prisk .get = wmt_gpio_get_value, 550170c6152STony Prisk .set = wmt_gpio_set_value, 5519fb1f39eSLinus Walleij .can_sleep = false, 552170c6152STony Prisk }; 553170c6152STony Prisk 554170c6152STony Prisk int wmt_pinctrl_probe(struct platform_device *pdev, 555170c6152STony Prisk struct wmt_pinctrl_data *data) 556170c6152STony Prisk { 557170c6152STony Prisk int err; 558170c6152STony Prisk 5594b024225SYueHaibing data->base = devm_platform_ioremap_resource(pdev, 0); 5602207a4e1SWei Yongjun if (IS_ERR(data->base)) 56176cda6ecSLaurent Navet return PTR_ERR(data->base); 562170c6152STony Prisk 563170c6152STony Prisk wmt_desc.pins = data->pins; 564170c6152STony Prisk wmt_desc.npins = data->npins; 565170c6152STony Prisk 566170c6152STony Prisk data->gpio_chip = wmt_gpio_chip; 56758383c78SLinus Walleij data->gpio_chip.parent = &pdev->dev; 568170c6152STony Prisk data->gpio_chip.of_node = pdev->dev.of_node; 569170c6152STony Prisk data->gpio_chip.ngpio = data->nbanks * 32; 570170c6152STony Prisk 571170c6152STony Prisk platform_set_drvdata(pdev, data); 572170c6152STony Prisk 573170c6152STony Prisk data->dev = &pdev->dev; 574170c6152STony Prisk 575f3abcb66SLaxman Dewangan data->pctl_dev = devm_pinctrl_register(&pdev->dev, &wmt_desc, data); 576323de9efSMasahiro Yamada if (IS_ERR(data->pctl_dev)) { 577170c6152STony Prisk dev_err(&pdev->dev, "Failed to register pinctrl\n"); 578323de9efSMasahiro Yamada return PTR_ERR(data->pctl_dev); 579170c6152STony Prisk } 580170c6152STony Prisk 5815c809c63SLinus Walleij err = gpiochip_add_data(&data->gpio_chip, data); 582170c6152STony Prisk if (err) { 583170c6152STony Prisk dev_err(&pdev->dev, "could not add GPIO chip\n"); 584f3abcb66SLaxman Dewangan return err; 585170c6152STony Prisk } 586170c6152STony Prisk 587170c6152STony Prisk err = gpiochip_add_pin_range(&data->gpio_chip, dev_name(data->dev), 588170c6152STony Prisk 0, 0, data->nbanks * 32); 589170c6152STony Prisk if (err) 590170c6152STony Prisk goto fail_range; 591170c6152STony Prisk 592170c6152STony Prisk dev_info(&pdev->dev, "Pin controller initialized\n"); 593170c6152STony Prisk 594170c6152STony Prisk return 0; 595170c6152STony Prisk 596170c6152STony Prisk fail_range: 597b4e7c55dSabdoulaye berthe gpiochip_remove(&data->gpio_chip); 598170c6152STony Prisk return err; 599170c6152STony Prisk } 600