mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/2] tegra20: add pinctrl driver
@ 2013-05-06 14:56 Lucas Stach
  2013-05-06 14:56 ` [PATCH 2/2] tegra: paz00: import pinconfig from Linux Lucas Stach
  2013-05-06 15:27 ` [PATCH 1/2] tegra20: add pinctrl driver Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 2 replies; 6+ messages in thread
From: Lucas Stach @ 2013-05-06 14:56 UTC (permalink / raw)
  To: barebox

This adds a pinctrl driver for the Tegra 20 line of SoCs. It only
supports the three basic pinconfiguration settings function mux,
tristate control and pullup/down control.

The driver understands the same devicetree bindings as the Linux one,
unimplemented pinconfiguration options will be ignored.

Signed-off-by: Lucas Stach <dev@lynxeye.de>
---
 arch/arm/dts/tegra20.dtsi         |   8 +
 drivers/pinctrl/Kconfig           |   6 +
 drivers/pinctrl/Makefile          |   1 +
 drivers/pinctrl/pinctrl-tegra20.c | 336 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 351 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-tegra20.c

diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
index b7d1e27..f63ead8 100644
--- a/arch/arm/dts/tegra20.dtsi
+++ b/arch/arm/dts/tegra20.dtsi
@@ -34,6 +34,14 @@
 		interrupt-controller;
 	};
 
+	pinmux: pinmux {
+	compatible = "nvidia,tegra20-pinmux";
+	reg = <0x70000014 0x10   /* Tri-state registers */
+	       0x70000080 0x20   /* Mux registers */
+	       0x700000a0 0x14   /* Pull-up/down registers */
+	       0x70000868 0xa8>; /* Pad control registers */
+	};
+
 	pmc {
 		compatible = "nvidia,tegra20-pmc";
 		reg = <0x7000e400 0x400>;
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index e6aee50..0b859b8 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -25,4 +25,10 @@ config PINCTRL_IMX_IOMUX_V3
 	help
 	  This iomux controller is found on i.MX25,35,51,53,6.
 
+config PINCTRL_TEGRA20
+	select PINCTRL
+	bool "Tegra 20 pinmux"
+	help
+	  The pinmux controller found on the Tegra 20 line of SoCs.
+
 endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index e9272d0..169ed18 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL)	+= pinctrl.o
 obj-$(CONFIG_PINCTRL_IMX_IOMUX_V1) += imx-iomux-v1.o
 obj-$(CONFIG_PINCTRL_IMX_IOMUX_V2) += imx-iomux-v2.o
 obj-$(CONFIG_PINCTRL_IMX_IOMUX_V3) += imx-iomux-v3.o
+obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
new file mode 100644
index 0000000..44a4a0c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-tegra20.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * Partly based on code
+ * Copyright (C) 2011-2012 NVIDIA Corporation <www.nvidia.com>
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ * @brief Device driver for the Tegra 20 pincontrol hardware module.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <pinctrl.h>
+#include <malloc.h>
+
+struct pinctrl_tegra20 {
+	void __iomem *regs[3];
+	struct pinctrl_device pinctrl;
+};
+
+struct tegra20_pingroup {
+	const char *name;
+	const char *funcs[4];
+	s16 trictrl_id;
+	s16 muxctrl_id;
+	s16 pullctrl_id;
+};
+
+#define PG(pg_name, f0, f1, f2, f3, tri, mux, pull)	\
+	{						\
+		.name = #pg_name,			\
+		.funcs = { #f0, #f1, #f2, #f3, },	\
+		.trictrl_id = tri,			\
+		.muxctrl_id = mux,			\
+		.pullctrl_id = pull			\
+	}
+
+static const struct tegra20_pingroup tegra20_groups[] = {
+	/* name,   f0,        f1,        f2,        f3,            tri,     mux,     pull */
+	PG(ata,    ide,       nand,      gmi,       rsvd4,         0,       12,      0  ),
+	PG(atb,    ide,       nand,      gmi,       sdio4,         1,       8,       1  ),
+	PG(atc,    ide,       nand,      gmi,       sdio4,         2,       11,      2  ),
+	PG(atd,    ide,       nand,      gmi,       sdio4,         3,       10,      3  ),
+	PG(ate,    ide,       nand,      gmi,       rsvd4,         57,      6,       4  ),
+	PG(cdev1,  osc,       plla_out,  pllm_out1, audio_sync,    4,       33,      32 ),
+	PG(cdev2,  osc,       ahb_clk,   apb_clk,   pllp_out4,     5,       34,      33 ),
+	PG(crtp,   crt,       rsvd2,     rsvd3,     rsvd4,         110,     105,     28 ),
+	PG(csus,   pllc_out1, pllp_out2, pllp_out3, vi_sensor_clk, 6,       35,      60 ),
+	PG(dap1,   dap1,      rsvd2,     gmi,       sdio2,         7,       42,      5  ),
+	PG(dap2,   dap2,      twc,       rsvd3,     gmi,           8,       43,      6  ),
+	PG(dap3,   dap3,      rsvd2,     rsvd3,     rsvd4,         9,       44,      7  ),
+	PG(dap4,   dap4,      rsvd2,     gmi,       rsvd4,         10,      45,      8  ),
+	PG(ddc,    i2c2,      rsvd2,     rsvd3,     rsvd4,         63,      32,      78 ),
+	PG(dta,    rsvd1,     sdio2,     vi,        rsvd4,         11,      26,      9  ),
+	PG(dtb,    rsvd1,     rsvd2,     vi,        spi1,          12,      27,      10 ),
+	PG(dtc,    rsvd1,     rsvd2,     vi,        rsvd4,         13,      29,      11 ),
+	PG(dtd,    rsvd1,     sdio2,     vi,        rsvd4,         14,      30,      12 ),
+	PG(dte,    rsvd1,     rsvd2,     vi,        spi1,          15,      31,      13 ),
+	PG(dtf,    i2c3,      rsvd2,     vi,        rsvd4,         108,     110,     14 ),
+	PG(gma,    uarte,     spi3,      gmi,       sdio4,         28,      16,      74 ),
+	PG(gmb,    ide,       nand,      gmi,       gmi_int,       61,      46,      75 ),
+	PG(gmc,    uartd,     spi4,      gmi,       sflash,        29,      17,      76 ),
+	PG(gmd,    rsvd1,     nand,      gmi,       sflash,        62,      47,      77 ),
+	PG(gme,    rsvd1,     dap5,      gmi,       sdio4,         32,      48,      44 ),
+	PG(gpu,    pwm,       uarta,     gmi,       rsvd4,         16,      50,      26 ),
+	PG(gpu7,   rtck,      rsvd2,     rsvd3,     rsvd4,         107,     109,     19 ),
+	PG(gpv,    pcie,      rsvd2,     rsvd3,     rsvd4,         17,      49,      15 ),
+	PG(hdint,  hdmi,      rsvd2,     rsvd3,     rsvd4,         87,      18,      -1 ),
+	PG(i2cp,   i2cp,      rsvd2,     rsvd3,     rsvd4,         18,      36,      17 ),
+	PG(irrx,   uarta,     uartb,     gmi,       spi4,          20,      41,      43 ),
+	PG(irtx,   uarta,     uartb,     gmi,       spi4,          19,      40,      42 ),
+	PG(kbca,   kbc,       nand,      sdio2,     emc_test0_dll, 22,      37,      20 ),
+	PG(kbcb,   kbc,       nand,      sdio2,     mio,           21,      38,      21 ),
+	PG(kbcc,   kbc,       nand,      trace,     emc_test1_dll, 58,      39,      22 ),
+	PG(kbcd,   kbc,       nand,      sdio2,     mio,           106,     108,     23 ),
+	PG(kbce,   kbc,       nand,      owr,       rsvd4,         26,      14,      65 ),
+	PG(kbcf,   kbc,       nand,      trace,     mio,           27,      13,      64 ),
+	PG(lcsn,   displaya,  displayb,  spi3,      rsvd4,         95,      70,      -1 ),
+	PG(ld0,    displaya,  displayb,  xio,       rsvd4,         64,      80,      -1 ),
+	PG(ld1,    displaya,  displayb,  xio,       rsvd4,         65,      81,      -1 ),
+	PG(ld2,    displaya,  displayb,  xio,       rsvd4,         66,      82,      -1 ),
+	PG(ld3,    displaya,  displayb,  xio,       rsvd4,         67,      83,      -1 ),
+	PG(ld4,    displaya,  displayb,  xio,       rsvd4,         68,      84,      -1 ),
+	PG(ld5,    displaya,  displayb,  xio,       rsvd4,         69,      85,      -1 ),
+	PG(ld6,    displaya,  displayb,  xio,       rsvd4,         70,      86,      -1 ),
+	PG(ld7,    displaya,  displayb,  xio,       rsvd4,         71,      87,      -1 ),
+	PG(ld8,    displaya,  displayb,  xio,       rsvd4,         72,      88,      -1 ),
+	PG(ld9,    displaya,  displayb,  xio,       rsvd4,         73,      89,      -1 ),
+	PG(ld10,   displaya,  displayb,  xio,       rsvd4,         74,      90,      -1 ),
+	PG(ld11,   displaya,  displayb,  xio,       rsvd4,         75,      91,      -1 ),
+	PG(ld12,   displaya,  displayb,  xio,       rsvd4,         76,      92,      -1 ),
+	PG(ld13,   displaya,  displayb,  xio,       rsvd4,         77,      93,      -1 ),
+	PG(ld14,   displaya,  displayb,  xio,       rsvd4,         78,      94,      -1 ),
+	PG(ld15,   displaya,  displayb,  xio,       rsvd4,         79,      95,      -1 ),
+	PG(ld16,   displaya,  displayb,  xio,       rsvd4,         80,      96,      -1 ),
+	PG(ld17,   displaya,  displayb,  rsvd3,     rsvd4,         81,      97,      -1 ),
+	PG(ldc,    displaya,  displayb,  rsvd3,     rsvd4,         94,      71,      -1 ),
+	PG(ldi,    displaya,  displayb,  rsvd3,     rsvd4,         102,     104,     -1 ),
+	PG(lhp0,   displaya,  displayb,  rsvd3,     rsvd4,         82,      101,     -1 ),
+	PG(lhp1,   displaya,  displayb,  rsvd3,     rsvd4,         83,      98,      -1 ),
+	PG(lhp2,   displaya,  displayb,  rsvd3,     rsvd4,         84,      99,      -1 ),
+	PG(lhs,    displaya,  displayb,  xio,       rsvd4,         103,     75,      -1 ),
+	PG(lm0,    displaya,  displayb,  spi3,      rsvd4,         88,      77,      -1 ),
+	PG(lm1,    displaya,  displayb,  rsvd3,     CRT,           89,      78,      -1 ),
+	PG(lpp,    displaya,  displayb,  rsvd3,     rsvd4,         104,     103,     -1 ),
+	PG(lpw0,   displaya,  displayb,  spi3,      hdmi,          99,      64,      -1 ),
+	PG(lpw1,   displaya,  displayb,  rsvd3,     rsvd4,         100,     65,      -1 ),
+	PG(lpw2,   displaya,  displayb,  spi3,      hdmi,          101,     66,      -1 ),
+	PG(lsc0,   displaya,  displayb,  xio,       rsvd4,         91,      73,      -1 ),
+	PG(lsc1,   displaya,  displayb,  spi3,      hdmi,          92,      74,      -1 ),
+	PG(lsck,   displaya,  displayb,  spi3,      hdmi,          93,      72,      -1 ),
+	PG(lsda,   displaya,  displayb,  spi3,      hdmi,          97,      68,      -1 ),
+	PG(lsdi,   displaya,  displayb,  spi3,      rsvd4,         98,      67,      -1 ),
+	PG(lspi,   displaya,  displayb,  xio,       hdmi,          96,      69,      -1 ),
+	PG(lvp0,   displaya,  displayb,  rsvd3,     rsvd4,         85,      79,      -1 ),
+	PG(lvp1,   displaya,  displayb,  rsvd3,     rsvd4,         86,      100,     -1 ),
+	PG(lvs,    displaya,  displayb,  xio,       rsvd4,         90,      76,      -1 ),
+	PG(owc,    owr,       rsvd2,     rsvd3,     rsvd4,         31,      20,      79 ),
+	PG(pmc,    pwr_on,    pwr_intr,  rsvd3,     rsvd4,         23,      105,     -1 ),
+	PG(pta,    i2c2,      hdmi,      gmi,       rsvd4,         24,      107,     18 ),
+	PG(rm,     i2c1,      rsvd2,     rsvd3,     rsvd4,         25,      7,       16 ),
+	PG(sdb,    uarta,     pwm,       sdio3,     spi2,          111,     53,      -1 ),
+	PG(sdc,    pwm,       twc,       sdio3,     spi3,          33,      54,      62 ),
+	PG(sdd,    uarta,     pwm,       sdio3,     spi3,          34,      55,      63 ),
+	PG(sdio1,  sdio1,     rsvd2,     uarte,     uarta,         30,      15,      73 ),
+	PG(slxa,   pcie,      spi4,      sdio3,     spi2,          36,      19,      27 ),
+	PG(slxc,   spdif,     spi4,      sdio3,     spi2,          37,      21,      29 ),
+	PG(slxd,   spdif,     spi4,      sdio3,     spi2,          38,      22,      30 ),
+	PG(slxk,   pcie,      spi4,      sdio3,     spi2,          39,      23,      31 ),
+	PG(spdi,   spdif,     rsvd2,     i2c1,      sdio2,         40,      52,      24 ),
+	PG(spdo,   spdif,     rsvd2,     i2c1,      sdio2,         41,      51,      25 ),
+	PG(spia,   spi1,      spi2,      spi3,      gmi,           42,      63,      34 ),
+	PG(spib,   spi1,      spi2,      spi3,      gmi,           43,      62,      35 ),
+	PG(spic,   spi1,      spi2,      spi3,      gmi,           44,      61,      36 ),
+	PG(spid,   spi2,      spi1,      spi2_alt,  gmi,           45,      60,      37 ),
+	PG(spie,   spi2,      spi1,      spi2_alt,  gmi,           46,      59,      38 ),
+	PG(spif,   spi3,      spi1,      spi2,      rsvd4,         47,      58,      39 ),
+	PG(spig,   spi3,      spi2,      spi2_alt,  i2c1,          48,      57,      40 ),
+	PG(spih,   spi3,      spi2,      spi2_alt,  i2c1,          49,      56,      41 ),
+	PG(uaa,    spi3,      mipi_hs,   uarta,     ulpi,          50,      0,       48 ),
+	PG(uab,    spi2,      mipi_hs,   uarta,     ulpi,          51,      1,       49 ),
+	PG(uac,    owr,       rsvd2,     rsvd3,     rsvd4,         52,      2,       50 ),
+	PG(uad,    irda,      spdif,     uarta,     spi4,          53,      3,       51 ),
+	PG(uca,    uartc,     rsvd2,     gmi,       rsvd4,         54,      24,      52 ),
+	PG(ucb,    uartc,     pwm,       gmi,       rsvd4,         55,      25,      53 ),
+	PG(uda,    spi1,      rsvd2,     uartd,     ulpi,          109,     4,       72 ),
+};
+
+static void pinctrl_tegra20_set_func(struct pinctrl_tegra20 *ctrl,
+				     int muxctrl_id, int func)
+{
+	u32 *regaddr = ctrl->regs[1];
+	u32 reg;
+	int maskbit;
+
+	regaddr += muxctrl_id >> 4;
+	maskbit = (muxctrl_id << 1) & 0x1f;
+
+	reg = readl(regaddr);
+	reg &= ~(0x3 << maskbit);
+	reg |= func << maskbit;
+	writel(reg, regaddr);
+}
+
+static void pinctrl_tegra20_set_pull(struct pinctrl_tegra20 *ctrl,
+				     int pullctrl_id, int pull)
+{
+	u32 *regaddr = ctrl->regs[2];
+	u32 reg;
+	int maskbit;
+
+	regaddr += pullctrl_id >> 4;
+	maskbit = (pullctrl_id << 1) & 0x1f;
+
+	reg = readl(regaddr);
+	reg &= ~(0x3 << maskbit);
+	reg |= pull << maskbit;
+	writel(reg, regaddr);
+}
+
+static void pinctrl_tegra20_set_tristate(struct pinctrl_tegra20 *ctrl,
+					 int trictrl_id, int tristate)
+{
+	u32 *regaddr = ctrl->regs[0];
+	u32 reg;
+	int maskbit;
+
+	regaddr += trictrl_id >> 5;
+	maskbit = trictrl_id & 0x1f;
+
+	reg = readl(regaddr);
+	reg &= ~(1 << maskbit);
+	reg |= tristate << maskbit;
+	writel(reg, regaddr);
+}
+
+static int pinctrl_tegra20_set_state(struct pinctrl_device *pdev,
+				     struct device_node *np)
+{
+	struct pinctrl_tegra20 *ctrl =
+			container_of(pdev, struct pinctrl_tegra20, pinctrl);
+	struct device_node *childnode;
+	int pull = -1, tri = -1, i, j, k;
+	const char *pins, *func = NULL;
+	const struct tegra20_pingroup *group;
+
+	/*
+	 * At first look if the node we are pointed at has children,
+	 * which we may want to visit.
+	 */
+	list_for_each_entry(childnode, &np->children, parent_list)
+		pinctrl_tegra20_set_state(pdev, childnode);
+
+	/* read relevant state from devicetree */
+	of_property_read_string(np, "nvidia,function", &func);
+	of_property_read_u32_array(np, "nvidia,pull", &pull, 1);
+	of_property_read_u32_array(np, "nvidia,tristate", &tri, 1);
+
+	/* iterate over all pingroups referenced in the dt node */
+	for (i = 0; ; i++) {
+		if (of_property_read_string_index(np, "nvidia,pins", i, &pins))
+			break;
+
+		for (j = 0; j < ARRAY_SIZE(tegra20_groups); j++) {
+			if (!strcmp(pins, tegra20_groups[j].name)) {
+				group = &tegra20_groups[j];
+				break;
+			}
+		}
+		/* if no matching pingroup is found bail out */
+		if (j == ARRAY_SIZE(tegra20_groups)) {
+			dev_warn(ctrl->pinctrl.dev,
+				 "invalid pingroup %s referenced in node %s\n",
+				 pins, np->name);
+			continue;
+		}
+
+		if (func) {
+			for (k = 0; k < 4; k++) {
+				if (!strcmp(func, group->funcs[k]))
+					break;
+			}
+			if (k < 4)
+				pinctrl_tegra20_set_func(ctrl,
+							 group->muxctrl_id, k);
+			else
+				dev_warn(ctrl->pinctrl.dev,
+					 "invalid function %s for pingroup %s in node %s\n",
+					 func, group->name, np->name);
+		}
+
+		if (pull >= 0) {
+			if (group->pullctrl_id >= 0)
+				pinctrl_tegra20_set_pull(ctrl,
+							 group->pullctrl_id,
+							 pull);
+			else
+				dev_warn(ctrl->pinctrl.dev,
+					 "pingroup %s in node %s doesn't support pull configuration\n",
+					 group->name, np->name);
+		}
+
+		if (tri >= 0)
+			pinctrl_tegra20_set_tristate(ctrl,
+						     group->trictrl_id, tri);
+	}
+
+	return 0;
+}
+
+static struct pinctrl_ops pinctrl_tegra20_ops = {
+	.set_state = pinctrl_tegra20_set_state,
+};
+
+static int pinctrl_tegra20_probe(struct device_d *dev)
+{
+	struct pinctrl_tegra20 *ctrl;
+	int i, ret = 0;
+
+	ctrl = xzalloc(sizeof(*ctrl));
+
+	/*
+	 * Tegra pincontrol is split out into four independent memory ranges:
+	 * tristate control, function mux, pullup/down control, pad control
+	 * (from lowest to highest hardware address).
+	 * We are only interested in the first three for now.
+	 */
+	for (i = 0; i <= 2; i++) {
+		ctrl->regs[i] = dev_request_mem_region(dev, i);
+	}
+
+	ctrl->pinctrl.dev = dev;
+	ctrl->pinctrl.ops = &pinctrl_tegra20_ops;
+
+	ret = pinctrl_register(&ctrl->pinctrl);
+	if (ret)
+		free(ctrl);
+
+	return ret;
+}
+
+static __maybe_unused struct of_device_id pinctrl_tegra20_dt_ids[] = {
+	{
+		.compatible = "nvidia,tegra20-pinmux",
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct driver_d pinctrl_tegra20_driver = {
+	.name		= "pinctrl-tegra20",
+	.probe		= pinctrl_tegra20_probe,
+	.of_compatible	= DRV_OF_COMPAT(pinctrl_tegra20_dt_ids),
+};
+
+static int pinctrl_tegra20_init(void)
+{
+	return platform_driver_register(&pinctrl_tegra20_driver);
+}
+postcore_initcall(pinctrl_tegra20_init);
-- 
1.8.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/2] tegra: paz00: import pinconfig from Linux
  2013-05-06 14:56 [PATCH 1/2] tegra20: add pinctrl driver Lucas Stach
@ 2013-05-06 14:56 ` Lucas Stach
  2013-05-06 15:27 ` [PATCH 1/2] tegra20: add pinctrl driver Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 6+ messages in thread
From: Lucas Stach @ 2013-05-06 14:56 UTC (permalink / raw)
  To: barebox

Signed-off-by: Lucas Stach <dev@lynxeye.de>
---
 arch/arm/dts/tegra20-paz00.dts | 216 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 216 insertions(+)

diff --git a/arch/arm/dts/tegra20-paz00.dts b/arch/arm/dts/tegra20-paz00.dts
index 09ccb8b..e8486aa 100644
--- a/arch/arm/dts/tegra20-paz00.dts
+++ b/arch/arm/dts/tegra20-paz00.dts
@@ -9,4 +9,220 @@
 	memory {
 		reg = <0x00000000 0x20000000>;
 	};
+
+	pinmux {
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux {
+			ata {
+				nvidia,pins = "ata", "atc", "atd", "ate",
+					"dap2", "gmb", "gmc", "gmd", "spia",
+					"spib", "spic", "spid", "spie";
+				nvidia,function = "gmi";
+			};
+			atb {
+				nvidia,pins = "atb", "gma", "gme";
+				nvidia,function = "sdio4";
+			};
+			cdev1 {
+				nvidia,pins = "cdev1";
+				nvidia,function = "plla_out";
+			};
+			cdev2 {
+				nvidia,pins = "cdev2";
+				nvidia,function = "pllp_out4";
+			};
+			crtp {
+				nvidia,pins = "crtp";
+				nvidia,function = "crt";
+			};
+			csus {
+				nvidia,pins = "csus";
+				nvidia,function = "pllc_out1";
+			};
+			dap1 {
+				nvidia,pins = "dap1";
+				nvidia,function = "dap1";
+			};
+			dap3 {
+				nvidia,pins = "dap3";
+				nvidia,function = "dap3";
+			};
+			dap4 {
+				nvidia,pins = "dap4";
+				nvidia,function = "dap4";
+			};
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "i2c2";
+			};
+			dta {
+				nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+				nvidia,function = "rsvd1";
+			};
+			dtf {
+				nvidia,pins = "dtf";
+				nvidia,function = "i2c3";
+			};
+			gpu {
+				nvidia,pins = "gpu", "sdb", "sdd";
+				nvidia,function = "pwm";
+			};
+			gpu7 {
+				nvidia,pins = "gpu7";
+				nvidia,function = "rtck";
+			};
+			gpv {
+				nvidia,pins = "gpv", "slxa", "slxk";
+				nvidia,function = "pcie";
+			};
+			hdint {
+				nvidia,pins = "hdint", "pta";
+				nvidia,function = "hdmi";
+			};
+			i2cp {
+				nvidia,pins = "i2cp";
+				nvidia,function = "i2cp";
+			};
+			irrx {
+				nvidia,pins = "irrx", "irtx";
+				nvidia,function = "uarta";
+			};
+			kbca {
+				nvidia,pins = "kbca", "kbcc", "kbce", "kbcf";
+				nvidia,function = "kbc";
+			};
+			kbcb {
+				nvidia,pins = "kbcb", "kbcd";
+				nvidia,function = "sdio2";
+			};
+			lcsn {
+				nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+					"ld3", "ld4", "ld5", "ld6", "ld7",
+					"ld8", "ld9", "ld10", "ld11", "ld12",
+					"ld13", "ld14", "ld15", "ld16", "ld17",
+					"ldc", "ldi", "lhp0", "lhp1", "lhp2",
+					"lhs", "lm0", "lm1", "lpp", "lpw0",
+					"lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+					"lsda", "lsdi", "lspi", "lvp0", "lvp1",
+					"lvs";
+				nvidia,function = "displaya";
+			};
+			owc {
+				nvidia,pins = "owc";
+				nvidia,function = "owr";
+			};
+			pmc {
+				nvidia,pins = "pmc";
+				nvidia,function = "pwr_on";
+			};
+			rm {
+				nvidia,pins = "rm";
+				nvidia,function = "i2c1";
+			};
+			sdc {
+				nvidia,pins = "sdc";
+				nvidia,function = "twc";
+			};
+			sdio1 {
+				nvidia,pins = "sdio1";
+				nvidia,function = "sdio1";
+			};
+			slxc {
+				nvidia,pins = "slxc", "slxd";
+				nvidia,function = "spi4";
+			};
+			spdi {
+				nvidia,pins = "spdi", "spdo";
+				nvidia,function = "rsvd2";
+			};
+			spif {
+				nvidia,pins = "spif", "uac";
+				nvidia,function = "rsvd4";
+			};
+			spig {
+				nvidia,pins = "spig", "spih";
+				nvidia,function = "spi2_alt";
+			};
+			uaa {
+				nvidia,pins = "uaa", "uab", "uda";
+				nvidia,function = "ulpi";
+			};
+			uad {
+				nvidia,pins = "uad";
+				nvidia,function = "spdif";
+			};
+			uca {
+				nvidia,pins = "uca", "ucb";
+				nvidia,function = "uartc";
+			};
+			conf_ata {
+				nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+					"cdev1", "cdev2", "dap1", "dap2", "dtf",
+					"gma", "gmb", "gmc", "gmd", "gme",
+					"gpu", "gpu7", "gpv", "i2cp", "pta",
+					"rm", "sdio1", "slxk", "spdo", "uac",
+					"uda";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+			};
+			conf_ck32 {
+				nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+					"pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+				nvidia,pull = <0>;
+			};
+			conf_crtp {
+				nvidia,pins = "crtp", "dap3", "dap4", "dtb",
+					"dtc", "dte", "slxa", "slxc", "slxd",
+					"spdi";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+			};
+			conf_csus {
+				nvidia,pins = "csus", "spia", "spib", "spid",
+					"spif";
+				nvidia,pull = <1>;
+				nvidia,tristate = <1>;
+			};
+			conf_ddc {
+				nvidia,pins = "ddc", "irrx", "irtx", "kbca",
+					"kbcb", "kbcc", "kbcd", "kbce", "kbcf",
+					"spic", "spig", "uaa", "uab";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+			};
+			conf_dta {
+				nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd",
+					"spie", "spih", "uad", "uca", "ucb";
+				nvidia,pull = <2>;
+				nvidia,tristate = <1>;
+			};
+			conf_hdint {
+				nvidia,pins = "hdint", "ld0", "ld1", "ld2",
+					"ld3", "ld4", "ld5", "ld6", "ld7",
+					"ld8", "ld9", "ld10", "ld11", "ld12",
+					"ld13", "ld14", "ld15", "ld16", "ld17",
+					"ldc", "ldi", "lhs", "lsc0", "lspi",
+					"lvs", "pmc";
+				nvidia,tristate = <0>;
+			};
+			conf_lc {
+				nvidia,pins = "lc", "ls";
+				nvidia,pull = <2>;
+			};
+			conf_lcsn {
+				nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2",
+					"lm0", "lm1", "lpp", "lpw0", "lpw1",
+					"lpw2", "lsc1", "lsck", "lsda", "lsdi",
+					"lvp0", "lvp1", "sdb";
+				nvidia,tristate = <1>;
+			};
+			conf_ld17_0 {
+				nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+					"ld23_22";
+				nvidia,pull = <1>;
+			};
+		};
+	};
 };
