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