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