xref: /rk3399_rockchip-uboot/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c (revision 64c1cc4cc5f72f480787bf493a5ebb0696d68bc0)
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>
11510454dbSMasahiro 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 
17*64c1cc4cSMasahiro Yamada static const char *uniphier_pinctrl_dummy_name = "_dummy";
18*64c1cc4cSMasahiro Yamada 
195dc626f8SMasahiro Yamada static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
205dc626f8SMasahiro Yamada {
215dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
225dc626f8SMasahiro Yamada 
235dc626f8SMasahiro Yamada 	return priv->socdata->groups_count;
245dc626f8SMasahiro Yamada }
255dc626f8SMasahiro Yamada 
265dc626f8SMasahiro Yamada static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
275dc626f8SMasahiro Yamada 						   unsigned selector)
285dc626f8SMasahiro Yamada {
295dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
305dc626f8SMasahiro Yamada 
31*64c1cc4cSMasahiro Yamada 	if (!priv->socdata->groups[selector].name)
32*64c1cc4cSMasahiro Yamada 		return uniphier_pinctrl_dummy_name;
33*64c1cc4cSMasahiro Yamada 
345dc626f8SMasahiro Yamada 	return priv->socdata->groups[selector].name;
355dc626f8SMasahiro Yamada }
365dc626f8SMasahiro Yamada 
375dc626f8SMasahiro Yamada static int uniphier_pinmux_get_functions_count(struct udevice *dev)
385dc626f8SMasahiro Yamada {
395dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
405dc626f8SMasahiro Yamada 
415dc626f8SMasahiro Yamada 	return priv->socdata->functions_count;
425dc626f8SMasahiro Yamada }
435dc626f8SMasahiro Yamada 
445dc626f8SMasahiro Yamada static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
455dc626f8SMasahiro Yamada 						     unsigned selector)
465dc626f8SMasahiro Yamada {
475dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
485dc626f8SMasahiro Yamada 
49*64c1cc4cSMasahiro Yamada 	if (!priv->socdata->functions[selector])
50*64c1cc4cSMasahiro Yamada 		return uniphier_pinctrl_dummy_name;
51*64c1cc4cSMasahiro Yamada 
525dc626f8SMasahiro Yamada 	return priv->socdata->functions[selector];
535dc626f8SMasahiro Yamada }
545dc626f8SMasahiro Yamada 
553b05b5f0SMasahiro Yamada static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
563b05b5f0SMasahiro Yamada 						 unsigned pin)
573b05b5f0SMasahiro Yamada {
583b05b5f0SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
593b05b5f0SMasahiro Yamada 	unsigned reg;
603b05b5f0SMasahiro Yamada 	u32 mask, tmp;
613b05b5f0SMasahiro Yamada 
623b05b5f0SMasahiro Yamada 	reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
633b05b5f0SMasahiro Yamada 	mask = BIT(pin % 32);
643b05b5f0SMasahiro Yamada 
653b05b5f0SMasahiro Yamada 	tmp = readl(priv->base + reg);
663b05b5f0SMasahiro Yamada 	tmp |= mask;
673b05b5f0SMasahiro Yamada 	writel(tmp, priv->base + reg);
683b05b5f0SMasahiro Yamada }
693b05b5f0SMasahiro Yamada 
703b05b5f0SMasahiro Yamada static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
713b05b5f0SMasahiro Yamada 						 unsigned pin)
725dc626f8SMasahiro Yamada {
735dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
745dc626f8SMasahiro Yamada 	int pins_count = priv->socdata->pins_count;
755dc626f8SMasahiro Yamada 	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
765dc626f8SMasahiro Yamada 	int i;
775dc626f8SMasahiro Yamada 
785dc626f8SMasahiro Yamada 	for (i = 0; i < pins_count; i++) {
795dc626f8SMasahiro Yamada 		if (pins[i].number == pin) {
805dc626f8SMasahiro Yamada 			unsigned int iectrl;
815dc626f8SMasahiro Yamada 			u32 tmp;
825dc626f8SMasahiro Yamada 
835dc626f8SMasahiro Yamada 			iectrl = uniphier_pin_get_iectrl(pins[i].data);
845dc626f8SMasahiro Yamada 			tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
855dc626f8SMasahiro Yamada 			tmp |= 1 << iectrl;
865dc626f8SMasahiro Yamada 			writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
875dc626f8SMasahiro Yamada 		}
885dc626f8SMasahiro Yamada 	}
895dc626f8SMasahiro Yamada }
905dc626f8SMasahiro Yamada 
913b05b5f0SMasahiro Yamada static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
923b05b5f0SMasahiro Yamada {
933b05b5f0SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
943b05b5f0SMasahiro Yamada 
953b05b5f0SMasahiro Yamada 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
963b05b5f0SMasahiro Yamada 		uniphier_pinconf_input_enable_perpin(dev, pin);
973b05b5f0SMasahiro Yamada 	else
983b05b5f0SMasahiro Yamada 		uniphier_pinconf_input_enable_legacy(dev, pin);
993b05b5f0SMasahiro Yamada }
1003b05b5f0SMasahiro Yamada 
1015dc626f8SMasahiro Yamada static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
1025e25b9d5SMasahiro Yamada 				    int muxval)
1035dc626f8SMasahiro Yamada {
1045dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
1058cc92b99SMasahiro Yamada 	unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
1068cc92b99SMasahiro Yamada 	bool load_pinctrl;
1075dc626f8SMasahiro Yamada 	u32 tmp;
1085dc626f8SMasahiro Yamada 
109fdd15b6aSMasahiro Yamada 	/* some pins need input-enabling */
110fdd15b6aSMasahiro Yamada 	uniphier_pinconf_input_enable(dev, pin);
111fdd15b6aSMasahiro Yamada 
1125e25b9d5SMasahiro Yamada 	if (muxval < 0)
1135e25b9d5SMasahiro Yamada 		return;		/* dedicated pin; nothing to do for pin-mux */
1145e25b9d5SMasahiro Yamada 
1158cc92b99SMasahiro Yamada 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
1168cc92b99SMasahiro Yamada 		/*
1178cc92b99SMasahiro Yamada 		 *  Mode       offset        bit
1188cc92b99SMasahiro Yamada 		 *  Normal     4 * n     shift+3:shift
1198cc92b99SMasahiro Yamada 		 *  Debug      4 * n     shift+7:shift+4
1208cc92b99SMasahiro Yamada 		 */
1218cc92b99SMasahiro Yamada 		mux_bits = 4;
1228cc92b99SMasahiro Yamada 		reg_stride = 8;
1238cc92b99SMasahiro Yamada 		load_pinctrl = true;
1248cc92b99SMasahiro Yamada 	} else {
1258cc92b99SMasahiro Yamada 		/*
1268cc92b99SMasahiro Yamada 		 *  Mode       offset           bit
1278cc92b99SMasahiro Yamada 		 *  Normal     8 * n        shift+3:shift
1288cc92b99SMasahiro Yamada 		 *  Debug      8 * n + 4    shift+3:shift
1298cc92b99SMasahiro Yamada 		 */
1308cc92b99SMasahiro Yamada 		mux_bits = 8;
1318cc92b99SMasahiro Yamada 		reg_stride = 4;
1328cc92b99SMasahiro Yamada 		load_pinctrl = false;
1338cc92b99SMasahiro Yamada 	}
1348cc92b99SMasahiro Yamada 
1355dc626f8SMasahiro Yamada 	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
1365dc626f8SMasahiro Yamada 	reg_end = reg + reg_stride;
1375dc626f8SMasahiro Yamada 	shift = pin * mux_bits % 32;
1385dc626f8SMasahiro Yamada 	mask = (1U << mux_bits) - 1;
1395dc626f8SMasahiro Yamada 
1405dc626f8SMasahiro Yamada 	/*
1415dc626f8SMasahiro Yamada 	 * If reg_stride is greater than 4, the MSB of each pinsel shall be
1425dc626f8SMasahiro Yamada 	 * stored in the offset+4.
1435dc626f8SMasahiro Yamada 	 */
1445dc626f8SMasahiro Yamada 	for (; reg < reg_end; reg += 4) {
1455dc626f8SMasahiro Yamada 		tmp = readl(priv->base + reg);
1465dc626f8SMasahiro Yamada 		tmp &= ~(mask << shift);
1475dc626f8SMasahiro Yamada 		tmp |= (mask & muxval) << shift;
1485dc626f8SMasahiro Yamada 		writel(tmp, priv->base + reg);
1495dc626f8SMasahiro Yamada 
1505dc626f8SMasahiro Yamada 		muxval >>= mux_bits;
1515dc626f8SMasahiro Yamada 	}
1525dc626f8SMasahiro Yamada 
1538cc92b99SMasahiro Yamada 	if (load_pinctrl)
1545dc626f8SMasahiro Yamada 		writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
1555dc626f8SMasahiro Yamada }
1565dc626f8SMasahiro Yamada 
1575dc626f8SMasahiro Yamada static int uniphier_pinmux_group_set(struct udevice *dev,
1585dc626f8SMasahiro Yamada 				     unsigned group_selector,
1595dc626f8SMasahiro Yamada 				     unsigned func_selector)
1605dc626f8SMasahiro Yamada {
1615dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
1625dc626f8SMasahiro Yamada 	const struct uniphier_pinctrl_group *grp =
1635dc626f8SMasahiro Yamada 					&priv->socdata->groups[group_selector];
1645dc626f8SMasahiro Yamada 	int i;
1655dc626f8SMasahiro Yamada 
1665dc626f8SMasahiro Yamada 	for (i = 0; i < grp->num_pins; i++)
1675dc626f8SMasahiro Yamada 		uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
1685dc626f8SMasahiro Yamada 
1695dc626f8SMasahiro Yamada 	return 0;
1705dc626f8SMasahiro Yamada }
1715dc626f8SMasahiro Yamada 
1725dc626f8SMasahiro Yamada const struct pinctrl_ops uniphier_pinctrl_ops = {
1735dc626f8SMasahiro Yamada 	.get_groups_count = uniphier_pinctrl_get_groups_count,
1745dc626f8SMasahiro Yamada 	.get_group_name = uniphier_pinctrl_get_group_name,
1755dc626f8SMasahiro Yamada 	.get_functions_count = uniphier_pinmux_get_functions_count,
1765dc626f8SMasahiro Yamada 	.get_function_name = uniphier_pinmux_get_function_name,
1775dc626f8SMasahiro Yamada 	.pinmux_group_set = uniphier_pinmux_group_set,
1785dc626f8SMasahiro Yamada 	.set_state = pinctrl_generic_set_state,
1795dc626f8SMasahiro Yamada };
1805dc626f8SMasahiro Yamada 
1815dc626f8SMasahiro Yamada int uniphier_pinctrl_probe(struct udevice *dev,
1825dc626f8SMasahiro Yamada 			   struct uniphier_pinctrl_socdata *socdata)
1835dc626f8SMasahiro Yamada {
1845dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
1855dc626f8SMasahiro Yamada 	fdt_addr_t addr;
1865dc626f8SMasahiro Yamada 
187186c1334SMasahiro Yamada 	addr = dev_get_addr(dev->parent);
1885dc626f8SMasahiro Yamada 	if (addr == FDT_ADDR_T_NONE)
1895dc626f8SMasahiro Yamada 		return -EINVAL;
1905dc626f8SMasahiro Yamada 
191510454dbSMasahiro Yamada 	priv->base = map_sysmem(addr, SZ_4K);
1925dc626f8SMasahiro Yamada 	if (!priv->base)
1935dc626f8SMasahiro Yamada 		return -ENOMEM;
1945dc626f8SMasahiro Yamada 
1955dc626f8SMasahiro Yamada 	priv->socdata = socdata;
1965dc626f8SMasahiro Yamada 
1975dc626f8SMasahiro Yamada 	return 0;
1985dc626f8SMasahiro Yamada }
1995dc626f8SMasahiro Yamada 
2005dc626f8SMasahiro Yamada int uniphier_pinctrl_remove(struct udevice *dev)
2015dc626f8SMasahiro Yamada {
2025dc626f8SMasahiro Yamada 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
2035dc626f8SMasahiro Yamada 
2045dc626f8SMasahiro Yamada 	unmap_sysmem(priv->base);
2055dc626f8SMasahiro Yamada 
2065dc626f8SMasahiro Yamada 	return 0;
2075dc626f8SMasahiro Yamada }
208