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 #define UNIPHIER_PINCTRL_PINMUX_BASE 0x1000 17 #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x1700 18 #define UNIPHIER_PINCTRL_IECTRL 0x1d00 19 20 static const char *uniphier_pinctrl_dummy_name = "_dummy"; 21 22 static int uniphier_pinctrl_get_groups_count(struct udevice *dev) 23 { 24 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 25 26 return priv->socdata->groups_count; 27 } 28 29 static const char *uniphier_pinctrl_get_group_name(struct udevice *dev, 30 unsigned selector) 31 { 32 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 33 34 if (!priv->socdata->groups[selector].name) 35 return uniphier_pinctrl_dummy_name; 36 37 return priv->socdata->groups[selector].name; 38 } 39 40 static int uniphier_pinmux_get_functions_count(struct udevice *dev) 41 { 42 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 43 44 return priv->socdata->functions_count; 45 } 46 47 static const char *uniphier_pinmux_get_function_name(struct udevice *dev, 48 unsigned selector) 49 { 50 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 51 52 if (!priv->socdata->functions[selector]) 53 return uniphier_pinctrl_dummy_name; 54 55 return priv->socdata->functions[selector]; 56 } 57 58 static void uniphier_pinconf_input_enable_perpin(struct udevice *dev, 59 unsigned pin) 60 { 61 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 62 unsigned reg; 63 u32 mask, tmp; 64 65 reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4; 66 mask = BIT(pin % 32); 67 68 tmp = readl(priv->base + reg); 69 tmp |= mask; 70 writel(tmp, priv->base + reg); 71 } 72 73 static void uniphier_pinconf_input_enable_legacy(struct udevice *dev, 74 unsigned pin) 75 { 76 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 77 int pins_count = priv->socdata->pins_count; 78 const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; 79 int i; 80 81 for (i = 0; i < pins_count; i++) { 82 if (pins[i].number == pin) { 83 unsigned int iectrl; 84 u32 tmp; 85 86 iectrl = uniphier_pin_get_iectrl(pins[i].data); 87 tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL); 88 tmp |= 1 << iectrl; 89 writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL); 90 } 91 } 92 } 93 94 static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin) 95 { 96 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 97 98 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) 99 uniphier_pinconf_input_enable_perpin(dev, pin); 100 else 101 uniphier_pinconf_input_enable_legacy(dev, pin); 102 } 103 104 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, 105 int muxval) 106 { 107 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 108 unsigned reg, reg_end, shift, mask; 109 unsigned mux_bits = 8; 110 unsigned reg_stride = 4; 111 bool load_pinctrl = false; 112 u32 tmp; 113 114 /* some pins need input-enabling */ 115 uniphier_pinconf_input_enable(dev, pin); 116 117 if (muxval < 0) 118 return; /* dedicated pin; nothing to do for pin-mux */ 119 120 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_MUX_4BIT) 121 mux_bits = 4; 122 123 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) { 124 /* 125 * Mode offset bit 126 * Normal 4 * n shift+3:shift 127 * Debug 4 * n shift+7:shift+4 128 */ 129 mux_bits /= 2; 130 reg_stride = 8; 131 load_pinctrl = true; 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