15dc626f8SMasahiro Yamada /* 25dc626f8SMasahiro Yamada * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 35dc626f8SMasahiro Yamada * 45dc626f8SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 55dc626f8SMasahiro Yamada */ 65dc626f8SMasahiro Yamada 75dc626f8SMasahiro Yamada #include <common.h> 85dc626f8SMasahiro Yamada #include <mapmem.h> 95dc626f8SMasahiro Yamada #include <linux/io.h> 105dc626f8SMasahiro Yamada #include <linux/err.h> 11510454dbSMasahiro Yamada #include <linux/sizes.h> 125dc626f8SMasahiro Yamada #include <dm/device.h> 135dc626f8SMasahiro Yamada #include <dm/pinctrl.h> 145dc626f8SMasahiro Yamada 155dc626f8SMasahiro Yamada #include "pinctrl-uniphier.h" 165dc626f8SMasahiro Yamada 17*64c1cc4cSMasahiro Yamada static const char *uniphier_pinctrl_dummy_name = "_dummy"; 18*64c1cc4cSMasahiro Yamada 195dc626f8SMasahiro Yamada static int uniphier_pinctrl_get_groups_count(struct udevice *dev) 205dc626f8SMasahiro Yamada { 215dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 225dc626f8SMasahiro Yamada 235dc626f8SMasahiro Yamada return priv->socdata->groups_count; 245dc626f8SMasahiro Yamada } 255dc626f8SMasahiro Yamada 265dc626f8SMasahiro Yamada static const char *uniphier_pinctrl_get_group_name(struct udevice *dev, 275dc626f8SMasahiro Yamada unsigned selector) 285dc626f8SMasahiro Yamada { 295dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 305dc626f8SMasahiro Yamada 31*64c1cc4cSMasahiro Yamada if (!priv->socdata->groups[selector].name) 32*64c1cc4cSMasahiro Yamada return uniphier_pinctrl_dummy_name; 33*64c1cc4cSMasahiro Yamada 345dc626f8SMasahiro Yamada return priv->socdata->groups[selector].name; 355dc626f8SMasahiro Yamada } 365dc626f8SMasahiro Yamada 375dc626f8SMasahiro Yamada static int uniphier_pinmux_get_functions_count(struct udevice *dev) 385dc626f8SMasahiro Yamada { 395dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 405dc626f8SMasahiro Yamada 415dc626f8SMasahiro Yamada return priv->socdata->functions_count; 425dc626f8SMasahiro Yamada } 435dc626f8SMasahiro Yamada 445dc626f8SMasahiro Yamada static const char *uniphier_pinmux_get_function_name(struct udevice *dev, 455dc626f8SMasahiro Yamada unsigned selector) 465dc626f8SMasahiro Yamada { 475dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 485dc626f8SMasahiro Yamada 49*64c1cc4cSMasahiro Yamada if (!priv->socdata->functions[selector]) 50*64c1cc4cSMasahiro Yamada return uniphier_pinctrl_dummy_name; 51*64c1cc4cSMasahiro Yamada 525dc626f8SMasahiro Yamada return priv->socdata->functions[selector]; 535dc626f8SMasahiro Yamada } 545dc626f8SMasahiro Yamada 553b05b5f0SMasahiro Yamada static void uniphier_pinconf_input_enable_perpin(struct udevice *dev, 563b05b5f0SMasahiro Yamada unsigned pin) 573b05b5f0SMasahiro Yamada { 583b05b5f0SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 593b05b5f0SMasahiro Yamada unsigned reg; 603b05b5f0SMasahiro Yamada u32 mask, tmp; 613b05b5f0SMasahiro Yamada 623b05b5f0SMasahiro Yamada reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4; 633b05b5f0SMasahiro Yamada mask = BIT(pin % 32); 643b05b5f0SMasahiro Yamada 653b05b5f0SMasahiro Yamada tmp = readl(priv->base + reg); 663b05b5f0SMasahiro Yamada tmp |= mask; 673b05b5f0SMasahiro Yamada writel(tmp, priv->base + reg); 683b05b5f0SMasahiro Yamada } 693b05b5f0SMasahiro Yamada 703b05b5f0SMasahiro Yamada static void uniphier_pinconf_input_enable_legacy(struct udevice *dev, 713b05b5f0SMasahiro Yamada unsigned pin) 725dc626f8SMasahiro Yamada { 735dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 745dc626f8SMasahiro Yamada int pins_count = priv->socdata->pins_count; 755dc626f8SMasahiro Yamada const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; 765dc626f8SMasahiro Yamada int i; 775dc626f8SMasahiro Yamada 785dc626f8SMasahiro Yamada for (i = 0; i < pins_count; i++) { 795dc626f8SMasahiro Yamada if (pins[i].number == pin) { 805dc626f8SMasahiro Yamada unsigned int iectrl; 815dc626f8SMasahiro Yamada u32 tmp; 825dc626f8SMasahiro Yamada 835dc626f8SMasahiro Yamada iectrl = uniphier_pin_get_iectrl(pins[i].data); 845dc626f8SMasahiro Yamada tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL); 855dc626f8SMasahiro Yamada tmp |= 1 << iectrl; 865dc626f8SMasahiro Yamada writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL); 875dc626f8SMasahiro Yamada } 885dc626f8SMasahiro Yamada } 895dc626f8SMasahiro Yamada } 905dc626f8SMasahiro Yamada 913b05b5f0SMasahiro Yamada static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin) 923b05b5f0SMasahiro Yamada { 933b05b5f0SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 943b05b5f0SMasahiro Yamada 953b05b5f0SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) 963b05b5f0SMasahiro Yamada uniphier_pinconf_input_enable_perpin(dev, pin); 973b05b5f0SMasahiro Yamada else 983b05b5f0SMasahiro Yamada uniphier_pinconf_input_enable_legacy(dev, pin); 993b05b5f0SMasahiro Yamada } 1003b05b5f0SMasahiro Yamada 1015dc626f8SMasahiro Yamada static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, 1025e25b9d5SMasahiro Yamada int muxval) 1035dc626f8SMasahiro Yamada { 1045dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 1058cc92b99SMasahiro Yamada unsigned mux_bits, reg_stride, reg, reg_end, shift, mask; 1068cc92b99SMasahiro Yamada bool load_pinctrl; 1075dc626f8SMasahiro Yamada u32 tmp; 1085dc626f8SMasahiro Yamada 109fdd15b6aSMasahiro Yamada /* some pins need input-enabling */ 110fdd15b6aSMasahiro Yamada uniphier_pinconf_input_enable(dev, pin); 111fdd15b6aSMasahiro Yamada 1125e25b9d5SMasahiro Yamada if (muxval < 0) 1135e25b9d5SMasahiro Yamada return; /* dedicated pin; nothing to do for pin-mux */ 1145e25b9d5SMasahiro Yamada 1158cc92b99SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) { 1168cc92b99SMasahiro Yamada /* 1178cc92b99SMasahiro Yamada * Mode offset bit 1188cc92b99SMasahiro Yamada * Normal 4 * n shift+3:shift 1198cc92b99SMasahiro Yamada * Debug 4 * n shift+7:shift+4 1208cc92b99SMasahiro Yamada */ 1218cc92b99SMasahiro Yamada mux_bits = 4; 1228cc92b99SMasahiro Yamada reg_stride = 8; 1238cc92b99SMasahiro Yamada load_pinctrl = true; 1248cc92b99SMasahiro Yamada } else { 1258cc92b99SMasahiro Yamada /* 1268cc92b99SMasahiro Yamada * Mode offset bit 1278cc92b99SMasahiro Yamada * Normal 8 * n shift+3:shift 1288cc92b99SMasahiro Yamada * Debug 8 * n + 4 shift+3:shift 1298cc92b99SMasahiro Yamada */ 1308cc92b99SMasahiro Yamada mux_bits = 8; 1318cc92b99SMasahiro Yamada reg_stride = 4; 1328cc92b99SMasahiro Yamada load_pinctrl = false; 1338cc92b99SMasahiro Yamada } 1348cc92b99SMasahiro Yamada 1355dc626f8SMasahiro Yamada reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride; 1365dc626f8SMasahiro Yamada reg_end = reg + reg_stride; 1375dc626f8SMasahiro Yamada shift = pin * mux_bits % 32; 1385dc626f8SMasahiro Yamada mask = (1U << mux_bits) - 1; 1395dc626f8SMasahiro Yamada 1405dc626f8SMasahiro Yamada /* 1415dc626f8SMasahiro Yamada * If reg_stride is greater than 4, the MSB of each pinsel shall be 1425dc626f8SMasahiro Yamada * stored in the offset+4. 1435dc626f8SMasahiro Yamada */ 1445dc626f8SMasahiro Yamada for (; reg < reg_end; reg += 4) { 1455dc626f8SMasahiro Yamada tmp = readl(priv->base + reg); 1465dc626f8SMasahiro Yamada tmp &= ~(mask << shift); 1475dc626f8SMasahiro Yamada tmp |= (mask & muxval) << shift; 1485dc626f8SMasahiro Yamada writel(tmp, priv->base + reg); 1495dc626f8SMasahiro Yamada 1505dc626f8SMasahiro Yamada muxval >>= mux_bits; 1515dc626f8SMasahiro Yamada } 1525dc626f8SMasahiro Yamada 1538cc92b99SMasahiro Yamada if (load_pinctrl) 1545dc626f8SMasahiro Yamada writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX); 1555dc626f8SMasahiro Yamada } 1565dc626f8SMasahiro Yamada 1575dc626f8SMasahiro Yamada static int uniphier_pinmux_group_set(struct udevice *dev, 1585dc626f8SMasahiro Yamada unsigned group_selector, 1595dc626f8SMasahiro Yamada unsigned func_selector) 1605dc626f8SMasahiro Yamada { 1615dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 1625dc626f8SMasahiro Yamada const struct uniphier_pinctrl_group *grp = 1635dc626f8SMasahiro Yamada &priv->socdata->groups[group_selector]; 1645dc626f8SMasahiro Yamada int i; 1655dc626f8SMasahiro Yamada 1665dc626f8SMasahiro Yamada for (i = 0; i < grp->num_pins; i++) 1675dc626f8SMasahiro Yamada uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]); 1685dc626f8SMasahiro Yamada 1695dc626f8SMasahiro Yamada return 0; 1705dc626f8SMasahiro Yamada } 1715dc626f8SMasahiro Yamada 1725dc626f8SMasahiro Yamada const struct pinctrl_ops uniphier_pinctrl_ops = { 1735dc626f8SMasahiro Yamada .get_groups_count = uniphier_pinctrl_get_groups_count, 1745dc626f8SMasahiro Yamada .get_group_name = uniphier_pinctrl_get_group_name, 1755dc626f8SMasahiro Yamada .get_functions_count = uniphier_pinmux_get_functions_count, 1765dc626f8SMasahiro Yamada .get_function_name = uniphier_pinmux_get_function_name, 1775dc626f8SMasahiro Yamada .pinmux_group_set = uniphier_pinmux_group_set, 1785dc626f8SMasahiro Yamada .set_state = pinctrl_generic_set_state, 1795dc626f8SMasahiro Yamada }; 1805dc626f8SMasahiro Yamada 1815dc626f8SMasahiro Yamada int uniphier_pinctrl_probe(struct udevice *dev, 1825dc626f8SMasahiro Yamada struct uniphier_pinctrl_socdata *socdata) 1835dc626f8SMasahiro Yamada { 1845dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 1855dc626f8SMasahiro Yamada fdt_addr_t addr; 1865dc626f8SMasahiro Yamada 187186c1334SMasahiro Yamada addr = dev_get_addr(dev->parent); 1885dc626f8SMasahiro Yamada if (addr == FDT_ADDR_T_NONE) 1895dc626f8SMasahiro Yamada return -EINVAL; 1905dc626f8SMasahiro Yamada 191510454dbSMasahiro Yamada priv->base = map_sysmem(addr, SZ_4K); 1925dc626f8SMasahiro Yamada if (!priv->base) 1935dc626f8SMasahiro Yamada return -ENOMEM; 1945dc626f8SMasahiro Yamada 1955dc626f8SMasahiro Yamada priv->socdata = socdata; 1965dc626f8SMasahiro Yamada 1975dc626f8SMasahiro Yamada return 0; 1985dc626f8SMasahiro Yamada } 1995dc626f8SMasahiro Yamada 2005dc626f8SMasahiro Yamada int uniphier_pinctrl_remove(struct udevice *dev) 2015dc626f8SMasahiro Yamada { 2025dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 2035dc626f8SMasahiro Yamada 2045dc626f8SMasahiro Yamada unmap_sysmem(priv->base); 2055dc626f8SMasahiro Yamada 2065dc626f8SMasahiro Yamada return 0; 2075dc626f8SMasahiro Yamada } 208