-- 
1.8.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] tegra20: add pinctrl driver
  2013-05-06 14:56 [PATCH 1/2] tegra20: add pinctrl driver Lucas Stach
  2013-05-06 14:56 ` [PATCH 2/2] tegra: paz00: import pinconfig from Linux Lucas Stach
@ 2013-05-06 15:27 ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-06 19:59   ` Sascha Hauer
  2013-05-08  6:28   ` Sascha Hauer
  1 sibling, 2 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-06 15:27 UTC (permalink / raw)
  To: Lucas Stach; +Cc: barebox

On 16:56 Mon 06 May     , Lucas Stach wrote:
> This adds a pinctrl driver for the Tegra 20 line of SoCs. It only
> supports the three basic pinconfiguration settings function mux,
> tristate control and pullup/down control.
> 
> The driver understands the same devicetree bindings as the Linux one,
> unimplemented pinconfiguration options will be ignored.
> 
> Signed-off-by: Lucas Stach <dev@lynxeye.de>
> ---
>  arch/arm/dts/tegra20.dtsi         |   8 +
>  drivers/pinctrl/Kconfig           |   6 +
>  drivers/pinctrl/Makefile          |   1 +
>  drivers/pinctrl/pinctrl-tegra20.c | 336 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 351 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl-tegra20.c
> 
> diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
> index b7d1e27..f63ead8 100644
> --- a/arch/arm/dts/tegra20.dtsi
> +++ b/arch/arm/dts/tegra20.dtsi
> @@ -34,6 +34,14 @@
>  		interrupt-controller;
>  	};
>  
> +	pinmux: pinmux {
> +	compatible = "nvidia,tegra20-pinmux";
> +	reg = <0x70000014 0x10   /* Tri-state registers */
> +	       0x70000080 0x20   /* Mux registers */
> +	       0x700000a0 0x14   /* Pull-up/down registers */
> +	       0x70000868 0xa8>; /* Pad control registers */
tab here
> +	};
> +
>  	pmc {
>  		compatible = "nvidia,tegra20-pmc";
>  		reg = <0x7000e400 0x400>;
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index e6aee50..0b859b8 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -25,4 +25,10 @@ config PINCTRL_IMX_IOMUX_V3
>  	help
>  	  This iomux controller is found on i.MX25,35,51,53,6.
>  
> +config PINCTRL_TEGRA20
> +	select PINCTRL
> +	bool "Tegra 20 pinmux"
> +	help
> +	  The pinmux controller found on the Tegra 20 line of SoCs.
pinctrl will be mandatory on tegra
> +
>  endmenu
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index e9272d0..169ed18 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL)	+= pinctrl.o
>  obj-$(CONFIG_PINCTRL_IMX_IOMUX_V1) += imx-iomux-v1.o
>  obj-$(CONFIG_PINCTRL_IMX_IOMUX_V2) += imx-iomux-v2.o
>  obj-$(CONFIG_PINCTRL_IMX_IOMUX_V3) += imx-iomux-v3.o
> +obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
> diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
> new file mode 100644
> index 0000000..44a4a0c
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-tegra20.c
> @@ -0,0 +1,336 @@
> +/*
> + * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
> + *
> + * Partly based on code
> + * Copyright (C) 2011-2012 NVIDIA Corporation <www.nvidia.com>
> + * Copyright (C) 2010 Google, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +/**
> + * @file
> + * @brief Device driver for the Tegra 20 pincontrol hardware module.
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <io.h>
> +#include <pinctrl.h>
> +#include <malloc.h>
> +
> +struct pinctrl_tegra20 {
> +	void __iomem *regs[3];
> +	struct pinctrl_device pinctrl;
> +};
> +
> +struct tegra20_pingroup {
> +	const char *name;
> +	const char *funcs[4];
> +	s16 trictrl_id;
> +	s16 muxctrl_id;
> +	s16 pullctrl_id;
> +};
> +
> +#define PG(pg_name, f0, f1, f2, f3, tri, mux, pull)	\
> +	{						\
> +		.name = #pg_name,			\
> +		.funcs = { #f0, #f1, #f2, #f3, },	\
> +		.trictrl_id = tri,			\
> +		.muxctrl_id = mux,			\
> +		.pullctrl_id = pull			\
> +	}
> +
> +static const struct tegra20_pingroup tegra20_groups[] = {
> +	/* name,   f0,        f1,        f2,        f3,            tri,     mux,     pull */
> +	PG(ata,    ide,       nand,      gmi,       rsvd4,         0,       12,      0  ),
> +	PG(atb,    ide,       nand,      gmi,       sdio4,         1,       8,       1  ),
> +	PG(atc,    ide,       nand,      gmi,       sdio4,         2,       11,      2  ),
> +	PG(atd,    ide,       nand,      gmi,       sdio4,         3,       10,      3  ),
> +	PG(ate,    ide,       nand,      gmi,       rsvd4,         57,      6,       4  ),
> +	PG(cdev1,  osc,       plla_out,  pllm_out1, audio_sync,    4,       33,      32 ),
> +	PG(cdev2,  osc,       ahb_clk,   apb_clk,   pllp_out4,     5,       34,      33 ),
> +	PG(crtp,   crt,       rsvd2,     rsvd3,     rsvd4,         110,     105,     28 ),
> +	PG(csus,   pllc_out1, pllp_out2, pllp_out3, vi_sensor_clk, 6,       35,      60 ),
> +	PG(dap1,   dap1,      rsvd2,     gmi,       sdio2,         7,       42,      5  ),
> +	PG(dap2,   dap2,      twc,       rsvd3,     gmi,           8,       43,      6  ),
> +	PG(dap3,   dap3,      rsvd2,     rsvd3,     rsvd4,         9,       44,      7  ),
> +	PG(dap4,   dap4,      rsvd2,     gmi,       rsvd4,         10,      45,      8  ),
> +	PG(ddc,    i2c2,      rsvd2,     rsvd3,     rsvd4,         63,      32,      78 ),
> +	PG(dta,    rsvd1,     sdio2,     vi,        rsvd4,         11,      26,      9  ),
> +	PG(dtb,    rsvd1,     rsvd2,     vi,        spi1,          12,      27,      10 ),
> +	PG(dtc,    rsvd1,     rsvd2,     vi,        rsvd4,         13,      29,      11 ),
> +	PG(dtd,    rsvd1,     sdio2,     vi,        rsvd4,         14,      30,      12 ),
> +	PG(dte,    rsvd1,     rsvd2,     vi,        spi1,          15,      31,      13 ),
> +	PG(dtf,    i2c3,      rsvd2,     vi,        rsvd4,         108,     110,     14 ),
> +	PG(gma,    uarte,     spi3,      gmi,       sdio4,         28,      16,      74 ),
> +	PG(gmb,    ide,       nand,      gmi,       gmi_int,       61,      46,      75 ),
> +	PG(gmc,    uartd,     spi4,      gmi,       sflash,        29,      17,      76 ),
> +	PG(gmd,    rsvd1,     nand,      gmi,       sflash,        62,      47,      77 ),
> +	PG(gme,    rsvd1,     dap5,      gmi,       sdio4,         32,      48,      44 ),
> +	PG(gpu,    pwm,       uarta,     gmi,       rsvd4,         16,      50,      26 ),
> +	PG(gpu7,   rtck,      rsvd2,     rsvd3,     rsvd4,         107,     109,     19 ),
> +	PG(gpv,    pcie,      rsvd2,     rsvd3,     rsvd4,         17,      49,      15 ),
> +	PG(hdint,  hdmi,      rsvd2,     rsvd3,     rsvd4,         87,      18,      -1 ),
> +	PG(i2cp,   i2cp,      rsvd2,     rsvd3,     rsvd4,         18,      36,      17 ),
> +	PG(irrx,   uarta,     uartb,     gmi,       spi4,          20,      41,      43 ),
> +	PG(irtx,   uarta,     uartb,     gmi,       spi4,          19,      40,      42 ),
> +	PG(kbca,   kbc,       nand,      sdio2,     emc_test0_dll, 22,      37,      20 ),
> +	PG(kbcb,   kbc,       nand,      sdio2,     mio,           21,      38,      21 ),
> +	PG(kbcc,   kbc,       nand,      trace,     emc_test1_dll, 58,      39,      22 ),
> +	PG(kbcd,   kbc,       nand,      sdio2,     mio,           106,     108,     23 ),
> +	PG(kbce,   kbc,       nand,      owr,       rsvd4,         26,      14,      65 ),
> +	PG(kbcf,   kbc,       nand,      trace,     mio,           27,      13,      64 ),
> +	PG(lcsn,   displaya,  displayb,  spi3,      rsvd4,         95,      70,      -1 ),
> +	PG(ld0,    displaya,  displayb,  xio,       rsvd4,         64,      80,      -1 ),
> +	PG(ld1,    displaya,  displayb,  xio,       rsvd4,         65,      81,      -1 ),
> +	PG(ld2,    displaya,  displayb,  xio,       rsvd4,         66,      82,      -1 ),
> +	PG(ld3,    displaya,  displayb,  xio,       rsvd4,         67,      83,      -1 ),
> +	PG(ld4,    displaya,  displayb,  xio,       rsvd4,         68,      84,      -1 ),
> +	PG(ld5,    displaya,  displayb,  xio,       rsvd4,         69,      85,      -1 ),
> +	PG(ld6,    displaya,  displayb,  xio,       rsvd4,         70,      86,      -1 ),
> +	PG(ld7,    displaya,  displayb,  xio,       rsvd4,         71,      87,      -1 ),
> +	PG(ld8,    displaya,  displayb,  xio,       rsvd4,         72,      88,      -1 ),
> +	PG(ld9,    displaya,  displayb,  xio,       rsvd4,         73,      89,      -1 ),
> +	PG(ld10,   displaya,  displayb,  xio,       rsvd4,         74,      90,      -1 ),
> +	PG(ld11,   displaya,  displayb,  xio,       rsvd4,         75,      91,      -1 ),
> +	PG(ld12,   displaya,  displayb,  xio,       rsvd4,         76,      92,      -1 ),
> +	PG(ld13,   displaya,  displayb,  xio,       rsvd4,         77,      93,      -1 ),
> +	PG(ld14,   displaya,  displayb,  xio,       rsvd4,         78,      94,      -1 ),
> +	PG(ld15,   displaya,  displayb,  xio,       rsvd4,         79,      95,      -1 ),
> +	PG(ld16,   displaya,  displayb,  xio,       rsvd4,         80,      96,      -1 ),
> +	PG(ld17,   displaya,  displayb,  rsvd3,     rsvd4,         81,      97,      -1 ),
> +	PG(ldc,    displaya,  displayb,  rsvd3,     rsvd4,         94,      71,      -1 ),
> +	PG(ldi,    displaya,  displayb,  rsvd3,     rsvd4,         102,     104,     -1 ),
> +	PG(lhp0,   displaya,  displayb,  rsvd3,     rsvd4,         82,      101,     -1 ),
> +	PG(lhp1,   displaya,  displayb,  rsvd3,     rsvd4,         83,      98,      -1 ),
> +	PG(lhp2,   displaya,  displayb,  rsvd3,     rsvd4,         84,      99,      -1 ),
> +	PG(lhs,    displaya,  displayb,  xio,       rsvd4,         103,     75,      -1 ),
> +	PG(lm0,    displaya,  displayb,  spi3,      rsvd4,         88,      77,      -1 ),
> +	PG(lm1,    displaya,  displayb,  rsvd3,     CRT,           89,      78,      -1 ),
> +	PG(lpp,    displaya,  displayb,  rsvd3,     rsvd4,         104,     103,     -1 ),
> +	PG(lpw0,   displaya,  displayb,  spi3,      hdmi,          99,      64,      -1 ),
> +	PG(lpw1,   displaya,  displayb,  rsvd3,     rsvd4,         100,     65,      -1 ),
> +	PG(lpw2,   displaya,  displayb,  spi3,      hdmi,          101,     66,      -1 ),
> +	PG(lsc0,   displaya,  displayb,  xio,       rsvd4,         91,      73,      -1 ),
> +	PG(lsc1,   displaya,  displayb,  spi3,      hdmi,          92,      74,      -1 ),
> +	PG(lsck,   displaya,  displayb,  spi3,      hdmi,          93,      72,      -1 ),
> +	PG(lsda,   displaya,  displayb,  spi3,      hdmi,          97,      68,      -1 ),
> +	PG(lsdi,   displaya,  displayb,  spi3,      rsvd4,         98,      67,      -1 ),
> +	PG(lspi,   displaya,  displayb,  xio,       hdmi,          96,      69,      -1 ),
> +	PG(lvp0,   displaya,  displayb,  rsvd3,     rsvd4,         85,      79,      -1 ),
> +	PG(lvp1,   displaya,  displayb,  rsvd3,     rsvd4,         86,      100,     -1 ),
> +	PG(lvs,    displaya,  displayb,  xio,       rsvd4,         90,      76,      -1 ),
> +	PG(owc,    owr,       rsvd2,     rsvd3,     rsvd4,         31,      20,      79 ),
> +	PG(pmc,    pwr_on,    pwr_intr,  rsvd3,     rsvd4,         23,      105,     -1 ),
> +	PG(pta,    i2c2,      hdmi,      gmi,       rsvd4,         24,      107,     18 ),
> +	PG(rm,     i2c1,      rsvd2,     rsvd3,     rsvd4,         25,      7,       16 ),
> +	PG(sdb,    uarta,     pwm,       sdio3,     spi2,          111,     53,      -1 ),
> +	PG(sdc,    pwm,       twc,       sdio3,     spi3,          33,      54,      62 ),
> +	PG(sdd,    uarta,     pwm,       sdio3,     spi3,          34,      55,      63 ),
> +	PG(sdio1,  sdio1,     rsvd2,     uarte,     uarta,         30,      15,      73 ),
> +	PG(slxa,   pcie,      spi4,      sdio3,     spi2,          36,      19,      27 ),
> +	PG(slxc,   spdif,     spi4,      sdio3,     spi2,          37,      21,      29 ),
> +	PG(slxd,   spdif,     spi4,      sdio3,     spi2,          38,      22,      30 ),
> +	PG(slxk,   pcie,      spi4,      sdio3,     spi2,          39,      23,      31 ),
> +	PG(spdi,   spdif,     rsvd2,     i2c1,      sdio2,         40,      52,      24 ),
> +	PG(spdo,   spdif,     rsvd2,     i2c1,      sdio2,         41,      51,      25 ),
> +	PG(spia,   spi1,      spi2,      spi3,      gmi,           42,      63,      34 ),
> +	PG(spib,   spi1,      spi2,      spi3,      gmi,           43,      62,      35 ),
> +	PG(spic,   spi1,      spi2,      spi3,      gmi,           44,      61,      36 ),
> +	PG(spid,   spi2,      spi1,      spi2_alt,  gmi,           45,      60,      37 ),
> +	PG(spie,   spi2,      spi1,      spi2_alt,  gmi,           46,      59,      38 ),
> +	PG(spif,   spi3,      spi1,      spi2,      rsvd4,         47,      58,      39 ),
> +	PG(spig,   spi3,      spi2,      spi2_alt,  i2c1,          48,      57,      40 ),
> +	PG(spih,   spi3,      spi2,      spi2_alt,  i2c1,          49,      56,      41 ),
> +	PG(uaa,    spi3,      mipi_hs,   uarta,     ulpi,          50,      0,       48 ),
> +	PG(uab,    spi2,      mipi_hs,   uarta,     ulpi,          51,      1,       49 ),
> +	PG(uac,    owr,       rsvd2,     rsvd3,     rsvd4,         52,      2,       50 ),
> +	PG(uad,    irda,      spdif,     uarta,     spi4,          53,      3,       51 ),
> +	PG(uca,    uartc,     rsvd2,     gmi,       rsvd4,         54,      24,      52 ),
> +	PG(ucb,    uartc,     pwm,       gmi,       rsvd4,         55,      25,      53 ),
> +	PG(uda,    spi1,      rsvd2,     uartd,     ulpi,          109,     4,       72 ),
> +};
really ugly blob but it's like tegra define so not choice
> +
> +static void pinctrl_tegra20_set_func(struct pinctrl_tegra20 *ctrl,
> +				     int muxctrl_id, int func)
> +{
> +	u32 *regaddr = ctrl->regs[1];
> +	u32 reg;
> +	int maskbit;
> +
> +	regaddr += muxctrl_id >> 4;
> +	maskbit = (muxctrl_id << 1) & 0x1f;
> +
> +	reg = readl(regaddr);
> +	reg &= ~(0x3 << maskbit);
> +	reg |= func << maskbit;
> +	writel(reg, regaddr);
> +}
> +
> +static void pinctrl_tegra20_set_pull(struct pinctrl_tegra20 *ctrl,
> +				     int pullctrl_id, int pull)
> +{
> +	u32 *regaddr = ctrl->regs[2];
> +	u32 reg;
> +	int maskbit;
> +
> +	regaddr += pullctrl_id >> 4;
> +	maskbit = (pullctrl_id << 1) & 0x1f;
> +
> +	reg = readl(regaddr);
> +	reg &= ~(0x3 << maskbit);
> +	reg |= pull << maskbit;
> +	writel(reg, regaddr);
> +}
> +
> +static void pinctrl_tegra20_set_tristate(struct pinctrl_tegra20 *ctrl,
> +					 int trictrl_id, int tristate)
> +{
> +	u32 *regaddr = ctrl->regs[0];
> +	u32 reg;
> +	int maskbit;
> +
> +	regaddr += trictrl_id >> 5;
> +	maskbit = trictrl_id & 0x1f;
> +
> +	reg = readl(regaddr);
> +	reg &= ~(1 << maskbit);
> +	reg |= tristate << maskbit;
> +	writel(reg, regaddr);
> +}
> +
> +static int pinctrl_tegra20_set_state(struct pinctrl_device *pdev,
> +				     struct device_node *np)
> +{
> +	struct pinctrl_tegra20 *ctrl =
> +			container_of(pdev, struct pinctrl_tegra20, pinctrl);
> +	struct device_node *childnode;
> +	int pull = -1, tri = -1, i, j, k;
> +	const char *pins, *func = NULL;
> +	const struct tegra20_pingroup *group;
> +
> +	/*
> +	 * At first look if the node we are pointed at has children,
> +	 * which we may want to visit.
> +	 */
> +	list_for_each_entry(childnode, &np->children, parent_list)
> +		pinctrl_tegra20_set_state(pdev, childnode);
> +
> +	/* read relevant state from devicetree */
> +	of_property_read_string(np, "nvidia,function", &func);
> +	of_property_read_u32_array(np, "nvidia,pull", &pull, 1);
> +	of_property_read_u32_array(np, "nvidia,tristate", &tri, 1);
> +
> +	/* iterate over all pingroups referenced in the dt node */
> +	for (i = 0; ; i++) {
> +		if (of_property_read_string_index(np, "nvidia,pins", i, &pins))
> +			break;
> +
> +		for (j = 0; j < ARRAY_SIZE(tegra20_groups); j++) {
> +			if (!strcmp(pins, tegra20_groups[j].name)) {
> +				group = &tegra20_groups[j];
> +				break;
> +			}
> +		}
> +		/* if no matching pingroup is found bail out */
> +		if (j == ARRAY_SIZE(tegra20_groups)) {
> +			dev_warn(ctrl->pinctrl.dev,
> +				 "invalid pingroup %s referenced in node %s\n",
> +				 pins, np->name);
> +			continue;
> +		}
> +
> +		if (func) {
> +			for (k = 0; k < 4; k++) {
> +				if (!strcmp(func, group->funcs[k]))
> +					break;
> +			}
> +			if (k < 4)
> +				pinctrl_tegra20_set_func(ctrl,
> +							 group->muxctrl_id, k);
> +			else
> +				dev_warn(ctrl->pinctrl.dev,
> +					 "invalid function %s for pingroup %s in node %s\n",
> +					 func, group->name, np->name);
> +		}
> +
> +		if (pull >= 0) {
> +			if (group->pullctrl_id >= 0)
> +				pinctrl_tegra20_set_pull(ctrl,
> +							 group->pullctrl_id,
> +							 pull);
> +			else
> +				dev_warn(ctrl->pinctrl.dev,
> +					 "pingroup %s in node %s doesn't support pull configuration\n",
> +					 group->name, np->name);
> +		}
> +
> +		if (tri >= 0)
> +			pinctrl_tegra20_set_tristate(ctrl,
> +						     group->trictrl_id, tri);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct pinctrl_ops pinctrl_tegra20_ops = {
> +	.set_state = pinctrl_tegra20_set_state,
> +};
> +
> +static int pinctrl_tegra20_probe(struct device_d *dev)
> +{
> +	struct pinctrl_tegra20 *ctrl;
> +	int i, ret = 0;
no need the init of ret
> +
> +	ctrl = xzalloc(sizeof(*ctrl));
> +
> +	/*
> +	 * Tegra pincontrol is split out into four independent memory ranges:
> +	 * tristate control, function mux, pullup/down control, pad control
> +	 * (from lowest to highest hardware address).
> +	 * We are only interested in the first three for now.
> +	 */
> +	for (i = 0; i <= 2; i++) {
> +		ctrl->regs[i] = dev_request_mem_region(dev, i);
> +	}
drop {}

but use a specific name will simplify debug

and make the code easier
> +
> +	ctrl->pinctrl.dev = dev;
> +	ctrl->pinctrl.ops = &pinctrl_tegra20_ops;
> +
> +	ret = pinctrl_register(&ctrl->pinctrl);
> +	if (ret)
> +		free(ctrl);
report an error message
> +

we sould handle probe defer too
> +	return ret;
> +}
> +
> +static __maybe_unused struct of_device_id pinctrl_tegra20_dt_ids[] = {
> +	{
> +		.compatible = "nvidia,tegra20-pinmux",
> +	}, {
> +		/* sentinel */
> +	}
> +};
> +
> +static struct driver_d pinctrl_tegra20_driver = {
> +	.name		= "pinctrl-tegra20",
> +	.probe		= pinctrl_tegra20_probe,
> +	.of_compatible	= DRV_OF_COMPAT(pinctrl_tegra20_dt_ids),
> +};
> +
> +static int pinctrl_tegra20_init(void)
> +{
> +	return platform_driver_register(&pinctrl_tegra20_driver);
> +}
> +postcore_initcall(pinctrl_tegra20_init);
> -- 
> 1.8.1.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] tegra20: add pinctrl driver
  2013-05-06 15:27 ` [PATCH 1/2] tegra20: add pinctrl driver Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-06 19:59   ` Sascha Hauer
  2013-05-06 20:47     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-08  6:28   ` Sascha Hauer
  1 sibling, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2013-05-06 19:59 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Mon, May 06, 2013 at 05:27:25PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > +
