Hi Linus, Tony,
This RFC series adds pinmux support for OMAP using the pinctrl framework. Though it adds a pinmux-omap.c driver file, it currently only supports OMAP4 and also has very few function/pin-groups defined.
I have also retained the existing muxing done from board files using the OMAP-mux framework since this series does not handle configuring pull up/downs for pins, and only looks at pin-muxing.
These are still early patches, but I wanted to get some feedback on if I am heading in the right direction. Hence sharing these in the current form.
regards, Rajendra
Rajendra Nayak (3): pinctrl: add a driver for the OMAP pinmux ARM: omap4: Add omap4 pinmux devices for core and wkup ARM: omap4: Add pinmux map in SDP and PANDA board files
arch/arm/mach-omap2/board-4430sdp.c | 10 + arch/arm/mach-omap2/board-omap4panda.c | 11 + arch/arm/mach-omap2/devices.c | 43 ++ drivers/pinctrl/Kconfig | 7 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinmux-omap.c | 735 ++++++++++++++++++++++++++++++++ 6 files changed, 807 insertions(+), 0 deletions(-) create mode 100644 drivers/pinctrl/pinmux-omap.c
This adds a driver for the OMAP pinmux portions of the system control module. The driver is based on the u300 pinmux driver and only supports OMAP4 platforms for now. Also has very minimal functions/pin-groups for OMAP4 defined.
Signed-off-by: Rajendra Nayak rnayak@ti.com --- drivers/pinctrl/Kconfig | 7 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinmux-omap.c | 735 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 743 insertions(+), 0 deletions(-) create mode 100644 drivers/pinctrl/pinmux-omap.c
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ef56644..f0770be 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -40,4 +40,11 @@ config PINMUX_U300 help Say Y here to enable the U300 pinmux driver
+config PINMUX_OMAP + bool "OMAP pinmux driver" + depends on ARCH_OMAP + select PINMUX + help + Say Y here to enable the OMAP pinmux driver + endif diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index bdc548a..c79e8c6 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o +obj-$(CONFIG_PINMUX_OMAP) += pinmux-omap.o diff --git a/drivers/pinctrl/pinmux-omap.c b/drivers/pinctrl/pinmux-omap.c new file mode 100644 index 0000000..fa96fbd --- /dev/null +++ b/drivers/pinctrl/pinmux-omap.c @@ -0,0 +1,735 @@ +/* + * Driver for the OMAP pinmux controller + * + * Copyright (C) 2011 Texas Instruments + * Author: Rajendra Nayak rnayak@ti.com + * + * The OMAP control module has a device-control sub-module + * which handles all pin/padmuxing for OMAP. The sub-module + * is further split into a 'core' instance within the CORE + * powerdomain and a 'wkup' instance within the WAKEUP + * powerdomain (which is always powered on) + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> + +#define DRIVER_NAME "pinmux-omap" + +#define OMAP_NUM_PADS 547 + +/* omap4 mux mode options for each pin. See TRM for options */ +#define OMAP_MUX_MODE0 0 +#define OMAP_MUX_MODE1 1 +#define OMAP_MUX_MODE2 2 +#define OMAP_MUX_MODE3 3 +#define OMAP_MUX_MODE4 4 +#define OMAP_MUX_MODE5 5 +#define OMAP_MUX_MODE6 6 +#define OMAP_MUX_MODE7 7 + +#define OMAP_MUX_NR_MODES 8 + +/* omap4 core pads */ +static const struct pinctrl_pin_desc omap4_core_pads[] = { + PINCTRL_PIN(0, "c12"), + PINCTRL_PIN(1, "d12"), + PINCTRL_PIN(2, "c13"), + PINCTRL_PIN(3, "d13"), + PINCTRL_PIN(4, "c15"), + PINCTRL_PIN(5, "d15"), + PINCTRL_PIN(6, "a16"), + PINCTRL_PIN(7, "b16"), + PINCTRL_PIN(8, "c16"), + PINCTRL_PIN(9, "d16"), + PINCTRL_PIN(10, "c17"), + PINCTRL_PIN(11, "d17"), + PINCTRL_PIN(12, "c18"), + PINCTRL_PIN(13, "d18"), + PINCTRL_PIN(14, "c19"), + PINCTRL_PIN(15, "d19"), + PINCTRL_PIN(16, "b17"), + PINCTRL_PIN(17, "a18"), + PINCTRL_PIN(18, "b18"), + PINCTRL_PIN(19, "a19"), + PINCTRL_PIN(20, "b19"), + PINCTRL_PIN(21, "b20"), + PINCTRL_PIN(22, "a21"), + PINCTRL_PIN(23, "b21"), + PINCTRL_PIN(24, "c20"), + PINCTRL_PIN(25, "d20"), + PINCTRL_PIN(26, "b25"), + PINCTRL_PIN(27, "c21"), + PINCTRL_PIN(28, "d21"), + PINCTRL_PIN(29, "c22"), + PINCTRL_PIN(30, "c25"), + PINCTRL_PIN(31, "b22"), + PINCTRL_PIN(32, "d25"), + PINCTRL_PIN(33, "b11"), + PINCTRL_PIN(34, "b12"), + PINCTRL_PIN(35, "c23"), + PINCTRL_PIN(36, "d22"), + PINCTRL_PIN(37, "b26"), + PINCTRL_PIN(38, "b23"), + PINCTRL_PIN(39, "d23"), + PINCTRL_PIN(40, "a24"), + PINCTRL_PIN(41, "b24"), + PINCTRL_PIN(42, "c24"), + PINCTRL_PIN(43, "d24"), + PINCTRL_PIN(44, "b9"), + PINCTRL_PIN(45, "b10"), + PINCTRL_PIN(46, "a8"), + PINCTRL_PIN(47, "b8"), + PINCTRL_PIN(48, "r26"), + PINCTRL_PIN(49, "r25"), + PINCTRL_PIN(50, "t26"), + PINCTRL_PIN(51, "t25"), + PINCTRL_PIN(52, "u26"), + PINCTRL_PIN(53, "u25"), + PINCTRL_PIN(54, "v26"), + PINCTRL_PIN(55, "v25"), + PINCTRL_PIN(56, "w26"), + PINCTRL_PIN(57, "w25"), + PINCTRL_PIN(58, "m26"), + PINCTRL_PIN(59, "m25"), + PINCTRL_PIN(60, "n26"), + PINCTRL_PIN(61, "n25"), + PINCTRL_PIN(62, "t27"), + PINCTRL_PIN(63, "u27"), + PINCTRL_PIN(64, "v27"), + PINCTRL_PIN(65, "ae18"), + PINCTRL_PIN(66, "ag19"), + PINCTRL_PIN(67, "af19"), + PINCTRL_PIN(68, "ae19"), + PINCTRL_PIN(69, "af18"), + PINCTRL_PIN(70, "ag18"), + PINCTRL_PIN(71, "ae17"), + PINCTRL_PIN(72, "af17"), + PINCTRL_PIN(73, "ah17"), + PINCTRL_PIN(74, "ae16"), + PINCTRL_PIN(75, "af16"), + PINCTRL_PIN(76, "ag16"), + PINCTRL_PIN(77, "af14"), + PINCTRL_PIN(78, "ae14"), + PINCTRL_PIN(79, "h2"), + PINCTRL_PIN(80, "h3"), + PINCTRL_PIN(81, "d2"), + PINCTRL_PIN(82, "e3"), + PINCTRL_PIN(83, "e4"), + PINCTRL_PIN(84, "e2"), + PINCTRL_PIN(85, "e1"), + PINCTRL_PIN(86, "f4"), + PINCTRL_PIN(87, "f3"), + PINCTRL_PIN(88, "f1"), + PINCTRL_PIN(89, "g4"), + PINCTRL_PIN(90, "g3"), + PINCTRL_PIN(91, "ad27"), + PINCTRL_PIN(92, "ad26"), + PINCTRL_PIN(93, "ad25"), + PINCTRL_PIN(94, "ac28"), + PINCTRL_PIN(95, "ac26"), + PINCTRL_PIN(96, "ac25"), + PINCTRL_PIN(97, "ab25"), + PINCTRL_PIN(98, "ac27"), + PINCTRL_PIN(99, "ag25"), + PINCTRL_PIN(100, "af25"), + PINCTRL_PIN(101, "ae25"), + PINCTRL_PIN(102, "af26"), + PINCTRL_PIN(103, "ah26"), + PINCTRL_PIN(104, "ae24"), + PINCTRL_PIN(105, "af24"), + PINCTRL_PIN(106, "ag24"), + PINCTRL_PIN(107, "ah24"), + PINCTRL_PIN(108, "ab26"), + PINCTRL_PIN(109, "ab27"), + PINCTRL_PIN(110, "aa25"), + PINCTRL_PIN(111, "aa26"), + PINCTRL_PIN(112, "aa27"), + PINCTRL_PIN(113, "ae28"), + PINCTRL_PIN(114, "ae26"), + PINCTRL_PIN(115, "c26"), + PINCTRL_PIN(116, "d26"), + PINCTRL_PIN(117, "w27"), + PINCTRL_PIN(118, "y27"), + PINCTRL_PIN(119, "ag21"), + PINCTRL_PIN(120, "ah22"), + PINCTRL_PIN(121, "af22"), + PINCTRL_PIN(122, "ae22"), + PINCTRL_PIN(123, "ag22"), + PINCTRL_PIN(124, "ae23"), + PINCTRL_PIN(125, "af23"), + PINCTRL_PIN(126, "ag23"), + PINCTRL_PIN(127, "ah23"), + PINCTRL_PIN(128, "f27"), + PINCTRL_PIN(129, "f28"), + PINCTRL_PIN(130, "g27"), + PINCTRL_PIN(131, "g28"), + PINCTRL_PIN(132, "ae5"), + PINCTRL_PIN(133, "af5"), + PINCTRL_PIN(134, "ae4"), + PINCTRL_PIN(135, "af4"), + PINCTRL_PIN(136, "ag3"), + PINCTRL_PIN(137, "af3"), + PINCTRL_PIN(138, "ae21"), + PINCTRL_PIN(139, "af20"), + PINCTRL_PIN(140, "af21"), + PINCTRL_PIN(141, "ae20"), + PINCTRL_PIN(142, "ag20"), + PINCTRL_PIN(143, "ah19"), + PINCTRL_PIN(144, "ag12"), + PINCTRL_PIN(145, "af12"), + PINCTRL_PIN(146, "ae12"), + PINCTRL_PIN(147, "ag13"), + PINCTRL_PIN(148, "ae11"), + PINCTRL_PIN(149, "af11"), + PINCTRL_PIN(150, "ag11"), + PINCTRL_PIN(151, "ah11"), + PINCTRL_PIN(152, "ae10"), + PINCTRL_PIN(153, "af10"), + PINCTRL_PIN(154, "ag10"), + PINCTRL_PIN(155, "ae9"), + PINCTRL_PIN(156, "af13"), + PINCTRL_PIN(157, "ae13"), + PINCTRL_PIN(158, "g26"), + PINCTRL_PIN(159, "g25"), + PINCTRL_PIN(160, "h26"), + PINCTRL_PIN(161, "h25"), + PINCTRL_PIN(162, "j27"), + PINCTRL_PIN(163, "h27"), + PINCTRL_PIN(164, "j26"), + PINCTRL_PIN(165, "j25"), + PINCTRL_PIN(166, "k26"), + PINCTRL_PIN(167, "k25"), + PINCTRL_PIN(168, "l27"), + PINCTRL_PIN(169, "k27"), + PINCTRL_PIN(170, "c3"), + PINCTRL_PIN(171, "b5"), + PINCTRL_PIN(172, "b4"), + PINCTRL_PIN(173, "aa28"), + PINCTRL_PIN(174, "y28"), + PINCTRL_PIN(175, "ae6"), + PINCTRL_PIN(176, "af6"), + PINCTRL_PIN(177, "f26"), + PINCTRL_PIN(178, "e27"), + PINCTRL_PIN(179, "e26"), + PINCTRL_PIN(180, "e25"), + PINCTRL_PIN(181, "d28"), + PINCTRL_PIN(182, "d27"), + PINCTRL_PIN(183, "m2"), + PINCTRL_PIN(184, "n2"), + PINCTRL_PIN(185, "p2"), + PINCTRL_PIN(186, "v1"), + PINCTRL_PIN(187, "v2"), + PINCTRL_PIN(188, "w1"), + PINCTRL_PIN(189, "w2"), + PINCTRL_PIN(190, "w3"), + PINCTRL_PIN(191, "w4"), + PINCTRL_PIN(192, "y2"), + PINCTRL_PIN(193, "y3"), + PINCTRL_PIN(194, "y4"), + PINCTRL_PIN(195, "aa1"), + PINCTRL_PIN(196, "aa2"), + PINCTRL_PIN(197, "aa3"), + PINCTRL_PIN(198, "aa4"), + PINCTRL_PIN(199, "ab2"), + PINCTRL_PIN(200, "ab3"), + PINCTRL_PIN(201, "ab4"), + PINCTRL_PIN(202, "ac4"), +}; + +/* omap4 wkup pads */ +static const struct pinctrl_pin_desc omap4_wkup_pads[] = { + PINCTRL_PIN(0, "c12"), + PINCTRL_PIN(1, "d12"), + PINCTRL_PIN(2, "c13"), + PINCTRL_PIN(3, "d13"), + PINCTRL_PIN(4, "c15"), + PINCTRL_PIN(5, "d15"), + PINCTRL_PIN(6, "a16"), + PINCTRL_PIN(7, "b16"), + PINCTRL_PIN(8, "c16"), + PINCTRL_PIN(9, "d16"), + PINCTRL_PIN(10, "c17"), + PINCTRL_PIN(11, "d17"), + PINCTRL_PIN(12, "c18"), + PINCTRL_PIN(13, "d18"), + PINCTRL_PIN(14, "c19"), + PINCTRL_PIN(15, "d19"), + PINCTRL_PIN(16, "b17"), + PINCTRL_PIN(17, "a18"), + PINCTRL_PIN(18, "b18"), + PINCTRL_PIN(19, "a19"), + PINCTRL_PIN(20, "b19"), + PINCTRL_PIN(21, "b20"), + PINCTRL_PIN(22, "a21"), + PINCTRL_PIN(23, "b21"), + PINCTRL_PIN(24, "c20"), + PINCTRL_PIN(25, "d20"), + PINCTRL_PIN(26, "b25"), + PINCTRL_PIN(27, "c21"), + PINCTRL_PIN(28, "d21"), + PINCTRL_PIN(29, "c22"), + PINCTRL_PIN(30, "c25"), + PINCTRL_PIN(31, "b22"), + PINCTRL_PIN(32, "d25"), + PINCTRL_PIN(33, "b11"), + PINCTRL_PIN(34, "b12"), + PINCTRL_PIN(35, "c23"), + PINCTRL_PIN(36, "d22"), + PINCTRL_PIN(37, "b26"), + PINCTRL_PIN(38, "b23"), + PINCTRL_PIN(39, "d23"), + PINCTRL_PIN(40, "a24"), + PINCTRL_PIN(41, "b24"), + PINCTRL_PIN(42, "c24"), + PINCTRL_PIN(43, "d24"), + PINCTRL_PIN(44, "b9"), + PINCTRL_PIN(45, "b10"), + PINCTRL_PIN(46, "a8"), + PINCTRL_PIN(47, "b8"), + PINCTRL_PIN(48, "r26"), + PINCTRL_PIN(49, "r25"), + PINCTRL_PIN(50, "h4"), + PINCTRL_PIN(51, "j2"), + PINCTRL_PIN(52, "g2"), + PINCTRL_PIN(53, "j1"), + PINCTRL_PIN(54, "k1"), + PINCTRL_PIN(55, "ag9"), + PINCTRL_PIN(56, "af9"), + PINCTRL_PIN(57, "ah6"), + PINCTRL_PIN(58, "ag8"), + PINCTRL_PIN(59, "ad1"), + PINCTRL_PIN(60, "ad2"), + PINCTRL_PIN(61, "ad3"), + PINCTRL_PIN(62, "ad4"), + PINCTRL_PIN(63, "ac2"), + PINCTRL_PIN(64, "ac3"), + PINCTRL_PIN(65, "ag7"), + PINCTRL_PIN(66, "ae7"), + PINCTRL_PIN(67, "af7"), + PINCTRL_PIN(68, "ah7"), + PINCTRL_PIN(69, "ag6"), + PINCTRL_PIN(70, "af8"), + PINCTRL_PIN(71, "ae8"), + PINCTRL_PIN(72, "ah2"), + PINCTRL_PIN(73, "ag1"), + PINCTRL_PIN(74, "ae3"), + PINCTRL_PIN(75, "ah1"), + PINCTRL_PIN(76, "ae1"), + PINCTRL_PIN(77, "ae2"), +}; + +/** + * @dev: a pointer back to containing device + * @virtbase: the offset to the controller in virtual memory + */ +struct omap_pmx { + struct device *dev; + struct pinctrl_dev *pctl; + u32 phybase; + u32 physize; + void __iomem *virtbase; +}; + +/** + * struct omap_pin_group - describes a omap pin group + * @name: the name of this specific pin group + * @pins: an array of discrete physical pins used in this group, taken + * from the driver-local pin enumeration space + * @muxmodes: mux mode to be configured for each pin + * @num_pins: the number of pins in this group array, i.e. the number of + * elements in .pins so we can iterate over that array + */ +struct omap_pin_group { + const char *name; + const unsigned *pins; + const unsigned *muxmodes; + const unsigned num_pins; +}; + +static const unsigned hdmi_pins[] = { + 44, /* HDMI_HPD */ + 45, /* HDMI_CEC */ + 46, /* HDMI_DDC_SCL */ + 47, /* HDMI_DDC_SDA */ +}; + +static const unsigned hdmi_muxmodes[] = { + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, +}; + +static const unsigned sdmmc5_pins[] = { + 132, /* WLAN SDIO: MMC5 CMD */ + 133, /* WLAN SDIO: MMC5 CLK */ + 134, /* WLAN SDIO: MMC5 DAT0 */ + 135, /* WLAN SDIO: MMC5 DAT1 */ + 136, /* WLAN SDIO: MMC5 DAT2 */ + 137, /* WLAN SDIO: MMC5 DAT3 */ +}; + +static const unsigned sdmmc5_muxmodes[] = { + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, + OMAP_MUX_MODE0, +}; + +static const unsigned dispc2_pins[] = { + 145, /* dispc2_data23 */ + 146, /* dispc2_data22 */ + 147, /* dispc2_data21 */ + 148, /* dispc2_data19 */ + 149, /* dispc2_data18 */ + 150, /* dispc2_data15 */ + 151, /* dispc2_data14 */ + 152, /* dispc2_data13 */ + 153, /* dispc2_data12 */ + 154, /* dispc2_data11 */ + 186, /* dispc2_data10 */ + 187, /* dispc2_data9 */ + 188, /* dispc2_data16 */ + 189, /* dispc2_data17 */ + 190, /* dispc2_hsync */ + 191, /* dispc2_pclk */ + 192, /* dispc2_vsync */ + 193, /* dispc2_de */ + 194, /* dispc2_data8 */ + 195, /* dispc2_data7 */ + 196, /* dispc2_data6 */ + 197, /* dispc2_data5 */ + 198, /* dispc2_data4 */ + 199, /* dispc2_data3 */ + 200, /* dispc2_data2 */ + 201, /* dispc2_data1 */ + 202, /* dispc2_data0 */ +}; + +static const unsigned dispc2_muxmodes[] = { + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, + OMAP_MUX_MODE5, +}; + +static const struct omap_pin_group omap_pin_groups[] = { + { + .name = "hdmi_grp", + .pins = hdmi_pins, + .muxmodes = hdmi_muxmodes, + .num_pins = ARRAY_SIZE(hdmi_pins), + }, + { + .name = "sdmmc5_grp", + .pins = sdmmc5_pins, + .muxmodes = sdmmc5_muxmodes, + .num_pins = ARRAY_SIZE(sdmmc5_pins), + }, + { + .name = "dispc2_grp", + .pins = dispc2_pins, + .muxmodes = dispc2_muxmodes, + .num_pins = ARRAY_SIZE(dispc2_pins), + }, +}; + +static int omap_list_groups(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(omap_pin_groups)) + return -EINVAL; + return 0; +} + +static const char *omap_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + if (selector >= ARRAY_SIZE(omap_pin_groups)) + return NULL; + return omap_pin_groups[selector].name; +} + +static int omap_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + const unsigned **pins, + unsigned *num_pins) +{ + if (selector >= ARRAY_SIZE(omap_pin_groups)) + return -EINVAL; + *pins = omap_pin_groups[selector].pins; + *num_pins = omap_pin_groups[selector].num_pins; + return 0; +} + +static void omap_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned offset) +{ + seq_printf(s, " " DRIVER_NAME); +} + +static struct pinctrl_ops omap_pctrl_ops = { + .list_groups = omap_list_groups, + .get_group_name = omap_get_group_name, + .get_group_pins = omap_get_group_pins, + .pin_dbg_show = omap_pin_dbg_show, +}; + +/* + * Here we define the available functions and their corresponding pin groups + */ + +/** + * struct omap_pmx_func - describes omap pinmux functions + * @name: the name of this specific function + * @groups: corresponding pin groups + * @onmask: bits to set to enable this when doing pin muxing + */ +struct omap_pmx_func { + const char *name; + const char * const *groups; + const unsigned num_groups; + const struct omap_pmx_mask *mask; +}; + +static const char * const hdmi_grps[] = { "hdmi_grp" }; +static const char * const sdmmc5_grps[] = { "sdmmc5_grp" }; +static const char * const dispc2_grps[] = { "dispc2_grp" }; + +static const struct omap_pmx_func omap_pmx_functions[] = { + { + .name = "hdmi", + .groups = hdmi_grps, + .num_groups = ARRAY_SIZE(hdmi_grps), + }, + { + .name = "sdmmc5", + .groups = sdmmc5_grps, + .num_groups = ARRAY_SIZE(sdmmc5_grps), + }, + { + .name = "dispc2", + .groups = dispc2_grps, + .num_groups = ARRAY_SIZE(dispc2_grps), + }, +}; + +/* handle 8 bit registers too, for now only worry about 16bit ones*/ +static u16 omap_pmx_read(struct omap_pmx *opmx, unsigned pin) +{ + return __raw_readw(opmx->virtbase + (pin * 2)); +} + +static void omap_pmx_write(u16 val, struct omap_pmx *opmx, unsigned pin) +{ + __raw_writew(val, opmx->virtbase + (pin * 2)); +} + +static void omap_pmx_endisable(struct omap_pmx *opmx, unsigned selector, + unsigned group, bool enable) +{ + int i; + unsigned pin, muxmode; + u16 oldval, newval; + + for (i = 0; i < omap_pin_groups[group].num_pins; i++) { + pin = omap_pin_groups[group].pins[i]; + muxmode = omap_pin_groups[group].muxmodes[i]; + /* Put disabled pins in safe (MODE7) mode */ + if (!enable) + muxmode = OMAP_MUX_MODE7; + oldval = omap_pmx_read(opmx, pin); + newval = (oldval & ~(OMAP_MUX_NR_MODES - 1)) | muxmode; + omap_pmx_write(newval, opmx, pin); + } +} + +static int omap_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct omap_pmx *opmx; + + opmx = pinctrl_dev_get_drvdata(pctldev); + omap_pmx_endisable(opmx, selector, group, true); + + return 0; +} + +static void omap_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct omap_pmx *opmx; + + opmx = pinctrl_dev_get_drvdata(pctldev); + omap_pmx_endisable(opmx, selector, group, false); +} + +static int omap_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(omap_pmx_functions)) + return -EINVAL; + return 0; +} + +static const char *omap_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + return omap_pmx_functions[selector].name; +} + +static int omap_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, + const char * const **groups, + unsigned * const num_groups) +{ + *groups = omap_pmx_functions[selector].groups; + *num_groups = omap_pmx_functions[selector].num_groups; + return 0; +} + +static struct pinmux_ops omap_pmx_ops = { + .list_functions = omap_pmx_list_funcs, + .get_function_name = omap_pmx_get_func_name, + .get_function_groups = omap_pmx_get_groups, + .enable = omap_pmx_enable, + .disable = omap_pmx_disable, +}; + +static struct pinctrl_desc omap_pmx_desc = { + .name = DRIVER_NAME, + .maxpin = OMAP_NUM_PADS-1, + .pctlops = &omap_pctrl_ops, + .pmxops = &omap_pmx_ops, + .owner = THIS_MODULE, +}; + +static int __init omap_pmx_probe(struct platform_device *pdev) +{ + int ret; + struct omap_pmx *opmx; + struct resource *res; + + /* Create state holders etc for this driver */ + opmx = devm_kzalloc(&pdev->dev, sizeof(*opmx), GFP_KERNEL); + if (!opmx) + return -ENOMEM; + + opmx->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENOENT; + goto out_no_resource; + } + opmx->phybase = res->start; + opmx->physize = resource_size(res); + + if (request_mem_region(opmx->phybase, opmx->physize, + DRIVER_NAME) == NULL) { + ret = -ENOMEM; + goto out_no_memregion; + } + + opmx->virtbase = ioremap(opmx->phybase, opmx->physize); + if (!opmx->virtbase) { + ret = -ENOMEM; + goto out_no_remap; + } + + if (pdev->id) { + omap_pmx_desc.pins = omap4_wkup_pads; + omap_pmx_desc.npins = ARRAY_SIZE(omap4_wkup_pads); + } else { + omap_pmx_desc.pins = omap4_core_pads; + omap_pmx_desc.npins = ARRAY_SIZE(omap4_core_pads); + } + + opmx->pctl = pinctrl_register(&omap_pmx_desc, &pdev->dev, opmx); + if (!opmx->pctl) { + dev_err(&pdev->dev, "could not register OMAP pinmux driver\n"); + ret = -EINVAL; + goto out_no_pmx; + } + + platform_set_drvdata(pdev, opmx); + + dev_info(&pdev->dev, "initialized OMAP pinmux driver\n"); + + return 0; + +out_no_pmx: + iounmap(opmx->virtbase); +out_no_remap: + platform_set_drvdata(pdev, NULL); +out_no_memregion: + release_mem_region(opmx->phybase, opmx->physize); +out_no_resource: + devm_kfree(&pdev->dev, opmx); + return ret; +} + +static int __exit omap_pmx_remove(struct platform_device *pdev) +{ + struct omap_pmx *opmx = platform_get_drvdata(pdev); + + pinctrl_unregister(opmx->pctl); + iounmap(opmx->virtbase); + release_mem_region(opmx->phybase, opmx->physize); + platform_set_drvdata(pdev, NULL); + devm_kfree(&pdev->dev, opmx); + + return 0; +} + +static struct platform_driver omap_pmx_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(omap_pmx_remove), +}; + +static int __init omap_pmx_init(void) +{ + return platform_driver_probe(&omap_pmx_driver, omap_pmx_probe); +} +arch_initcall(omap_pmx_init); + +static void __exit omap_pmx_exit(void) +{ + platform_driver_unregister(&omap_pmx_driver); +} +module_exit(omap_pmx_exit); + +MODULE_AUTHOR("Rajendra Nayak rnayak@ti.com"); +MODULE_DESCRIPTION("OMAP pin control driver"); +MODULE_LICENSE("GPL v2");
* Rajendra Nayak rnayak@ti.com [111114 04:05]:
--- /dev/null +++ b/drivers/pinctrl/pinmux-omap.c @@ -0,0 +1,735 @@
+/* omap4 core pads */ +static const struct pinctrl_pin_desc omap4_core_pads[] = {
- PINCTRL_PIN(0, "c12"),
- PINCTRL_PIN(1, "d12"),
- PINCTRL_PIN(2, "c13"),
...
Let's not even plan on adding this data here. We already have about 6000 lines of pinmux data for omaps even without this patch.
Instead, just write something as a separate patch that populates omap pinmux data from the existing data until we have the data coming from DT.
+/* omap4 wkup pads */ +static const struct pinctrl_pin_desc omap4_wkup_pads[] = {
- PINCTRL_PIN(0, "c12"),
- PINCTRL_PIN(1, "d12"),
- PINCTRL_PIN(2, "c13"),
...
This too needs to go.
+static const unsigned hdmi_pins[] = {
- 44, /* HDMI_HPD */
- 45, /* HDMI_CEC */
- 46, /* HDMI_DDC_SCL */
- 47, /* HDMI_DDC_SDA */
+};
+static const unsigned hdmi_muxmodes[] = {
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
+};
+static const unsigned sdmmc5_pins[] = {
- 132, /* WLAN SDIO: MMC5 CMD */
- 133, /* WLAN SDIO: MMC5 CLK */
- 134, /* WLAN SDIO: MMC5 DAT0 */
- 135, /* WLAN SDIO: MMC5 DAT1 */
- 136, /* WLAN SDIO: MMC5 DAT2 */
- 137, /* WLAN SDIO: MMC5 DAT3 */
+};
+static const unsigned sdmmc5_muxmodes[] = {
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
- OMAP_MUX_MODE0,
+};
+static const unsigned dispc2_pins[] = {
- 145, /* dispc2_data23 */
- 146, /* dispc2_data22 */
- 147, /* dispc2_data21 */
...
And all of the above.. The same goes for all the static package specific data.
+/* handle 8 bit registers too, for now only worry about 16bit ones*/ +static u16 omap_pmx_read(struct omap_pmx *opmx, unsigned pin) +{
- return __raw_readw(opmx->virtbase + (pin * 2));
+}
+static void omap_pmx_write(u16 val, struct omap_pmx *opmx, unsigned pin) +{
- __raw_writew(val, opmx->virtbase + (pin * 2));
+}
Might as well fix this one since we already have it working.
The rest looks OK to me as a minimal driver. I don't know if we should still populate it with platform_data though, that seems already broken as it's omap4 only. Might as well go with the DT support to start with.
Regards,
Tony
On Monday 14 November 2011 10:53 PM, Tony Lindgren wrote:
- Rajendra Nayakrnayak@ti.com [111114 04:05]:
--- /dev/null +++ b/drivers/pinctrl/pinmux-omap.c @@ -0,0 +1,735 @@
+/* omap4 core pads */ +static const struct pinctrl_pin_desc omap4_core_pads[] = {
- PINCTRL_PIN(0, "c12"),
- PINCTRL_PIN(1, "d12"),
- PINCTRL_PIN(2, "c13"),
...
Let's not even plan on adding this data here. We already have about 6000 lines of pinmux data for omaps even without this patch.
Instead, just write something as a separate patch that populates omap pinmux data from the existing data until we have the data coming from DT.
But the plan is to get rid of those 6000 lines of pinmux data that exists today for OMAP. I did not remove it now, because I still need to take care of the pull up/down configurations which are missing. Once thats in place, we can get rid of the existing data completely.
Linus, Is there a plan to move even the data that exists in the pinmux drivers today (including the function/pin-groups definition) eventually to DT? Or is it just the 'mapping' data to map devices to functions (that today is done from board files) which alone will be moved?
regards, Rajendra
On Tue, Nov 15, 2011 at 5:33 AM, Rajendra Nayak rnayak@ti.com wrote:
On Monday 14 November 2011 10:53 PM, Tony Lindgren wrote:
- Rajendra Nayakrnayak@ti.com [111114 04:05]:
+static const struct pinctrl_pin_desc omap4_core_pads[] = { + PINCTRL_PIN(0, "c12"), + PINCTRL_PIN(1, "d12"), + PINCTRL_PIN(2, "c13"),
...
Let's not even plan on adding this data here. We already have about 6000 lines of pinmux data for omaps even without this patch.
But the plan is to get rid of those 6000 lines of pinmux data that exists today for OMAP. I did not remove it now, because I still need to take care of the pull up/down configurations which are missing. Once thats in place, we can get rid of the existing data completely.
Linus, Is there a plan to move even the data that exists in the pinmux drivers today (including the function/pin-groups definition) eventually to DT? Or is it just the 'mapping' data to map devices to functions (that today is done from board files) which alone will be moved?
Not for the U300 driver, for the simple reason that it cannot use device tree. So both methods of providing the data need to be allowed - either as static data (the U300 driver does not even have platform data, the pin data is encoded in the driver itself since it's tied to U300 and not used for any other systems or variants) or as device tree lookups.
That said I have no clue on how to make the DT bindings FTM, patches and suggestions welcome.
Yours, Linus Walleij
On 17 November 2011 13:38, Linus Walleij linus.walleij@linaro.org wrote:
Linus, Is there a plan to move even the data that exists in the pinmux drivers today (including the function/pin-groups definition) eventually to DT? Or is it just the 'mapping' data to map devices to functions (that today is done from board files) which alone will be moved?
Not for the U300 driver, for the simple reason that it cannot use device tree. So both methods of providing the data need to be allowed - either as static data (the U300 driver does not even have platform data, the pin data is encoded in the driver itself since it's tied to U300 and not used for any other systems or variants) or as device tree lookups.
That said I have no clue on how to make the DT bindings FTM, patches and suggestions welcome.
For now, the Samsung GPIO, Pinconfig and Pinmux information is represented in device tree as listed below.
i2c@1C004000 { compatible = "..."; reg = <0x... 0x..>; gpios = <&gpa0 2 2 3 0>, <&gpa0 3 2 3 0>; ... };
The format of the gpio specifier is <[Pad Controller phandle] [pin number within the controller] [Pin Mux Function] [Pull Up/Down] [Drive Strength]>
From a perspective of writing a 'gpios' property for a device node,
this is quite simple. Looking up the hardware manual of the SoC can provide all the values that should be used in the gpio specifier.
The GPIO/PinCtrl driver can provide a translate function that picks up the values for the gpio specifier and writes the same value to the pad-controller registers. But, this a deviation from the existing pinctrl subsystem code which mainly relies on name of the pin-group and pin-function.
Does this seem to be a feasible option for specifying gpio/pinconfig/pinmux dt bindings?
Thanks. Thomas.
On Thu, Nov 17, 2011 at 12:26 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
For now, the Samsung GPIO, Pinconfig and Pinmux information is represented in device tree as listed below.
Does this mean that the understanding of this format is merged into the mainline kernel drivers or is it keps out-of-tree?
i2c@1C004000 { compatible = "..."; reg = <0x... 0x..>; gpios = <&gpa0 2 2 3 0>, <&gpa0 3 2 3 0>; ... };
The format of the gpio specifier is <[Pad Controller phandle] [pin number within the controller] [Pin Mux Function] [Pull Up/Down] [Drive Strength]>
From a perspective of writing a 'gpios' property for a device node, this is quite simple. Looking up the hardware manual of the SoC can provide all the values that should be used in the gpio specifier.
That may not be as simple as it seems if all you have is the device tree and no manual, but I get the picture.
The GPIO/PinCtrl driver can provide a translate function that picks up the values for the gpio specifier and writes the same value to the pad-controller registers. But, this a deviation from the existing pinctrl subsystem code which mainly relies on name of the pin-group and pin-function.
Does this seem to be a feasible option for specifying gpio/pinconfig/pinmux dt bindings?
I would prefer the above to use the nice generic enums from the pin control subsystem's pinmux and pinconf properties in the end so the device tree on its own is understandable without any manual whatsoever, but we'll see about that.
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Thanks, Linus Walleij
Hi Linus,
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org wrote:
On Thu, Nov 17, 2011 at 12:26 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
For now, the Samsung GPIO, Pinconfig and Pinmux information is represented in device tree as listed below.
Does this mean that the understanding of this format is merged into the mainline kernel drivers or is it keps out-of-tree?
All existing dt support in samsung drivers use this format and it works fine. But I could not complete work on time and pull request for samsung-dt support for 3.2 was delayed and hence rejected. So for now, it is out of tree but available in linux-next.
i2c@1C004000 { compatible = "..."; reg = <0x... 0x..>; gpios = <&gpa0 2 2 3 0>, <&gpa0 3 2 3 0>; ... };
The format of the gpio specifier is <[Pad Controller phandle] [pin number within the controller] [Pin Mux Function] [Pull Up/Down] [Drive Strength]>
From a perspective of writing a 'gpios' property for a device node, this is quite simple. Looking up the hardware manual of the SoC can provide all the values that should be used in the gpio specifier.
That may not be as simple as it seems if all you have is the device tree and no manual, but I get the picture.
The GPIO/PinCtrl driver can provide a translate function that picks up the values for the gpio specifier and writes the same value to the pad-controller registers. But, this a deviation from the existing pinctrl subsystem code which mainly relies on name of the pin-group and pin-function.
Does this seem to be a feasible option for specifying gpio/pinconfig/pinmux dt bindings?
I would prefer the above to use the nice generic enums from the pin control subsystem's pinmux and pinconf properties in the end so the device tree on its own is understandable without any manual whatsoever, but we'll see about that.
This may lead to linux specific information getting into the device tree. And that might not be acceptable.
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
Thanks, Thomas.
On Tue, Nov 22, 2011 at 12:09 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org wrote:
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
OK I think I get it now, so DT bindings shall really NOT be read by any of the pinctrl core, it is *supposed* to be all driver-specific. Then it makes perfect sense to have it as it is.
So for example in the pinctrl-coh901xxx.c example driver I have locally defined registers presets like:
#define U300_FLOATING_INPUT { \ .bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE, \ .output = false, \ }
#define U300_PULL_UP_INPUT { \ .bias_mode = PIN_CONFIG_BIAS_PULL_UP, \ .output = false, \ }
Then this type of stuff shall keep its custom format in the device tree, and the driver for coh901xxx reads that out.
Thanks for helping me understand this crucial assumption of how it works...
Yours, Linus Walleij
* Linus Walleij linus.walleij@linaro.org [111122 03:30]:
On Tue, Nov 22, 2011 at 12:09 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org wrote:
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
OK I think I get it now, so DT bindings shall really NOT be read by any of the pinctrl core, it is *supposed* to be all driver-specific. Then it makes perfect sense to have it as it is.
Yes the driver nodes should describe in DT which pins to use:
serial@12340000 { compatible = "8250"; reg = <0x12340000 0x40>; reg-shift = <2>; interrupts = < 10 >; pins = "uart1_rx", "uart1_tx"; };
Note that we should use the actual signal names, not package specific pad names. This way they have a high likelyhood to work for new packages too by just mapping the signals to the new package.
So for example in the pinctrl-coh901xxx.c example driver I have locally defined registers presets like:
#define U300_FLOATING_INPUT { \ .bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE, \ .output = false, \ }
#define U300_PULL_UP_INPUT { \ .bias_mode = PIN_CONFIG_BIAS_PULL_UP, \ .output = false, \ }
I think things like above should also be set in the node for the driver because it is board specific. For example, if you have an external pull on the board for some line, then the internal pull needs to be disabled.
I don't know how we should describe the driver set values though, maybe something like:
serial@12340000 { compatible = "8250"; reg = <0x12340000 0x40>; reg-shift = <2>; interrupts = < 10 >; pins = "uart1_rx", "uart1_tx"; pin-values = < 0x7 0x7 >; };
Note that with device tree things get simpler for muxing as we can get rid of the hardcoded grouping of pins in mux drivers. Instead of hardcoded pingroups, the groups can be created dynamically based on what the driver DT entries have.
The reason why we want to avoid hardcoded pin groups is because trying to map all the pad combinations in the pinmux driver is not a scalable way to go. And it's not even possible at least on omaps because of the huge number of combinations with alternative pins and multiple packages.
Then this type of stuff shall keep its custom format in the device tree, and the driver for coh901xxx reads that out.
Thanks for helping me understand this crucial assumption of how it works...
FYI I'm playing with a DT based pinmux-simple.c driver that should be pretty generic and work for all kinds of hardware hopefully.
It will be few days before I can post anything though, there are some pinctrl fwk issues to deal with first. Like the hardcoded pinmux_maps that assumes that dev entries are static. This means that multiple instances of pinmux drivers won't work..
Cheers,
Tony
Tony Lindgren wrote at Tuesday, November 22, 2011 10:54 AM:
- Linus Walleij linus.walleij@linaro.org [111122 03:30]:
On Tue, Nov 22, 2011 at 12:09 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org wrote:
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
OK I think I get it now, so DT bindings shall really NOT be read by any of the pinctrl core, it is *supposed* to be all driver-specific. Then it makes perfect sense to have it as it is.
Yes the driver nodes should describe in DT which pins to use:
serial@12340000 { compatible = "8250"; reg = <0x12340000 0x40>; reg-shift = <2>; interrupts = < 10 >; pins = "uart1_rx", "uart1_tx"; };
Sorry to jump in late here, but I wasn't aware of this thread.
I don't necessarily agree with that. Describing the HW doesn't necessarily mean that each device needs to describe what pinmux pins it uses; one could quite easily have the pinmux describe what settings the various pins should have and which drivers will use those pins. That would map very well to the pinctrl subsystem's mapping table, and at least Tegra's existing pinmux tables, which are both just a big array of settings which end up getting provided to drivers.
I'll try and track down the rest of this thread and catch up though...
On 16:28 Tue 22 Nov , Stephen Warren wrote:
Tony Lindgren wrote at Tuesday, November 22, 2011 10:54 AM:
- Linus Walleij linus.walleij@linaro.org [111122 03:30]:
On Tue, Nov 22, 2011 at 12:09 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org wrote:
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
OK I think I get it now, so DT bindings shall really NOT be read by any of the pinctrl core, it is *supposed* to be all driver-specific. Then it makes perfect sense to have it as it is.
Yes the driver nodes should describe in DT which pins to use:
serial@12340000 { compatible = "8250"; reg = <0x12340000 0x40>; reg-shift = <2>; interrupts = < 10 >; pins = "uart1_rx", "uart1_tx"; };
Sorry to jump in late here, but I wasn't aware of this thread.
I don't necessarily agree with that. Describing the HW doesn't necessarily mean that each device needs to describe what pinmux pins it uses; one could quite easily have the pinmux describe what settings the various pins should have and which drivers will use those pins. That would map very well to the pinctrl subsystem's mapping table, and at least Tegra's existing pinmux tables, which are both just a big array of settings which end up getting provided to drivers.
I'll try and track down the rest of this thread and catch up though...
I agreee here
as example on at91 I try to found a good way to let the macb driver to ask the pin configuration
so in my mind i do not need put all pins in each board but in the dtsi and then in the drivers just said pins = "mii"; or pins = "rmii"; or if I want to use the alternative config
pins = "mii_alt"; or pins = "rmii_alt";
and then in the dtsi I describe the pin used for those configs which is soc specifific not board
Best Regards, J.
On Wed, Nov 23, 2011 at 1:28 AM, Stephen Warren swarren@nvidia.com wrote:
Describing the HW doesn't necessarily mean that each device needs to describe what pinmux pins it uses; one could quite easily have the pinmux describe what settings the various pins should have and which drivers will use those pins. That would map very well to the pinctrl subsystem's mapping table, and at least Tegra's existing pinmux tables, which are both just a big array of settings which end up getting provided to drivers.
That sounds true. It's also something that is cleanly cut out as a very well defined and abstract piece of hardware information to live in the device tree and which would be useful for any OS using DT.
I'd have to see the device trees and corresponding map bindings before I understand it fully though.
Just my €0.01 Linus Walleij
Op 22 nov. 2011, om 18:54 heeft Tony Lindgren het volgende geschreven:
- Linus Walleij linus.walleij@linaro.org [111122 03:30]:
On Tue, Nov 22, 2011 at 12:09 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org wrote:
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
OK I think I get it now, so DT bindings shall really NOT be read by any of the pinctrl core, it is *supposed* to be all driver-specific. Then it makes perfect sense to have it as it is.
Yes the driver nodes should describe in DT which pins to use:
serial@12340000 { compatible = "8250"; reg = <0x12340000 0x40>; reg-shift = <2>; interrupts = < 10 >; pins = "uart1_rx", "uart1_tx"; };
Note that we should use the actual signal names, not package specific pad names. This way they have a high likelyhood to work for new packages too by just mapping the signals to the new package.
How would this handle the situation where you can mux a signal to multiple pins? IIRC omap3 and am335x can do funny stuff with the display pins like being able to map the blue bits to different pinblocks.
regards,
Koen
-----Original Message----- From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- owner@vger.kernel.org] On Behalf Of Koen Kooi Sent: Wednesday, November 23, 2011 8:51 PM To: Tony Lindgren Cc: Linus Walleij; Thomas Abraham; Nayak, Rajendra; linux- omap@vger.kernel.org; linaro-dev@lists.linaro.org; linus.walleij@stericsson.com; linux-samsung-soc; devicetree- discuss@lists.ozlabs.org Subject: Re: [RFC 1/3] pinctrl: add a driver for the OMAP pinmux
Op 22 nov. 2011, om 18:54 heeft Tony Lindgren het volgende geschreven:
- Linus Walleij linus.walleij@linaro.org [111122 03:30]:
On Tue, Nov 22, 2011 at 12:09 PM, Thomas Abraham thomas.abraham@linaro.org wrote:
On 17 November 2011 19:27, Linus Walleij linus.walleij@linaro.org
wrote:
Maybe I'm mistaken about the device tree ambitions, but I was sort of hoping that it would not contain too much custom magic numbers that need to be cross-referenced elsewhere ... or rather - the more understandable the device tree is, the more we win.
Device tree is expected to describe the hardware. So to cross-reference the hardware manual to understand device tree should be fine I guess. For instance, GPIO numbers in dts would be written as a numeric number and not a enum or other format. And by looking up the manual, we understand the actual details of the GPIO pin.
If dt-compiler had a option to support #define like in C, the numbers could have been made more easier to understand. Like, 3 to mean GPIO_PULL_UP in Exynos dts file.
OK I think I get it now, so DT bindings shall really NOT be read by any of the pinctrl core, it is *supposed* to be all driver-specific. Then it makes perfect sense to have it as it is.
Yes the driver nodes should describe in DT which pins to use:
serial@12340000 { compatible = "8250"; reg = <0x12340000 0x40>; reg-shift = <2>; interrupts = < 10 >; pins = "uart1_rx", "uart1_tx"; };
Note that we should use the actual signal names, not package specific pad names. This way they have a high likelyhood to work for new packages too by just mapping the signals to the new package.
How would this handle the situation where you can mux a signal to multiple pins? IIRC omap3 and am335x can do funny stuff with the display pins like being able to map the blue bits to different pinblocks.
That's quite not true, in case of omap3 pins are labeled as R0-R7, B0-B7 and G0-G7; what changes is pixel format.
AM335x LCDC is completely different IP altogether and spec doesn't map Colors to pins. It barely maps bit0 from memory to pinX. Now you call it as a standard or legacy or may be due to SGX software, the pixel format we use is BGR (as in memory). It is completely depends on how you interface the pins to LCD (considering) Software support/requirement.
Thanks, Vaibhav
regards,
Koen
On Tue, Nov 22, 2011 at 6:54 PM, Tony Lindgren tony@atomide.com wrote:
Note that with device tree things get simpler for muxing as we can get rid of the hardcoded grouping of pins in mux drivers. Instead of hardcoded pingroups, the groups can be created dynamically based on what the driver DT entries have.
Yes, I know too little about DT to figure out how these should come in.
The reason why we want to avoid hardcoded pin groups is because trying to map all the pad combinations in the pinmux driver is not a scalable way to go. And it's not even possible at least on omaps because of the huge number of combinations with alternative pins and multiple packages.
Yes, that's a solid case!
FYI I'm playing with a DT based pinmux-simple.c driver that should be pretty generic and work for all kinds of hardware hopefully.
I love it.
It will be few days before I can post anything though, there are some pinctrl fwk issues to deal with first. Like the hardcoded pinmux_maps that assumes that dev entries are static. This means that multiple instances of pinmux drivers won't work..
I'm not following, but I guess I will understand when I see the patches. The idea behind the current map concept is that you get either a string or struct device * to identify the pin controller and mapped device, that's as far as I thought it out, sorry for any inherent limitations, they're not intentional...
Thanks, Linus Walleij
Hi,
* Linus Walleij linus.walleij@linaro.org [111124 01:29]:
On Tue, Nov 22, 2011 at 6:54 PM, Tony Lindgren tony@atomide.com wrote:
Note that with device tree things get simpler for muxing as we can get rid of the hardcoded grouping of pins in mux drivers. Instead of hardcoded pingroups, the groups can be created dynamically based on what the driver DT entries have.
Yes, I know too little about DT to figure out how these should come in.
The reason why we want to avoid hardcoded pin groups is because trying to map all the pad combinations in the pinmux driver is not a scalable way to go. And it's not even possible at least on omaps because of the huge number of combinations with alternative pins and multiple packages.
Yes, that's a solid case!
So far it seems that device tree simplifies things here quite a bit in at least two ways:
- We by default have automatically generated 1:1 mapping of devices to groups (of course others can be added too)
- We should be able to support new SoC packages with different pin on existing kernels, like distro kernels, just by modifying the the device tree data ;)
FYI I'm playing with a DT based pinmux-simple.c driver that should be pretty generic and work for all kinds of hardware hopefully.
I love it.
Still need few more days with these patches..
It will be few days before I can post anything though, there are some pinctrl fwk issues to deal with first. Like the hardcoded pinmux_maps that assumes that dev entries are static. This means that multiple instances of pinmux drivers won't work..
I'm not following, but I guess I will understand when I see the patches. The idea behind the current map concept is that you get either a string or struct device * to identify the pin controller and mapped device, that's as far as I thought it out, sorry for any inherent limitations, they're not intentional...
Yeah we can sort those out afterwards. We should probably pass over the static board specific mapping as platform_data to the pinmux device and make it be part of struct pinctrl_dev. Then new driver instances can have their own pctldev->mapping and we can support both platform_data and device tree based drivers on the same system. Anyways, I'll try to get the initial patches working with just one instance to start with so we have something to play with.
Regards,
Tony
On Thu, Nov 24, 2011 at 8:54 PM, Tony Lindgren tony@atomide.com wrote:
We should probably pass over the static board specific mapping as platform_data to the pinmux device and make it be part of struct pinctrl_dev. Then new driver instances can have their own pctldev->mapping and we can support both platform_data and device tree based drivers on the same system.
That sounds like a real good idea and I think it'll work fine.
You can use the map in mach-u300/core.c as guinea pig for refactoring if you like. I think that's the only map that's in-tree ftm.
Thanks, Linus Walleij
On Mon, Nov 14, 2011 at 1:40 PM, Rajendra Nayak rnayak@ti.com wrote:
(...)
- The OMAP control module has a device-control sub-module
- which handles all pin/padmuxing for OMAP. The sub-module
- is further split into a 'core' instance within the CORE
- powerdomain and a 'wkup' instance within the WAKEUP
- powerdomain (which is always powered on)
(...)
+/* omap4 core pads */ +static const struct pinctrl_pin_desc omap4_core_pads[] = {
- PINCTRL_PIN(0, "c12"),
- PINCTRL_PIN(1, "d12"),
- PINCTRL_PIN(2, "c13"),
(...)
+/* omap4 wkup pads */ +static const struct pinctrl_pin_desc omap4_wkup_pads[] = {
- PINCTRL_PIN(0, "c12"),
- PINCTRL_PIN(1, "d12"),
- PINCTRL_PIN(2, "c13"),
(...)
I have a hard time wrapping my head around why you need to define all the same pads twice and adding two almost identical pin controllers.
Probably it's just me lacking understanding ...
My recent thinking about wakeups is rather (built on experience with the hardware I've seen) that you define a number of states for each pinmux group so it can be set in say active, low_power and sleep state, which will reconfigure the pads associated with each mux for respective mode.
In the current pin config patch set we also have a PIN_CONFIG_WAKEUP property that can be set on a per-pin basis to say configure that a specific pin shall trigger a wakeup of the system if it's in sleep state.
So my idea is that when you switch states of pin muxes, say from active to sleeping, the subsystem will call the driver to reprogram the pins to sleep mode, typically grounding some pins, biasing some other pins and setting the wakeup property of some pins.
So is this really two different sets of registers for the same pads at totally different places in memory, or is this some way of modeling different modes for the same pads? If it's the latter we need some better abstraction than doing it all twice.
Yours, Linus Walleij
On Thursday 17 November 2011 01:50 PM, Linus Walleij wrote:
On Mon, Nov 14, 2011 at 1:40 PM, Rajendra Nayakrnayak@ti.com wrote:
(...)
- The OMAP control module has a device-control sub-module
- which handles all pin/padmuxing for OMAP. The sub-module
- is further split into a 'core' instance within the CORE
- powerdomain and a 'wkup' instance within the WAKEUP
- powerdomain (which is always powered on)
(...)
+/* omap4 core pads */ +static const struct pinctrl_pin_desc omap4_core_pads[] = {
PINCTRL_PIN(0, "c12"),
PINCTRL_PIN(1, "d12"),
PINCTRL_PIN(2, "c13"),
(...)
+/* omap4 wkup pads */ +static const struct pinctrl_pin_desc omap4_wkup_pads[] = {
PINCTRL_PIN(0, "c12"),
PINCTRL_PIN(1, "d12"),
PINCTRL_PIN(2, "c13"),
(...)
I have a hard time wrapping my head around why you need to define all the same pads twice and adding two almost identical pin controllers.
Oops, I seem to have completely messed up with the omap4_wkup_pads table.. It should have been just these pins from the table
+ PINCTRL_PIN(50, "h4"), + PINCTRL_PIN(51, "j2"), + PINCTRL_PIN(52, "g2"), + PINCTRL_PIN(53, "j1"), + PINCTRL_PIN(54, "k1"), + PINCTRL_PIN(55, "ag9"), + PINCTRL_PIN(56, "af9"), + PINCTRL_PIN(57, "ah6"), + PINCTRL_PIN(58, "ag8"), + PINCTRL_PIN(59, "ad1"), + PINCTRL_PIN(60, "ad2"), + PINCTRL_PIN(61, "ad3"), + PINCTRL_PIN(62, "ad4"), + PINCTRL_PIN(63, "ac2"), + PINCTRL_PIN(64, "ac3"), + PINCTRL_PIN(65, "ag7"), + PINCTRL_PIN(66, "ae7"), + PINCTRL_PIN(67, "af7"), + PINCTRL_PIN(68, "ah7"), + PINCTRL_PIN(69, "ag6"), + PINCTRL_PIN(70, "af8"), + PINCTRL_PIN(71, "ae8"), + PINCTRL_PIN(72, "ah2"), + PINCTRL_PIN(73, "ag1"), + PINCTRL_PIN(74, "ae3"), + PINCTRL_PIN(75, "ah1"), + PINCTRL_PIN(76, "ae1"), + PINCTRL_PIN(77, "ae2"),
But somehow I ended up with having the first 49 pins duplicated from the omap4_core_pads table. Will fix up, and sorry for all the confusion.
Probably it's just me lacking understanding ...
My recent thinking about wakeups is rather (built on experience with the hardware I've seen) that you define a number of states for each pinmux group so it can be set in say active, low_power and sleep state, which will reconfigure the pads associated with each mux for respective mode.
In the current pin config patch set we also have a PIN_CONFIG_WAKEUP property that can be set on a per-pin basis to say configure that a specific pin shall trigger a wakeup of the system if it's in sleep state.
So my idea is that when you switch states of pin muxes, say from active to sleeping, the subsystem will call the driver to reprogram the pins to sleep mode, typically grounding some pins, biasing some other pins and setting the wakeup property of some pins.
So is this really two different sets of registers for the same pads at totally different places in memory, or is this some way of modeling different modes for the same pads? If it's the latter we need some better abstraction than doing it all twice.
These are different pads/pins and controlled through different set of registers.
Yours, Linus Walleij
Add omap4 pinmux platform devices for core-pinmux and wkup-pinmux.
Signed-off-by: Rajendra Nayak rnayak@ti.com --- arch/arm/mach-omap2/devices.c | 43 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index c15cfad..bd9fff6 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -671,6 +671,48 @@ static void omap_init_vout(void) static inline void omap_init_vout(void) {} #endif
+static struct resource pinmux_core_resources[] = { + { + .start = 0x4a100040, + .end = 0x4a100040 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource pinmux_wkup_resources[] = { + { + .start = 0x4a31e040, + .end = 0x4a31e040 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device omap4_pinmux_core_device = { + .name = "pinmux-omap", + .id = 0, + .num_resources = ARRAY_SIZE(pinmux_core_resources), + .resource = pinmux_core_resources, +}; + +static struct platform_device omap4_pinmux_wkup_device = { + .name = "pinmux-omap", + .id = 1, + .num_resources = ARRAY_SIZE(pinmux_wkup_resources), + .resource = pinmux_wkup_resources, +}; + +static struct platform_device *omap4_pinmux_devices[] = { + &omap4_pinmux_core_device, + &omap4_pinmux_wkup_device, +}; + +static inline void omap_init_pinmux(void) +{ + if (cpu_is_omap44xx()) + platform_add_devices(omap4_pinmux_devices, + ARRAY_SIZE(omap4_pinmux_devices)); +} + /*-------------------------------------------------------------------------*/
static int __init omap2_init_devices(void) @@ -690,6 +732,7 @@ static int __init omap2_init_devices(void) omap_init_sham(); omap_init_aes(); omap_init_vout(); + omap_init_pinmux();
return 0; }
Register pinmux mappings for SDP and PANDA from board files. Retain the existing mux configurations as they do pull up/down configuration as well which are not handled currently.
Signed-off-by: Rajendra Nayak rnayak@ti.com --- arch/arm/mach-omap2/board-4430sdp.c | 10 ++++++++++ arch/arm/mach-omap2/board-omap4panda.c | 11 +++++++++++ 2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 5156468..136597e 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -25,6 +25,7 @@ #include <linux/regulator/fixed.h> #include <linux/leds.h> #include <linux/leds_pwm.h> +#include <linux/pinctrl/machine.h>
#include <mach/hardware.h> #include <mach/omap4-common.h> @@ -942,6 +943,12 @@ static void omap4_sdp4430_wifi_init(void) platform_device_register(&omap_vwlan_device); }
+/* Pinmux settings */ +static struct pinmux_map omap_pinmux_map[] = { + PINMUX_MAP_PRIMARY_SYS_HOG("HDMI", "hdmi"), + PINMUX_MAP_PRIMARY_SYS_HOG("SDMMC5", "sdmmc5"), +}; + static void __init omap_4430sdp_init(void) { int status; @@ -950,6 +957,9 @@ static void __init omap_4430sdp_init(void) if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; omap4_mux_init(board_mux, NULL, package); + /* Initialize pinmuxing */ + pinmux_register_mappings(omap_pinmux_map, + ARRAY_SIZE(omap_pinmux_map));
omap4_i2c_init(); omap_sfh7741prox_init(); diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index a8c2c42..05c7927 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -28,6 +28,7 @@ #include <linux/regulator/machine.h> #include <linux/regulator/fixed.h> #include <linux/wl12xx.h> +#include <linux/pinctrl/machine.h>
#include <mach/hardware.h> #include <mach/omap4-common.h> @@ -548,6 +549,13 @@ void omap4_panda_display_init(void) omap_display_init(&omap4_panda_dss_data); }
+/* Pinmux settings */ +static struct pinmux_map omap_pinmux_map[] = { + PINMUX_MAP_PRIMARY_SYS_HOG("HDMI", "hdmi"), + PINMUX_MAP_PRIMARY_SYS_HOG("SDMMC5", "sdmmc5"), + PINMUX_MAP_PRIMARY_SYS_HOG("DISPC2", "dispc2"), +}; + static void __init omap4_panda_init(void) { int package = OMAP_PACKAGE_CBS; @@ -555,6 +563,9 @@ static void __init omap4_panda_init(void) if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; omap4_mux_init(board_mux, NULL, package); + /* Initialize pinmuxing */ + pinmux_register_mappings(omap_pinmux_map, + ARRAY_SIZE(omap_pinmux_map));
if (wl12xx_set_platform_data(&omap_panda_wlan_data)) pr_err("error setting wl12xx data\n");
On Mon, Nov 14, 2011 at 1:40 PM, Rajendra Nayak rnayak@ti.com wrote:
These are still early patches, but I wanted to get some feedback on if I am heading in the right direction. Hence sharing these in the current form.
The platform pieces look good! We need to discuss about the driver and needed infrastructure.
Yours, Linus Walleij