* [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