> > +static struct pinctrl_ops pinctrl_tegra20_ops = {
> > +	.set_state = pinctrl_tegra20_set_state,
> > +};
> > +
> > +static int pinctrl_tegra20_probe(struct device_d *dev)
> > +{
> > +	struct pinctrl_tegra20 *ctrl;
> > +	int i, ret = 0;
> no need the init of ret
> > +
> > +	ctrl = xzalloc(sizeof(*ctrl));
> > +
> > +	/*
> > +	 * Tegra pincontrol is split out into four independent memory ranges:
> > +	 * tristate control, function mux, pullup/down control, pad control
> > +	 * (from lowest to highest hardware address).
> > +	 * We are only interested in the first three for now.
> > +	 */
> > +	for (i = 0; i <= 2; i++) {
> > +		ctrl->regs[i] = dev_request_mem_region(dev, i);

The return values of dev_request_mem_region should be checked for new
drivers. I know 98% of the code currently does not do this and it was a
mistake. The above may fail if regions overlap or there are other bugs
in the devicetree. Having this silently fail means that the actual
register accesses do a NULL pointer deref later.

> > +	}
> drop {}
> 
> but use a specific name will simplify debug

I don't think this should be mandatory.

> 
> and make the code easier
> > +
> > +	ctrl->pinctrl.dev = dev;
> > +	ctrl->pinctrl.ops = &pinctrl_tegra20_ops;
> > +
> > +	ret = pinctrl_register(&ctrl->pinctrl);
> > +	if (ret)
> > +		free(ctrl);
> report an error message

The core will answer with an error message here. There is no need to
litter the code with error messages which only add to the binary size.
The above may fail for a developer but really should not fail for a user.
A developer has enough information with the probe functions error code.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] tegra20: add pinctrl driver
  2013-05-06 19:59   ` Sascha Hauer
@ 2013-05-06 20:47     ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-06 20:47 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On 21:59 Mon 06 May     , Sascha Hauer wrote:
> On Mon, May 06, 2013 at 05:27:25PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > +
> > > +static struct pinctrl_ops pinctrl_tegra20_ops = {
> > > +	.set_state = pinctrl_tegra20_set_state,
> > > +};
> > > +
> > > +static int pinctrl_tegra20_probe(struct device_d *dev)
> > > +{
> > > +	struct pinctrl_tegra20 *ctrl;
> > > +	int i, ret = 0;
> > no need the init of ret
> > > +
> > > +	ctrl = xzalloc(sizeof(*ctrl));
> > > +
> > > +	/*
> > > +	 * Tegra pincontrol is split out into four independent memory ranges:
> > > +	 * tristate control, function mux, pullup/down control, pad control
> > > +	 * (from lowest to highest hardware address).
> > > +	 * We are only interested in the first three for now.
> > > +	 */
> > > +	for (i = 0; i <= 2; i++) {
> > > +		ctrl->regs[i] = dev_request_mem_region(dev, i);
> 
> The return values of dev_request_mem_region should be checked for new
> drivers. I know 98% of the code currently does not do this and it was a
> mistake. The above may fail if regions overlap or there are other bugs
> in the devicetree. Having this silently fail means that the actual
> register accesses do a NULL pointer deref later.
why not simply put a BUG in the request_mem
> 
> > > +	}
> > drop {}
> > 
> > but use a specific name will simplify debug
> 
> I don't think this should be mandatory.
the issue is that a number can be easly endup to a hiden typo (no compile
error) where a ttypo in the name will no compile.

> 
> > 
> > and make the code easier
> > > +
> > > +	ctrl->pinctrl.dev = dev;
> > > +	ctrl->pinctrl.ops = &pinctrl_tegra20_ops;
> > > +
> > > +	ret = pinctrl_register(&ctrl->pinctrl);
> > > +	if (ret)
> > > +		free(ctrl);
> > report an error message
> 
> The core will answer with an error message here. There is no need to
> litter the code with error messages which only add to the binary size.
> The above may fail for a developer but really should not fail for a user.
> A developer has enough information with the probe functions error code.

pinctrl_register print no error message

it's good to known why we failled no just that the probe return -Exxx

and this will not impact the binary size if we put a dev_warn or dev_debug

as we can drop them with the printk level

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] tegra20: add pinctrl driver
  2013-05-06 15:27 ` [PATCH 1/2] tegra20: add pinctrl driver Jean-Christophe PLAGNIOL-VILLARD
  2013-05-06 19:59   ` Sascha Hauer
@ 2013-05-08  6:28   ` Sascha Hauer
  1 sibling, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2013-05-08  6:28 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Mon, May 06, 2013 at 05:27:25PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 16:56 Mon 06 May     , Lucas Stach wrote:
