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 <linux/io.h> 9 #include <linux/err.h> 10 #include <linux/sizes.h> 11 #include <dm/device.h> 12 #include <dm/pinctrl.h> 13 14 #include "pinctrl-uniphier.h" 15 16 static const char *uniphier_pinctrl_dummy_name = "_dummy"; 17 18 static int uniphier_pinctrl_get_groups_count(struct udevice *dev) 19 { 20 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 21 22 return priv->socdata->groups_count; 23 } 24 25 static const char *uniphier_pinctrl_get_group_name(struct udevice *dev, 26 unsigned selector) 27 { 28 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 29 30 if (!priv->socdata->groups[selector].name) 31 return uniphier_pinctrl_dummy_name; 32 33 return priv->socdata->groups[selector].name; 34 } 35 36 static int uniphier_pinmux_get_functions_count(struct udevice *dev) 37 { 38 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 39 40 return priv->socdata->functions_count; 41 } 42 43 static const char *uniphier_pinmux_get_function_name(struct udevice *dev, 44 unsigned selector) 45 { 46 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 47 48 if (!priv->socdata->functions[selector]) 49 return uniphier_pinctrl_dummy_name; 50 51 return priv->socdata->functions[selector]; 52 } 53 54 static void uniphier_pinconf_input_enable_perpin(struct udevice *dev, 55 unsigned pin) 56 { 57 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 58 unsigned reg; 59 u32 mask, tmp; 60 61 reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4; 62 mask = BIT(pin % 32); 63 64 tmp = readl(priv->base + reg); 65 tmp |= mask; 66 writel(tmp, priv->base + reg); 67 } 68 69 static void uniphier_pinconf_input_enable_legacy(struct udevice *dev, 70 unsigned pin) 71 { 72 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 73 int pins_count = priv->socdata->pins_count; 74 const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; 75 int i; 76 77 for (i = 0; i < pins_count; i++) { 78 if (pins[i].number == pin) { 79 unsigned int iectrl; 80 u32 tmp; 81 82 iectrl = uniphier_pin_get_iectrl(pins[i].data); 83 tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL); 84 tmp |= 1 << iectrl; 85 writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL); 86 } 87 } 88 } 89 90 static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin) 91 { 92 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 93 94 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) 95 uniphier_pinconf_input_enable_perpin(dev, pin); 96 else 97 uniphier_pinconf_input_enable_legacy(dev, pin); 98 } 99 100 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, 101 int muxval) 102 { 103 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 104 unsigned mux_bits, reg_stride, reg, reg_end, shift, mask; 105 bool load_pinctrl; 106 u32 tmp; 107 108 /* some pins need input-enabling */ 109 uniphier_pinconf_input_enable(dev, pin); 110 111 if (muxval < 0) 112 return; /* dedicated pin; nothing to do for pin-mux */ 113 114 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) { 115 /* 116 * Mode offset bit 117 * Normal 4 * n shift+3:shift 118 * Debug 4 * n shift+7:shift+4 119 */ 120 mux_bits = 4; 121 reg_stride = 8; 122 load_pinctrl = true; 123 } else { 124 /* 125 * Mode offset bit 126 * Normal 8 * n shift+3:shift 127 * Debug 8 * n + 4 shift+3:shift 128 */ 129 mux_bits = 8; 130 reg_stride = 4; 131 load_pinctrl = false; 132 } 133 134 reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride; 135 reg_end = reg + reg_stride; 136 shift = pin * mux_bits % 32; 137 mask = (1U << mux_bits) - 1; 138 139 /* 140 * If reg_stride is greater than 4, the MSB of each pinsel shall be 141 * stored in the offset+4. 142 */ 143 for (; reg < reg_end; reg += 4) { 144 tmp = readl(priv->base + reg); 145 tmp &= ~(mask << shift); 146 tmp |= (mask & muxval) << shift; 147 writel(tmp, priv->base + reg); 148 149 muxval >>= mux_bits; 150 } 151 152 if (load_pinctrl) 153 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX); 154 } 155 156 static int uniphier_pinmux_group_set(struct udevice *dev, 157 unsigned group_selector, 158 unsigned func_selector) 159 { 160 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 161 const struct uniphier_pinctrl_group *grp = 162 &priv->socdata->groups[group_selector]; 163 int i; 164 165 for (i = 0; i < grp->num_pins; i++) 166 uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]); 167 168 return 0; 169 } 170 171 const struct pinctrl_ops uniphier_pinctrl_ops = { 172 .get_groups_count = uniphier_pinctrl_get_groups_count, 173 .get_group_name = uniphier_pinctrl_get_group_name, 174 .get_functions_count = uniphier_pinmux_get_functions_count, 175 .get_function_name = uniphier_pinmux_get_function_name, 176 .pinmux_group_set = uniphier_pinmux_group_set, 177 .set_state = pinctrl_generic_set_state, 178 }; 179 180 int uniphier_pinctrl_probe(struct udevice *dev, 181 struct uniphier_pinctrl_socdata *socdata) 182 { 183 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 184 fdt_addr_t addr; 185 186 addr = dev_get_addr(dev->parent); 187 if (addr == FDT_ADDR_T_NONE) 188 return -EINVAL; 189 190 priv->base = devm_ioremap(dev, addr, SZ_4K); 191 if (!priv->base) 192 return -ENOMEM; 193 194 priv->socdata = socdata; 195 196 return 0; 197 } 198