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