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