15dc626f8SMasahiro Yamada /*
24e3d8406SMasahiro Yamada * Copyright (C) 2015-2016 Socionext Inc.
34e3d8406SMasahiro Yamada * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
45dc626f8SMasahiro Yamada *
55dc626f8SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+
65dc626f8SMasahiro Yamada */
75dc626f8SMasahiro Yamada
86a6b9d5dSMasahiro Yamada #include <common.h>
99d922450SSimon Glass #include <dm.h>
105dc626f8SMasahiro Yamada #include <linux/io.h>
115dc626f8SMasahiro Yamada #include <linux/err.h>
12510454dbSMasahiro Yamada #include <linux/sizes.h>
135dc626f8SMasahiro Yamada #include <dm/pinctrl.h>
145dc626f8SMasahiro Yamada
155dc626f8SMasahiro Yamada #include "pinctrl-uniphier.h"
165dc626f8SMasahiro Yamada
17cdc7e3cbSMasahiro Yamada #define UNIPHIER_PINCTRL_PINMUX_BASE 0x1000
18cdc7e3cbSMasahiro Yamada #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x1700
196a6b9d5dSMasahiro Yamada #define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00
20cdc7e3cbSMasahiro Yamada #define UNIPHIER_PINCTRL_IECTRL 0x1d00
21cdc7e3cbSMasahiro Yamada
2264c1cc4cSMasahiro Yamada static const char *uniphier_pinctrl_dummy_name = "_dummy";
2364c1cc4cSMasahiro Yamada
uniphier_pinctrl_get_groups_count(struct udevice * dev)245dc626f8SMasahiro Yamada static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
255dc626f8SMasahiro Yamada {
265dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
275dc626f8SMasahiro Yamada
285dc626f8SMasahiro Yamada return priv->socdata->groups_count;
295dc626f8SMasahiro Yamada }
305dc626f8SMasahiro Yamada
uniphier_pinctrl_get_group_name(struct udevice * dev,unsigned selector)315dc626f8SMasahiro Yamada static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
325dc626f8SMasahiro Yamada unsigned selector)
335dc626f8SMasahiro Yamada {
345dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
355dc626f8SMasahiro Yamada
3664c1cc4cSMasahiro Yamada if (!priv->socdata->groups[selector].name)
3764c1cc4cSMasahiro Yamada return uniphier_pinctrl_dummy_name;
3864c1cc4cSMasahiro Yamada
395dc626f8SMasahiro Yamada return priv->socdata->groups[selector].name;
405dc626f8SMasahiro Yamada }
415dc626f8SMasahiro Yamada
uniphier_pinmux_get_functions_count(struct udevice * dev)425dc626f8SMasahiro Yamada static int uniphier_pinmux_get_functions_count(struct udevice *dev)
435dc626f8SMasahiro Yamada {
445dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
455dc626f8SMasahiro Yamada
465dc626f8SMasahiro Yamada return priv->socdata->functions_count;
475dc626f8SMasahiro Yamada }
485dc626f8SMasahiro Yamada
uniphier_pinmux_get_function_name(struct udevice * dev,unsigned selector)495dc626f8SMasahiro Yamada static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
505dc626f8SMasahiro Yamada unsigned selector)
515dc626f8SMasahiro Yamada {
525dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
535dc626f8SMasahiro Yamada
5464c1cc4cSMasahiro Yamada if (!priv->socdata->functions[selector])
5564c1cc4cSMasahiro Yamada return uniphier_pinctrl_dummy_name;
5664c1cc4cSMasahiro Yamada
575dc626f8SMasahiro Yamada return priv->socdata->functions[selector];
585dc626f8SMasahiro Yamada }
595dc626f8SMasahiro Yamada
uniphier_pinconf_input_enable_perpin(struct udevice * dev,unsigned int pin,int enable)606a6b9d5dSMasahiro Yamada static int uniphier_pinconf_input_enable_perpin(struct udevice *dev,
616a6b9d5dSMasahiro Yamada unsigned int pin, int enable)
623b05b5f0SMasahiro Yamada {
633b05b5f0SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
643b05b5f0SMasahiro Yamada unsigned reg;
653b05b5f0SMasahiro Yamada u32 mask, tmp;
663b05b5f0SMasahiro Yamada
673b05b5f0SMasahiro Yamada reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
683b05b5f0SMasahiro Yamada mask = BIT(pin % 32);
693b05b5f0SMasahiro Yamada
703b05b5f0SMasahiro Yamada tmp = readl(priv->base + reg);
716a6b9d5dSMasahiro Yamada if (enable)
723b05b5f0SMasahiro Yamada tmp |= mask;
736a6b9d5dSMasahiro Yamada else
746a6b9d5dSMasahiro Yamada tmp &= ~mask;
753b05b5f0SMasahiro Yamada writel(tmp, priv->base + reg);
766a6b9d5dSMasahiro Yamada
776a6b9d5dSMasahiro Yamada return 0;
783b05b5f0SMasahiro Yamada }
793b05b5f0SMasahiro Yamada
uniphier_pinconf_input_enable_legacy(struct udevice * dev,unsigned int pin,int enable)806a6b9d5dSMasahiro Yamada static int uniphier_pinconf_input_enable_legacy(struct udevice *dev,
816a6b9d5dSMasahiro Yamada unsigned int pin, int enable)
825dc626f8SMasahiro Yamada {
835dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
845dc626f8SMasahiro Yamada int pins_count = priv->socdata->pins_count;
855dc626f8SMasahiro Yamada const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
865dc626f8SMasahiro Yamada int i;
875dc626f8SMasahiro Yamada
886a6b9d5dSMasahiro Yamada /*
896a6b9d5dSMasahiro Yamada * Multiple pins share one input enable, per-pin disabling is
906a6b9d5dSMasahiro Yamada * impossible.
916a6b9d5dSMasahiro Yamada */
926a6b9d5dSMasahiro Yamada if (!enable)
936a6b9d5dSMasahiro Yamada return -EINVAL;
946a6b9d5dSMasahiro Yamada
955dc626f8SMasahiro Yamada for (i = 0; i < pins_count; i++) {
965dc626f8SMasahiro Yamada if (pins[i].number == pin) {
975dc626f8SMasahiro Yamada unsigned int iectrl;
985dc626f8SMasahiro Yamada u32 tmp;
995dc626f8SMasahiro Yamada
1005dc626f8SMasahiro Yamada iectrl = uniphier_pin_get_iectrl(pins[i].data);
1015dc626f8SMasahiro Yamada tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
1025dc626f8SMasahiro Yamada tmp |= 1 << iectrl;
1035dc626f8SMasahiro Yamada writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
1045dc626f8SMasahiro Yamada }
1055dc626f8SMasahiro Yamada }
1066a6b9d5dSMasahiro Yamada
1076a6b9d5dSMasahiro Yamada return 0;
1085dc626f8SMasahiro Yamada }
1095dc626f8SMasahiro Yamada
uniphier_pinconf_input_enable(struct udevice * dev,unsigned int pin,int enable)1106a6b9d5dSMasahiro Yamada static int uniphier_pinconf_input_enable(struct udevice *dev,
1116a6b9d5dSMasahiro Yamada unsigned int pin, int enable)
1123b05b5f0SMasahiro Yamada {
1133b05b5f0SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
1143b05b5f0SMasahiro Yamada
1153b05b5f0SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
1166a6b9d5dSMasahiro Yamada return uniphier_pinconf_input_enable_perpin(dev, pin, enable);
1173b05b5f0SMasahiro Yamada else
1186a6b9d5dSMasahiro Yamada return uniphier_pinconf_input_enable_legacy(dev, pin, enable);
1193b05b5f0SMasahiro Yamada }
1203b05b5f0SMasahiro Yamada
1216a6b9d5dSMasahiro Yamada #if CONFIG_IS_ENABLED(PINCONF)
1226a6b9d5dSMasahiro Yamada
1236a6b9d5dSMasahiro Yamada static const struct pinconf_param uniphier_pinconf_params[] = {
1246a6b9d5dSMasahiro Yamada { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
1256a6b9d5dSMasahiro Yamada { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
1266a6b9d5dSMasahiro Yamada { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
1276a6b9d5dSMasahiro Yamada { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
1286a6b9d5dSMasahiro Yamada { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
1296a6b9d5dSMasahiro Yamada { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
1306a6b9d5dSMasahiro Yamada };
1316a6b9d5dSMasahiro Yamada
uniphier_pinconf_bias_set(struct udevice * dev,unsigned int pin,unsigned int param,unsigned int arg)1326a6b9d5dSMasahiro Yamada static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
1336a6b9d5dSMasahiro Yamada unsigned int param, unsigned int arg)
1346a6b9d5dSMasahiro Yamada {
1356a6b9d5dSMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
1366a6b9d5dSMasahiro Yamada unsigned int enable = 1;
1376a6b9d5dSMasahiro Yamada unsigned int reg;
1386a6b9d5dSMasahiro Yamada u32 mask, tmp;
1396a6b9d5dSMasahiro Yamada
1406a6b9d5dSMasahiro Yamada if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE))
1416a6b9d5dSMasahiro Yamada return -ENOTSUPP;
1426a6b9d5dSMasahiro Yamada
1436a6b9d5dSMasahiro Yamada switch (param) {
1446a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_DISABLE:
1456a6b9d5dSMasahiro Yamada enable = 0;
1466a6b9d5dSMasahiro Yamada break;
1476a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_PULL_UP:
1486a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_PULL_DOWN:
1496a6b9d5dSMasahiro Yamada if (arg == 0) /* total bias is not supported */
1506a6b9d5dSMasahiro Yamada return -EINVAL;
1516a6b9d5dSMasahiro Yamada break;
1526a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
1536a6b9d5dSMasahiro Yamada if (arg == 0) /* configuration ignored */
1546a6b9d5dSMasahiro Yamada return 0;
1556a6b9d5dSMasahiro Yamada default:
1566a6b9d5dSMasahiro Yamada BUG();
1576a6b9d5dSMasahiro Yamada }
1586a6b9d5dSMasahiro Yamada
1596a6b9d5dSMasahiro Yamada reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4;
1606a6b9d5dSMasahiro Yamada mask = BIT(pin % 32);
1616a6b9d5dSMasahiro Yamada
1626a6b9d5dSMasahiro Yamada tmp = readl(priv->base + reg);
1636a6b9d5dSMasahiro Yamada if (enable)
1646a6b9d5dSMasahiro Yamada tmp |= mask;
1656a6b9d5dSMasahiro Yamada else
1666a6b9d5dSMasahiro Yamada tmp &= ~mask;
1676a6b9d5dSMasahiro Yamada writel(tmp, priv->base + reg);
1686a6b9d5dSMasahiro Yamada
1696a6b9d5dSMasahiro Yamada return 0;
1706a6b9d5dSMasahiro Yamada }
1716a6b9d5dSMasahiro Yamada
uniphier_pinconf_set_one(struct udevice * dev,unsigned int pin,unsigned int param,unsigned int arg)1726a6b9d5dSMasahiro Yamada static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin,
1736a6b9d5dSMasahiro Yamada unsigned int param, unsigned int arg)
1746a6b9d5dSMasahiro Yamada {
1756a6b9d5dSMasahiro Yamada int ret;
1766a6b9d5dSMasahiro Yamada
1776a6b9d5dSMasahiro Yamada switch (param) {
1786a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_DISABLE:
1796a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_PULL_UP:
1806a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_PULL_DOWN:
1816a6b9d5dSMasahiro Yamada case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
1826a6b9d5dSMasahiro Yamada ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
1836a6b9d5dSMasahiro Yamada break;
1846a6b9d5dSMasahiro Yamada case PIN_CONFIG_INPUT_ENABLE:
1856a6b9d5dSMasahiro Yamada ret = uniphier_pinconf_input_enable(dev, pin, arg);
1866a6b9d5dSMasahiro Yamada break;
1876a6b9d5dSMasahiro Yamada default:
1886a6b9d5dSMasahiro Yamada printf("unsupported configuration parameter %u\n", param);
1896a6b9d5dSMasahiro Yamada return -EINVAL;
1906a6b9d5dSMasahiro Yamada }
1916a6b9d5dSMasahiro Yamada
1926a6b9d5dSMasahiro Yamada return ret;
1936a6b9d5dSMasahiro Yamada }
1946a6b9d5dSMasahiro Yamada
uniphier_pinconf_group_set(struct udevice * dev,unsigned int group_selector,unsigned int param,unsigned int arg)1956a6b9d5dSMasahiro Yamada static int uniphier_pinconf_group_set(struct udevice *dev,
1966a6b9d5dSMasahiro Yamada unsigned int group_selector,
1976a6b9d5dSMasahiro Yamada unsigned int param, unsigned int arg)
1986a6b9d5dSMasahiro Yamada {
1996a6b9d5dSMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
2006a6b9d5dSMasahiro Yamada const struct uniphier_pinctrl_group *grp =
2016a6b9d5dSMasahiro Yamada &priv->socdata->groups[group_selector];
2026a6b9d5dSMasahiro Yamada int i, ret;
2036a6b9d5dSMasahiro Yamada
2046a6b9d5dSMasahiro Yamada for (i = 0; i < grp->num_pins; i++) {
2056a6b9d5dSMasahiro Yamada ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg);
2066a6b9d5dSMasahiro Yamada if (ret)
2076a6b9d5dSMasahiro Yamada return ret;
2086a6b9d5dSMasahiro Yamada }
2096a6b9d5dSMasahiro Yamada
2106a6b9d5dSMasahiro Yamada return 0;
2116a6b9d5dSMasahiro Yamada }
2126a6b9d5dSMasahiro Yamada
2136a6b9d5dSMasahiro Yamada #endif /* CONFIG_IS_ENABLED(PINCONF) */
2146a6b9d5dSMasahiro Yamada
uniphier_pinmux_set_one(struct udevice * dev,unsigned pin,int muxval)2155dc626f8SMasahiro Yamada static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
2165e25b9d5SMasahiro Yamada int muxval)
2175dc626f8SMasahiro Yamada {
2185dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
219bbb11980SMasahiro Yamada unsigned reg, reg_end, shift, mask;
220bbb11980SMasahiro Yamada unsigned mux_bits = 8;
221bbb11980SMasahiro Yamada unsigned reg_stride = 4;
222bbb11980SMasahiro Yamada bool load_pinctrl = false;
2235dc626f8SMasahiro Yamada u32 tmp;
2245dc626f8SMasahiro Yamada
225fdd15b6aSMasahiro Yamada /* some pins need input-enabling */
2266a6b9d5dSMasahiro Yamada uniphier_pinconf_input_enable(dev, pin, 1);
227fdd15b6aSMasahiro Yamada
2285e25b9d5SMasahiro Yamada if (muxval < 0)
2295e25b9d5SMasahiro Yamada return; /* dedicated pin; nothing to do for pin-mux */
2305e25b9d5SMasahiro Yamada
231bbb11980SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_MUX_4BIT)
232bbb11980SMasahiro Yamada mux_bits = 4;
233bbb11980SMasahiro Yamada
2348cc92b99SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
2358cc92b99SMasahiro Yamada /*
2368cc92b99SMasahiro Yamada * Mode offset bit
2378cc92b99SMasahiro Yamada * Normal 4 * n shift+3:shift
2388cc92b99SMasahiro Yamada * Debug 4 * n shift+7:shift+4
2398cc92b99SMasahiro Yamada */
240bbb11980SMasahiro Yamada mux_bits /= 2;
2418cc92b99SMasahiro Yamada reg_stride = 8;
2428cc92b99SMasahiro Yamada load_pinctrl = true;
2438cc92b99SMasahiro Yamada }
2448cc92b99SMasahiro Yamada
2455dc626f8SMasahiro Yamada reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
2465dc626f8SMasahiro Yamada reg_end = reg + reg_stride;
2475dc626f8SMasahiro Yamada shift = pin * mux_bits % 32;
2485dc626f8SMasahiro Yamada mask = (1U << mux_bits) - 1;
2495dc626f8SMasahiro Yamada
2505dc626f8SMasahiro Yamada /*
2515dc626f8SMasahiro Yamada * If reg_stride is greater than 4, the MSB of each pinsel shall be
2525dc626f8SMasahiro Yamada * stored in the offset+4.
2535dc626f8SMasahiro Yamada */
2545dc626f8SMasahiro Yamada for (; reg < reg_end; reg += 4) {
2555dc626f8SMasahiro Yamada tmp = readl(priv->base + reg);
2565dc626f8SMasahiro Yamada tmp &= ~(mask << shift);
2575dc626f8SMasahiro Yamada tmp |= (mask & muxval) << shift;
2585dc626f8SMasahiro Yamada writel(tmp, priv->base + reg);
2595dc626f8SMasahiro Yamada
2605dc626f8SMasahiro Yamada muxval >>= mux_bits;
2615dc626f8SMasahiro Yamada }
2625dc626f8SMasahiro Yamada
2638cc92b99SMasahiro Yamada if (load_pinctrl)
2645dc626f8SMasahiro Yamada writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
2655dc626f8SMasahiro Yamada }
2665dc626f8SMasahiro Yamada
uniphier_pinmux_group_set(struct udevice * dev,unsigned group_selector,unsigned func_selector)2675dc626f8SMasahiro Yamada static int uniphier_pinmux_group_set(struct udevice *dev,
2685dc626f8SMasahiro Yamada unsigned group_selector,
2695dc626f8SMasahiro Yamada unsigned func_selector)
2705dc626f8SMasahiro Yamada {
2715dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
2725dc626f8SMasahiro Yamada const struct uniphier_pinctrl_group *grp =
2735dc626f8SMasahiro Yamada &priv->socdata->groups[group_selector];
2745dc626f8SMasahiro Yamada int i;
2755dc626f8SMasahiro Yamada
2765dc626f8SMasahiro Yamada for (i = 0; i < grp->num_pins; i++)
2775dc626f8SMasahiro Yamada uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
2785dc626f8SMasahiro Yamada
2795dc626f8SMasahiro Yamada return 0;
2805dc626f8SMasahiro Yamada }
2815dc626f8SMasahiro Yamada
2825dc626f8SMasahiro Yamada const struct pinctrl_ops uniphier_pinctrl_ops = {
2835dc626f8SMasahiro Yamada .get_groups_count = uniphier_pinctrl_get_groups_count,
2845dc626f8SMasahiro Yamada .get_group_name = uniphier_pinctrl_get_group_name,
2855dc626f8SMasahiro Yamada .get_functions_count = uniphier_pinmux_get_functions_count,
2865dc626f8SMasahiro Yamada .get_function_name = uniphier_pinmux_get_function_name,
2875dc626f8SMasahiro Yamada .pinmux_group_set = uniphier_pinmux_group_set,
2886a6b9d5dSMasahiro Yamada #if CONFIG_IS_ENABLED(PINCONF)
2896a6b9d5dSMasahiro Yamada .pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
2906a6b9d5dSMasahiro Yamada .pinconf_params = uniphier_pinconf_params,
2916a6b9d5dSMasahiro Yamada .pinconf_group_set = uniphier_pinconf_group_set,
2926a6b9d5dSMasahiro Yamada #endif
2935dc626f8SMasahiro Yamada .set_state = pinctrl_generic_set_state,
2945dc626f8SMasahiro Yamada };
2955dc626f8SMasahiro Yamada
uniphier_pinctrl_probe(struct udevice * dev,struct uniphier_pinctrl_socdata * socdata)2965dc626f8SMasahiro Yamada int uniphier_pinctrl_probe(struct udevice *dev,
2975dc626f8SMasahiro Yamada struct uniphier_pinctrl_socdata *socdata)
2985dc626f8SMasahiro Yamada {
2995dc626f8SMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
3005dc626f8SMasahiro Yamada fdt_addr_t addr;
3015dc626f8SMasahiro Yamada
302*a821c4afSSimon Glass addr = devfdt_get_addr(dev->parent);
3035dc626f8SMasahiro Yamada if (addr == FDT_ADDR_T_NONE)
3045dc626f8SMasahiro Yamada return -EINVAL;
3055dc626f8SMasahiro Yamada
3064e3d8406SMasahiro Yamada priv->base = devm_ioremap(dev, addr, SZ_4K);
3075dc626f8SMasahiro Yamada if (!priv->base)
3085dc626f8SMasahiro Yamada return -ENOMEM;
3095dc626f8SMasahiro Yamada
3105dc626f8SMasahiro Yamada priv->socdata = socdata;
3115dc626f8SMasahiro Yamada
3125dc626f8SMasahiro Yamada return 0;
3135dc626f8SMasahiro Yamada }
314