xref: /rk3399_rockchip-uboot/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c (revision 4e3d84066e09c9ab6cee2102db7a2c51090962a4)
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