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> 11*510454dbSMasahiro 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 175dc626f8SMasahiro Yamada static int uniphier_pinctrl_get_groups_count(struct udevice *dev) 185dc626f8SMasahiro Yamada { 195dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 205dc626f8SMasahiro Yamada 215dc626f8SMasahiro Yamada return priv->socdata->groups_count; 225dc626f8SMasahiro Yamada } 235dc626f8SMasahiro Yamada 245dc626f8SMasahiro Yamada static const char *uniphier_pinctrl_get_group_name(struct udevice *dev, 255dc626f8SMasahiro Yamada unsigned selector) 265dc626f8SMasahiro Yamada { 275dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 285dc626f8SMasahiro Yamada 295dc626f8SMasahiro Yamada return priv->socdata->groups[selector].name; 305dc626f8SMasahiro Yamada } 315dc626f8SMasahiro Yamada 325dc626f8SMasahiro Yamada static int uniphier_pinmux_get_functions_count(struct udevice *dev) 335dc626f8SMasahiro Yamada { 345dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 355dc626f8SMasahiro Yamada 365dc626f8SMasahiro Yamada return priv->socdata->functions_count; 375dc626f8SMasahiro Yamada } 385dc626f8SMasahiro Yamada 395dc626f8SMasahiro Yamada static const char *uniphier_pinmux_get_function_name(struct udevice *dev, 405dc626f8SMasahiro Yamada unsigned selector) 415dc626f8SMasahiro Yamada { 425dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 435dc626f8SMasahiro Yamada 445dc626f8SMasahiro Yamada return priv->socdata->functions[selector]; 455dc626f8SMasahiro Yamada } 465dc626f8SMasahiro Yamada 475dc626f8SMasahiro Yamada static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin) 485dc626f8SMasahiro Yamada { 495dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 505dc626f8SMasahiro Yamada int pins_count = priv->socdata->pins_count; 515dc626f8SMasahiro Yamada const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; 525dc626f8SMasahiro Yamada int i; 535dc626f8SMasahiro Yamada 545dc626f8SMasahiro Yamada for (i = 0; i < pins_count; i++) { 555dc626f8SMasahiro Yamada if (pins[i].number == pin) { 565dc626f8SMasahiro Yamada unsigned int iectrl; 575dc626f8SMasahiro Yamada u32 tmp; 585dc626f8SMasahiro Yamada 595dc626f8SMasahiro Yamada iectrl = uniphier_pin_get_iectrl(pins[i].data); 605dc626f8SMasahiro Yamada tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL); 615dc626f8SMasahiro Yamada tmp |= 1 << iectrl; 625dc626f8SMasahiro Yamada writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL); 635dc626f8SMasahiro Yamada } 645dc626f8SMasahiro Yamada } 655dc626f8SMasahiro Yamada } 665dc626f8SMasahiro Yamada 675dc626f8SMasahiro Yamada static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, 685dc626f8SMasahiro Yamada unsigned muxval) 695dc626f8SMasahiro Yamada { 705dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 715dc626f8SMasahiro Yamada unsigned mux_bits = priv->socdata->mux_bits; 725dc626f8SMasahiro Yamada unsigned reg_stride = priv->socdata->reg_stride; 735dc626f8SMasahiro Yamada unsigned reg, reg_end, shift, mask; 745dc626f8SMasahiro Yamada u32 tmp; 755dc626f8SMasahiro Yamada 76fdd15b6aSMasahiro Yamada /* some pins need input-enabling */ 77fdd15b6aSMasahiro Yamada uniphier_pinconf_input_enable(dev, pin); 78fdd15b6aSMasahiro Yamada 795dc626f8SMasahiro Yamada reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride; 805dc626f8SMasahiro Yamada reg_end = reg + reg_stride; 815dc626f8SMasahiro Yamada shift = pin * mux_bits % 32; 825dc626f8SMasahiro Yamada mask = (1U << mux_bits) - 1; 835dc626f8SMasahiro Yamada 845dc626f8SMasahiro Yamada /* 855dc626f8SMasahiro Yamada * If reg_stride is greater than 4, the MSB of each pinsel shall be 865dc626f8SMasahiro Yamada * stored in the offset+4. 875dc626f8SMasahiro Yamada */ 885dc626f8SMasahiro Yamada for (; reg < reg_end; reg += 4) { 895dc626f8SMasahiro Yamada tmp = readl(priv->base + reg); 905dc626f8SMasahiro Yamada tmp &= ~(mask << shift); 915dc626f8SMasahiro Yamada tmp |= (mask & muxval) << shift; 925dc626f8SMasahiro Yamada writel(tmp, priv->base + reg); 935dc626f8SMasahiro Yamada 945dc626f8SMasahiro Yamada muxval >>= mux_bits; 955dc626f8SMasahiro Yamada } 965dc626f8SMasahiro Yamada 975dc626f8SMasahiro Yamada if (priv->socdata->load_pinctrl) 985dc626f8SMasahiro Yamada writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX); 995dc626f8SMasahiro Yamada } 1005dc626f8SMasahiro Yamada 1015dc626f8SMasahiro Yamada static int uniphier_pinmux_group_set(struct udevice *dev, 1025dc626f8SMasahiro Yamada unsigned group_selector, 1035dc626f8SMasahiro Yamada unsigned func_selector) 1045dc626f8SMasahiro Yamada { 1055dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 1065dc626f8SMasahiro Yamada const struct uniphier_pinctrl_group *grp = 1075dc626f8SMasahiro Yamada &priv->socdata->groups[group_selector]; 1085dc626f8SMasahiro Yamada int i; 1095dc626f8SMasahiro Yamada 1105dc626f8SMasahiro Yamada for (i = 0; i < grp->num_pins; i++) 1115dc626f8SMasahiro Yamada uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]); 1125dc626f8SMasahiro Yamada 1135dc626f8SMasahiro Yamada return 0; 1145dc626f8SMasahiro Yamada } 1155dc626f8SMasahiro Yamada 1165dc626f8SMasahiro Yamada const struct pinctrl_ops uniphier_pinctrl_ops = { 1175dc626f8SMasahiro Yamada .get_groups_count = uniphier_pinctrl_get_groups_count, 1185dc626f8SMasahiro Yamada .get_group_name = uniphier_pinctrl_get_group_name, 1195dc626f8SMasahiro Yamada .get_functions_count = uniphier_pinmux_get_functions_count, 1205dc626f8SMasahiro Yamada .get_function_name = uniphier_pinmux_get_function_name, 1215dc626f8SMasahiro Yamada .pinmux_group_set = uniphier_pinmux_group_set, 1225dc626f8SMasahiro Yamada .set_state = pinctrl_generic_set_state, 1235dc626f8SMasahiro Yamada }; 1245dc626f8SMasahiro Yamada 1255dc626f8SMasahiro Yamada int uniphier_pinctrl_probe(struct udevice *dev, 1265dc626f8SMasahiro Yamada struct uniphier_pinctrl_socdata *socdata) 1275dc626f8SMasahiro Yamada { 1285dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 1295dc626f8SMasahiro Yamada fdt_addr_t addr; 1305dc626f8SMasahiro Yamada 131*510454dbSMasahiro Yamada addr = dev_get_addr(dev); 1325dc626f8SMasahiro Yamada if (addr == FDT_ADDR_T_NONE) 1335dc626f8SMasahiro Yamada return -EINVAL; 1345dc626f8SMasahiro Yamada 135*510454dbSMasahiro Yamada priv->base = map_sysmem(addr, SZ_4K); 1365dc626f8SMasahiro Yamada if (!priv->base) 1375dc626f8SMasahiro Yamada return -ENOMEM; 1385dc626f8SMasahiro Yamada 1395dc626f8SMasahiro Yamada priv->socdata = socdata; 1405dc626f8SMasahiro Yamada 1415dc626f8SMasahiro Yamada return 0; 1425dc626f8SMasahiro Yamada } 1435dc626f8SMasahiro Yamada 1445dc626f8SMasahiro Yamada int uniphier_pinctrl_remove(struct udevice *dev) 1455dc626f8SMasahiro Yamada { 1465dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); 1475dc626f8SMasahiro Yamada 1485dc626f8SMasahiro Yamada unmap_sysmem(priv->base); 1495dc626f8SMasahiro Yamada 1505dc626f8SMasahiro Yamada return 0; 1515dc626f8SMasahiro Yamada } 152