> > This adds a pinctrl driver for the Tegra 20 line of SoCs. It only
> > supports the three basic pinconfiguration settings function mux,
> > tristate control and pullup/down control.
> > 
> > The driver understands the same devicetree bindings as the Linux one,
> > unimplemented pinconfiguration options will be ignored.
> > 
> > Signed-off-by: Lucas Stach <dev@lynxeye.de>
> > ---
> >  arch/arm/dts/tegra20.dtsi         |   8 +
> >  drivers/pinctrl/Kconfig           |   6 +
> >  drivers/pinctrl/Makefile          |   1 +
> >  drivers/pinctrl/pinctrl-tegra20.c | 336 ++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 351 insertions(+)
> >  create mode 100644 drivers/pinctrl/pinctrl-tegra20.c
> > 
> > diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
> > index b7d1e27..f63ead8 100644
> > --- a/arch/arm/dts/tegra20.dtsi
> > +++ b/arch/arm/dts/tegra20.dtsi
> > @@ -34,6 +34,14 @@
> >  		interrupt-controller;
> >  	};
> >  
> > +	pinmux: pinmux {
> > +	compatible = "nvidia,tegra20-pinmux";
> > +	reg = <0x70000014 0x10   /* Tri-state registers */
> > +	       0x70000080 0x20   /* Mux registers */
> > +	       0x700000a0 0x14   /* Pull-up/down registers */
> > +	       0x70000868 0xa8>; /* Pad control registers */
> tab here

This is done to align under the lines above. I wouldn't do it in my
code, but it's perfectly fine to do it.

> > +	};
> > +
> >  	pmc {
> >  		compatible = "nvidia,tegra20-pmc";
> >  		reg = <0x7000e400 0x400>;
> > diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> > index e6aee50..0b859b8 100644
> > --- a/drivers/pinctrl/Kconfig
> > +++ b/drivers/pinctrl/Kconfig
> > @@ -25,4 +25,10 @@ config PINCTRL_IMX_IOMUX_V3
> >  	help
> >  	  This iomux controller is found on i.MX25,35,51,53,6.
> >  
> > +config PINCTRL_TEGRA20
> > +	select PINCTRL
> > +	bool "Tegra 20 pinmux"
> > +	help
> > +	  The pinmux controller found on the Tegra 20 line of SoCs.
> pinctrl will be mandatory on tegra

It will, yes, but no need to do it now. There can well be some time to
test the driver before it becomes mandatory.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-05-08  6:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-06 14:56 [PATCH 1/2] tegra20: add pinctrl driver Lucas Stach
2013-05-06 14:56 ` [PATCH 2/2] tegra: paz00: import pinconfig from Linux Lucas Stach
2013-05-06 15:27 ` [PATCH 1/2] tegra20: add pinctrl driver Jean-Christophe PLAGNIOL-VILLARD
2013-05-06 19:59   ` Sascha Hauer
2013-05-06 20:47     ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-08  6:28   ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox