1 /* 2 * Copyright (C) 2015-2016 Socionext Inc. 3 * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <linux/io.h> 11 #include <linux/err.h> 12 #include <linux/kernel.h> 13 #include <linux/sizes.h> 14 #include <dm/pinctrl.h> 15 16 #include "pinctrl-uniphier.h" 17 18 #define UNIPHIER_PINCTRL_PINMUX_BASE 0x1000 19 #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x1700 20 #define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00 21 #define UNIPHIER_PINCTRL_IECTRL 0x1d00 22 23 static const char *uniphier_pinctrl_dummy_name = "_dummy"; 24 25 static int uniphier_pinctrl_get_groups_count(struct udevice *dev) 26 { 27 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 28 29 return priv->socdata->groups_count; 30 } 31 32 static const char *uniphier_pinctrl_get_group_name(struct udevice *dev, 33 unsigned selector) 34 { 35 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 36 37 if (!priv->socdata->groups[selector].name) 38 return uniphier_pinctrl_dummy_name; 39 40 return priv->socdata->groups[selector].name; 41 } 42 43 static int uniphier_pinmux_get_functions_count(struct udevice *dev) 44 { 45 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 46 47 return priv->socdata->functions_count; 48 } 49 50 static const char *uniphier_pinmux_get_function_name(struct udevice *dev, 51 unsigned selector) 52 { 53 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 54 55 if (!priv->socdata->functions[selector]) 56 return uniphier_pinctrl_dummy_name; 57 58 return priv->socdata->functions[selector]; 59 } 60 61 static int uniphier_pinconf_input_enable_perpin(struct udevice *dev, 62 unsigned int pin, int enable) 63 { 64 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 65 unsigned reg; 66 u32 mask, tmp; 67 68 reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4; 69 mask = BIT(pin % 32); 70 71 tmp = readl(priv->base + reg); 72 if (enable) 73 tmp |= mask; 74 else 75 tmp &= ~mask; 76 writel(tmp, priv->base + reg); 77 78 return 0; 79 } 80 81 static int uniphier_pinconf_input_enable_legacy(struct udevice *dev, 82 unsigned int pin, int enable) 83 { 84 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 85 86 /* 87 * Multiple pins share one input enable, per-pin disabling is 88 * impossible. 89 */ 90 if (!enable) 91 return -EINVAL; 92 93 /* Set all bits instead of having a bunch of pin data */ 94 writel(U32_MAX, priv->base + UNIPHIER_PINCTRL_IECTRL); 95 96 return 0; 97 } 98 99 static int uniphier_pinconf_input_enable(struct udevice *dev, 100 unsigned int pin, int enable) 101 { 102 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 103 104 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) 105 return uniphier_pinconf_input_enable_perpin(dev, pin, enable); 106 else 107 return uniphier_pinconf_input_enable_legacy(dev, pin, enable); 108 } 109 110 #if CONFIG_IS_ENABLED(PINCONF) 111 112 static const struct pinconf_param uniphier_pinconf_params[] = { 113 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, 114 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, 115 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, 116 { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 }, 117 { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, 118 { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, 119 }; 120 121 static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin, 122 unsigned int param, unsigned int arg) 123 { 124 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 125 unsigned int enable = 1; 126 unsigned int reg; 127 u32 mask, tmp; 128 129 if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE)) 130 return -ENOTSUPP; 131 132 switch (param) { 133 case PIN_CONFIG_BIAS_DISABLE: 134 enable = 0; 135 break; 136 case PIN_CONFIG_BIAS_PULL_UP: 137 case PIN_CONFIG_BIAS_PULL_DOWN: 138 if (arg == 0) /* total bias is not supported */ 139 return -EINVAL; 140 break; 141 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 142 if (arg == 0) /* configuration ignored */ 143 return 0; 144 default: 145 BUG(); 146 } 147 148 reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4; 149 mask = BIT(pin % 32); 150 151 tmp = readl(priv->base + reg); 152 if (enable) 153 tmp |= mask; 154 else 155 tmp &= ~mask; 156 writel(tmp, priv->base + reg); 157 158 return 0; 159 } 160 161 static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin, 162 unsigned int param, unsigned int arg) 163 { 164 int ret; 165 166 switch (param) { 167 case PIN_CONFIG_BIAS_DISABLE: 168 case PIN_CONFIG_BIAS_PULL_UP: 169 case PIN_CONFIG_BIAS_PULL_DOWN: 170 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 171 ret = uniphier_pinconf_bias_set(dev, pin, param, arg); 172 break; 173 case PIN_CONFIG_INPUT_ENABLE: 174 ret = uniphier_pinconf_input_enable(dev, pin, arg); 175 break; 176 default: 177 printf("unsupported configuration parameter %u\n", param); 178 return -EINVAL; 179 } 180 181 return ret; 182 } 183 184 static int uniphier_pinconf_group_set(struct udevice *dev, 185 unsigned int group_selector, 186 unsigned int param, unsigned int arg) 187 { 188 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 189 const struct uniphier_pinctrl_group *grp = 190 &priv->socdata->groups[group_selector]; 191 int i, ret; 192 193 for (i = 0; i < grp->num_pins; i++) { 194 ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg); 195 if (ret) 196 return ret; 197 } 198 199 return 0; 200 } 201 202 #endif /* CONFIG_IS_ENABLED(PINCONF) */ 203 204 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, 205 int muxval) 206 { 207 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 208 unsigned reg, reg_end, shift, mask; 209 unsigned mux_bits = 8; 210 unsigned reg_stride = 4; 211 bool load_pinctrl = false; 212 u32 tmp; 213 214 /* some pins need input-enabling */ 215 uniphier_pinconf_input_enable(dev, pin, 1); 216 217 if (muxval < 0) 218 return; /* dedicated pin; nothing to do for pin-mux */ 219 220 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_MUX_4BIT) 221 mux_bits = 4; 222 223 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) { 224 /* 225 * Mode offset bit 226 * Normal 4 * n shift+3:shift 227 * Debug 4 * n shift+7:shift+4 228 */ 229 mux_bits /= 2; 230 reg_stride = 8; 231 load_pinctrl = true; 232 } 233 234 reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride; 235 reg_end = reg + reg_stride; 236 shift = pin * mux_bits % 32; 237 mask = (1U << mux_bits) - 1; 238 239 /* 240 * If reg_stride is greater than 4, the MSB of each pinsel shall be 241 * stored in the offset+4. 242 */ 243 for (; reg < reg_end; reg += 4) { 244 tmp = readl(priv->base + reg); 245 tmp &= ~(mask << shift); 246 tmp |= (mask & muxval) << shift; 247 writel(tmp, priv->base + reg); 248 249 muxval >>= mux_bits; 250 } 251 252 if (load_pinctrl) 253 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX); 254 } 255 256 static int uniphier_pinmux_group_set(struct udevice *dev, 257 unsigned group_selector, 258 unsigned func_selector) 259 { 260 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 261 const struct uniphier_pinctrl_group *grp = 262 &priv->socdata->groups[group_selector]; 263 int i; 264 265 for (i = 0; i < grp->num_pins; i++) 266 uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]); 267 268 return 0; 269 } 270 271 const struct pinctrl_ops uniphier_pinctrl_ops = { 272 .get_groups_count = uniphier_pinctrl_get_groups_count, 273 .get_group_name = uniphier_pinctrl_get_group_name, 274 .get_functions_count = uniphier_pinmux_get_functions_count, 275 .get_function_name = uniphier_pinmux_get_function_name, 276 .pinmux_group_set = uniphier_pinmux_group_set, 277 #if CONFIG_IS_ENABLED(PINCONF) 278 .pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params), 279 .pinconf_params = uniphier_pinconf_params, 280 .pinconf_group_set = uniphier_pinconf_group_set, 281 #endif 282 .set_state = pinctrl_generic_set_state, 283 }; 284 285 int uniphier_pinctrl_probe(struct udevice *dev, 286 struct uniphier_pinctrl_socdata *socdata) 287 { 288 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 289 fdt_addr_t addr; 290 291 addr = devfdt_get_addr(dev->parent); 292 if (addr == FDT_ADDR_T_NONE) 293 return -EINVAL; 294 295 priv->base = devm_ioremap(dev, addr, SZ_4K); 296 if (!priv->base) 297 return -ENOMEM; 298 299 priv->socdata = socdata; 300 301 return 0; 302 } 303