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(struct udevice *dev, unsigned pin) 48 { 49 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 50 int pins_count = priv->socdata->pins_count; 51 const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; 52 int i; 53 54 for (i = 0; i < pins_count; i++) { 55 if (pins[i].number == pin) { 56 unsigned int iectrl; 57 u32 tmp; 58 59 iectrl = uniphier_pin_get_iectrl(pins[i].data); 60 tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL); 61 tmp |= 1 << iectrl; 62 writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL); 63 } 64 } 65 } 66 67 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, 68 unsigned muxval) 69 { 70 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 71 unsigned mux_bits = priv->socdata->mux_bits; 72 unsigned reg_stride = priv->socdata->reg_stride; 73 unsigned reg, reg_end, shift, mask; 74 u32 tmp; 75 76 /* some pins need input-enabling */ 77 uniphier_pinconf_input_enable(dev, pin); 78 79 reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride; 80 reg_end = reg + reg_stride; 81 shift = pin * mux_bits % 32; 82 mask = (1U << mux_bits) - 1; 83 84 /* 85 * If reg_stride is greater than 4, the MSB of each pinsel shall be 86 * stored in the offset+4. 87 */ 88 for (; reg < reg_end; reg += 4) { 89 tmp = readl(priv->base + reg); 90 tmp &= ~(mask << shift); 91 tmp |= (mask & muxval) << shift; 92 writel(tmp, priv->base + reg); 93 94 muxval >>= mux_bits; 95 } 96 97 if (priv->socdata->load_pinctrl) 98 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX); 99 } 100 101 static int uniphier_pinmux_group_set(struct udevice *dev, 102 unsigned group_selector, 103 unsigned func_selector) 104 { 105 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 106 const struct uniphier_pinctrl_group *grp = 107 &priv->socdata->groups[group_selector]; 108 int i; 109 110 for (i = 0; i < grp->num_pins; i++) 111 uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]); 112 113 return 0; 114 } 115 116 const struct pinctrl_ops uniphier_pinctrl_ops = { 117 .get_groups_count = uniphier_pinctrl_get_groups_count, 118 .get_group_name = uniphier_pinctrl_get_group_name, 119 .get_functions_count = uniphier_pinmux_get_functions_count, 120 .get_function_name = uniphier_pinmux_get_function_name, 121 .pinmux_group_set = uniphier_pinmux_group_set, 122 .set_state = pinctrl_generic_set_state, 123 }; 124 125 int uniphier_pinctrl_probe(struct udevice *dev, 126 struct uniphier_pinctrl_socdata *socdata) 127 { 128 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 129 fdt_addr_t addr; 130 131 addr = dev_get_addr(dev); 132 if (addr == FDT_ADDR_T_NONE) 133 return -EINVAL; 134 135 priv->base = map_sysmem(addr, SZ_4K); 136 if (!priv->base) 137 return -ENOMEM; 138 139 priv->socdata = socdata; 140 141 return 0; 142 } 143 144 int uniphier_pinctrl_remove(struct udevice *dev) 145 { 146 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 147 148 unmap_sysmem(priv->base); 149 150 return 0; 151 } 152