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