Skip to contentSkip to conversation

mfd: omap: control: core system control driver

PATCH New Konstantin Baydarov 4 participants 10 messages Jul 25, 2012 – Aug 29, 2012

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

This patch introduces a MFD core device driver for OMAP system control module.

The control module allows software control of various static modes supported by the device. It is composed of two control submodules: general control module and device (padconfiguration) control module.

Device driver is probed with postcore_initcall. Control module register CONTROL_STATUS that is needed by omap_type() is early mapped by postcore_initcall_sync.

---
 .../devicetree/bindings/mfd/omap_control.txt       |   32 ++++
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/plat-omap/Kconfig                         |    4 +
 drivers/mfd/Kconfig                                |    6 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  162 ++++++++++++++++++++
 include/linux/mfd/omap_control.h                   |   35 +++++
 7 files changed, 241 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/omap_control.txt
 create mode 100644 drivers/mfd/omap-control-core.c
 create mode 100644 include/linux/mfd/omap_control.h
Documentation/devicetree/bindings/mfd/omap_control.txt new file +32 -0
new file mode 100644
index 0000000..a9dca9e
@@ -0,0 +1,32 @@
+* Texas Instrument OMAP System Control Module (SCM) bindings
+
+The control module allows software control of various static modes supported by
+the device. The control module controls the settings of various device  modules
+through register configuration and internal signals. It also controls  the  pad
+configuration, pin functional multiplexing, and the routing of internal signals
+(such as PRCM  signals or DMA requests)  to output pins configured for hardware
+observability.
+
+Required properties:
+- compatible : Should be:
+  - "ti,omap3-control" for OMAP3 support
+  - "ti,omap4-control" for OMAP4 support
+  - "ti,omap5-control" for OMAP5 support
+
+OMAP specific properties:
+- ti,hwmods: Name of the hwmod associated to the control module:
+  Should be "ctrl_module_core";
+
+OMAP CONTROL_STATUS register:
+reg = <0x4A0022C4 0x4>; /* CONTROL_STATUS register */
+
+Examples:
+ctrl_module_core: ctrl_module_core at 4A0022C4 {
+	compatible = "ti,omap4-control";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/* ranges; */
+	ti,hwmods = "ctrl_module_core";
+	reg = <0x4A0022C4 0x4>; /* CONTROL_STATUS register */
+};
+
arch/arm/mach-omap2/Kconfig +1 -0
index dd0fbf7..1235576 100644
@@ -59,6 +59,7 @@ config ARCH_OMAP4
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
 	select PM_RUNTIME if CPU_IDLE
+	select ARCH_HAS_CONTROL_MODULE
 	select PM_OPP if PM
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select ARM_CPU_SUSPEND if PM
arch/arm/plat-omap/Kconfig +4 -0
index dd36eba..2b2c9d8 100644
@@ -5,6 +5,10 @@ menu "TI OMAP Common Features"
 config ARCH_OMAP_OTG
 	bool
 
+config ARCH_HAS_CONTROL_MODULE
+	bool
+	select MFD_OMAP_CONTROL
+
 choice
 	prompt "OMAP System Type"
 	default ARCH_OMAP2PLUS
drivers/mfd/Kconfig +6 -0
index 92144ed..530ac60 100644
@@ -823,6 +823,12 @@ config MFD_WL1273_CORE
 	  driver connects the radio-wl1273 V4L2 module and the wl1273
 	  audio codec.
 
+config MFD_OMAP_CONTROL
+	bool "Texas Instruments OMAP System control module"
+	depends on ARCH_HAS_CONTROL_MODULE
+	help
+	  This is the core driver for system control module.
+
 config MFD_OMAP_USB_HOST
 	bool "Support OMAP USBHS core driver"
 	depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
drivers/mfd/Makefile +1 -0
index 75f6ed6..b037443 100644
@@ -107,6 +107,7 @@ obj-$(CONFIG_MFD_TPS6586X)	+= tps6586x.o
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
+obj-$(CONFIG_MFD_OMAP_CONTROL)	+= omap-control-core.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
drivers/mfd/omap-control-core.c new file +162 -0

162 lines not on this page · raw message

include/linux/mfd/omap_control.h new file +35 -0
new file mode 100644
index 0000000..ee90a38
@@ -0,0 +1,35 @@
+/*
+ * OMAP system control module header file
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   J Keerthy <[email protected]>
+ *   Moiz Sonasath <[email protected]>
+ *   Abraham, Kishon Vijay <[email protected]>
+ *   Eduardo Valentin <[email protected]>
+ *   Konstantin Baydarov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_CONTROL_H
+#define __DRIVERS_OMAP_CONTROL_H
+
+#ifdef CONFIG_MFD_OMAP_CONTROL
+u32 omap_control_status_read(void);
+#else
+static inline u32 omap_control_status_read(void)
+{
+	return 0;
+}
+#endif
+
+#endif /* __DRIVERS_OMAP_CONTROL_H */
Signature · 1 line
1.7.7.6
#1 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

Hi,

Quoted 9 lines · Konstantin Baydarov

This patch introduces a MFD core device driver for OMAP system control module.

The control module allows software control of various static modes supported by the device. It is composed of two control submodules: general control module and device (padconfiguration) control module.

Quoted 8 lines

Device driver is probed with postcore_initcall. Control module register CONTROL_STATUS that is needed by omap_type() is early mapped by postcore_initcall_sync.

I believe this and the next 3 were authored by Eduardo. Also missing his

Quoted 1 line

From tag.

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120725/ee160db6/attachment.sig>
maintainer
#2 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

In reply to Konstantin Baydarov

drivers/mfd/omap-control-core.c line 45

Quoted 5 lines · Konstantin Baydarov
drivers/mfd/omap-control-core.c new file +5 -0
+
+u32 omap_control_status_read(void)
+{
+	return __raw_readl(omap_control_base);
+}

Ah OK it's changed here.. Sorry I was looking at the older version.

Quoted 12 lines
drivers/mfd/omap-control-core.c new file +12 -0
+void __init of_omap_control_init(const struct of_device_id *matches)
+{
+	struct device_node *np;
+	struct property *pp = 0;
+
+	for_each_matching_node(np, matches) {
+		pp = of_find_property(np, "reg", NULL);
+		if(pp) {
+			omap_control_phys_base = (unsigned long)be32_to_cpup(pp->value);
+			omap_control_mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
+			/*
+			 * Map control module register CONTROL_STATUS register:

drivers/mfd/omap-control-core.c line 135

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+			 * omap24xx - OMAP24XX_CONTROL_STATUS
+			 * am33xx   - AM33XX_CONTROL_STATUS
+			 * omap34xx - OMAP343X_CONTROL_STATUS
+			 * omap44xx - OMAP4_CTRL_MODULE_CORE_STATUS
+			 * omap54xx - OMAP5XXX_CONTROL_STATUS
+			 */
+			omap_control_base = ioremap(omap_control_phys_base, omap_control_mapsize);
+		}
+	}
+}

You should probably add a function for setting omap_control_base separately from *set_globals* in arch/arm/mach-omap2/common.c. That way it's initialized early for id.c, and you can initialize everything else later as regular device drivers.

FYI, we want to initialize as much as possible late so we have proper debugging console set up in case things go wrong.

Regards,

Tony

maintainer
#3 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

Quoted 38 lines · Tony Lindgren

drivers/mfd/omap-control-core.c line 45

Quoted 5 lines · Konstantin Baydarov
drivers/mfd/omap-control-core.c new file +5 -0
+
+u32 omap_control_status_read(void)
+{
+	return __raw_readl(omap_control_base);
+}

Ah OK it's changed here.. Sorry I was looking at the older version.

Quoted 12 lines
drivers/mfd/omap-control-core.c new file +12 -0
+void __init of_omap_control_init(const struct of_device_id *matches)
+{
+	struct device_node *np;
+	struct property *pp = 0;
+
+	for_each_matching_node(np, matches) {
+		pp = of_find_property(np, "reg", NULL);
+		if(pp) {
+			omap_control_phys_base = (unsigned long)be32_to_cpup(pp->value);
+			omap_control_mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
+			/*
+			 * Map control module register CONTROL_STATUS register:

drivers/mfd/omap-control-core.c line 135

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+			 * omap24xx - OMAP24XX_CONTROL_STATUS
+			 * am33xx   - AM33XX_CONTROL_STATUS
+			 * omap34xx - OMAP343X_CONTROL_STATUS
+			 * omap44xx - OMAP4_CTRL_MODULE_CORE_STATUS
+			 * omap54xx - OMAP5XXX_CONTROL_STATUS
+			 */
+			omap_control_base = ioremap(omap_control_phys_base, omap_control_mapsize);
+		}
+	}
+}

You should probably add a function for setting omap_control_base separately from *set_globals* in arch/arm/mach-omap2/common.c. That way it's initialized early for id.c, and you can initialize everything else later as regular device drivers.

Quoted 2 lines

FYI, we want to initialize as much as possible late so we have proper debugging console set up in case things go wrong.

Hmm it seems that omap_control_base is now only initialized for DT boot case? This will break booting on almost all systems..

Tony

maintainer
#4 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

Quoted 39 lines · Tony Lindgren
Quoted 38 lines · Tony Lindgren

drivers/mfd/omap-control-core.c line 45

Quoted 5 lines · Konstantin Baydarov
drivers/mfd/omap-control-core.c new file +5 -0
+
+u32 omap_control_status_read(void)
+{
+	return __raw_readl(omap_control_base);
+}

Ah OK it's changed here.. Sorry I was looking at the older version.

Quoted 12 lines
drivers/mfd/omap-control-core.c new file +12 -0
+void __init of_omap_control_init(const struct of_device_id *matches)
+{
+	struct device_node *np;
+	struct property *pp = 0;
+
+	for_each_matching_node(np, matches) {
+		pp = of_find_property(np, "reg", NULL);
+		if(pp) {
+			omap_control_phys_base = (unsigned long)be32_to_cpup(pp->value);
+			omap_control_mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
+			/*
+			 * Map control module register CONTROL_STATUS register:

drivers/mfd/omap-control-core.c line 135

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+			 * omap24xx - OMAP24XX_CONTROL_STATUS
+			 * am33xx   - AM33XX_CONTROL_STATUS
+			 * omap34xx - OMAP343X_CONTROL_STATUS
+			 * omap44xx - OMAP4_CTRL_MODULE_CORE_STATUS
+			 * omap54xx - OMAP5XXX_CONTROL_STATUS
+			 */
+			omap_control_base = ioremap(omap_control_phys_base, omap_control_mapsize);
+		}
+	}
+}

You should probably add a function for setting omap_control_base separately from *set_globals* in arch/arm/mach-omap2/common.c. That way it's initialized early for id.c, and you can initialize everything else later as regular device drivers.

Quoted 5 lines
Quoted 2 lines

FYI, we want to initialize as much as possible late so we have proper debugging console set up in case things go wrong.

Hmm it seems that omap_control_base is now only initialized for DT boot case? This will break booting on almost all systems..

Looking at things more, looks like omap_type() is getting called early from timer.c. So maybe just let set_globals initialize omap_control_base and let omap_type() read that directly. That way the SCM core driver can behave like a regular device driver and it does not need to be initialized early.

Regards,

Tony

#5 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

Hi, Tony.

Quoted 40 lines · Tony Lindgren
Quoted 39 lines · Tony Lindgren
Quoted 38 lines · Tony Lindgren

drivers/mfd/omap-control-core.c line 45

Quoted 5 lines · Konstantin Baydarov
drivers/mfd/omap-control-core.c new file +5 -0
+
+u32 omap_control_status_read(void)
+{
+	return __raw_readl(omap_control_base);
+}

Ah OK it's changed here.. Sorry I was looking at the older version.

Quoted 12 lines
drivers/mfd/omap-control-core.c new file +12 -0
+void __init of_omap_control_init(const struct of_device_id *matches)
+{
+	struct device_node *np;
+	struct property *pp = 0;
+
+	for_each_matching_node(np, matches) {
+		pp = of_find_property(np, "reg", NULL);
+		if(pp) {
+			omap_control_phys_base = (unsigned long)be32_to_cpup(pp->value);
+			omap_control_mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
+			/*
+			 * Map control module register CONTROL_STATUS register:

drivers/mfd/omap-control-core.c line 135

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+			 * omap24xx - OMAP24XX_CONTROL_STATUS
+			 * am33xx   - AM33XX_CONTROL_STATUS
+			 * omap34xx - OMAP343X_CONTROL_STATUS
+			 * omap44xx - OMAP4_CTRL_MODULE_CORE_STATUS
+			 * omap54xx - OMAP5XXX_CONTROL_STATUS
+			 */
+			omap_control_base = ioremap(omap_control_phys_base, omap_control_mapsize);
+		}
+	}
+}

You should probably add a function for setting omap_control_base separately from *set_globals* in arch/arm/mach-omap2/common.c. That way it's initialized early for id.c, and you can initialize everything else later as regular device drivers.

FYI, we want to initialize as much as possible late so we have proper debugging console set up in case things go wrong.

Quoted 7 lines
Quoted 2 lines

Hmm it seems that omap_control_base is now only initialized for DT boot case? This will break booting on almost all systems..

Looking at things more, looks like omap_type() is getting called early from timer.c. So maybe just let set_globals initialize omap_control_base and let omap_type() read that directly. That way the SCM core driver can behave like a regular device driver and it does not need to be initialized early.

Yes, omap_type() is called very early , that is why I'm using early_initcall for omap_control_base initialization.

Do you mean following?:
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)

{
    if (omap2_globals->ctrl)
        omap2_ctrl_base = omap2_globals->ctrl;

    if (omap2_globals->ctrl_pad)
        omap4_ctrl_pad_base = omap2_globals->ctrl_pad;

    omap_control_base = omap2_ctrl_base;  // this line is added
}

Or you suggest to move
void __init of_omap_control_init(const struct of_device_id *matches)

{
    struct device_node *np;
    struct property *pp = 0;

    for_each_matching_node(np, matches) {
        pp = of_find_property(np, "reg", NULL);
        if(pp) {
            omap_control_phys_base = (unsigned long)be32_to_cpup(pp->value);
            omap_control_mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
            /*
             * Map control module register CONTROL_STATUS register:
             * omap24xx - OMAP24XX_CONTROL_STATUS
             * am33xx   - AM33XX_CONTROL_STATUS
             * omap34xx - OMAP343X_CONTROL_STATUS
             * omap44xx - OMAP4_CTRL_MODULE_CORE_STATUS
             * omap54xx - OMAP5XXX_CONTROL_STATUS
             */
            omap_control_base = ioremap(omap_control_phys_base, omap_control_mapsize);
        }
    }
}

into omap2_set_globals_control() ?

Also if we move omap_control_base initialization to omap2_set_globals_control(), than the initialization routine of drivers/mfd/omap-control-core.c become empty, because omap_control_base is the only thing that is initialized in omap-control-core driver.

BR,
Konstantin Baydarov.

Quoted 8 lines

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer
#6 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

Quoted 7 lines · Konstantin Baydarov

On 08/08/2012 06:39 PM, Tony Lindgren wrote:

Yes, omap_type() is called very early , that is why I'm using early_initcall for omap_control_base initialization.

Do you mean following?:
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)

Quoted 9 lines
{
    if (omap2_globals->ctrl)
        omap2_ctrl_base = omap2_globals->ctrl;

    if (omap2_globals->ctrl_pad)
        omap4_ctrl_pad_base = omap2_globals->ctrl_pad;

    omap_control_base = omap2_ctrl_base;  // this line is added
}

OK so we already have set_globals_control, but we're not using it.. No need for this line is added above.

Let's do the attached clean-up patch and just leave omap_control_base out of the driver for now as it's not currently needed there.

If omap_control_base is needed in the driver, then we need to pass it in the platform_data to the driver for the non-DT boot case, or parse it from DT like you're doing.

Regards,

Tony

From: Tony Lindgren <[email protected]>
Date: Wed, 8 Aug 2012 23:13:03 -0700
Subject: [PATCH] ARM: OMAP2+: Change omap_type() to use omap_ctrl_base_get()

We have the SoC specific ctrl_base already initialized in set_globals.

arch/arm/mach-omap2/id.c +9 -17
@@ -42,28 +42,20 @@ int omap_type(void)
 {
 	u32 val = 0;
 
-	if (cpu_is_omap24xx()) {
-		val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
-	} else if (soc_is_am33xx()) {
-		val = omap_ctrl_readl(AM33XX_CONTROL_STATUS);
-	} else if (cpu_is_omap34xx()) {
-		val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
-	} else if (cpu_is_omap44xx()) {
-		val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STATUS);
-	} else if (soc_is_omap54xx()) {
-		val = omap_ctrl_readl(OMAP5XXX_CONTROL_STATUS);
+	val = __raw_readl(omap_ctrl_base_get());
+	if (!val) {
+		pr_err("Cannot detect omap type!\n");
+		return 0;
+	}
+
+	if (soc_is_omap54xx()) {
 		val &= OMAP5_DEVICETYPE_MASK;
 		val >>= 6;
-		goto out;
 	} else {
-		pr_err("Cannot detect omap type!\n");
-		goto out;
+		val &= OMAP2_DEVICETYPE_MASK;
+		val >>= 8;
 	}
 
-	val &= OMAP2_DEVICETYPE_MASK;
-	val >>= 8;
-
-out:
 	return val;
 }
 EXPORT_SYMBOL(omap_type);
#7 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

In reply to Konstantin Baydarov

Hi, Tony.

Quoted 4 lines · Konstantin Baydarov

Yes, omap_type() is called very early , that is why I'm using early_initcall for omap_control_base initialization.

Do you mean following?:
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)

Quoted 9 lines
{
    if (omap2_globals->ctrl)
        omap2_ctrl_base = omap2_globals->ctrl;

    if (omap2_globals->ctrl_pad)
        omap4_ctrl_pad_base = omap2_globals->ctrl_pad;

    omap_control_base = omap2_ctrl_base;  // this line is added
}

Sorry for the confusion - the code above isn't correct. First, as omap-control-core.c driver maps only control module status register the omap_control_base should be renamed to omap_control_status_reg:

drivers/mfd/omap-control-core.c +1 -1
@@ -35,13 +35,15 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
-void __iomem *omap_control_base;
+void __iomem *omap_control_status_reg;
 unsigned long omap_control_phys_base;
 size_t omap_control_mapsize;
 
 u32 omap_control_status_read(void)
 
 

Then, if you want to move omap_control_status_reg(omap_control_base) initialization to the omap2_set_globals_control(), it can be done following way:

arch/arm/mach-omap2/control.c +16 -0
@@ -149,6 +149,8 @@ static struct omap3_control_regs control_context;
 #define OMAP_CTRL_REGADDR(reg)		(omap2_ctrl_base + (reg))
 #define OMAP4_CTRL_PAD_REGADDR(reg)	(omap4_ctrl_pad_base + (reg))
 
+extern void __iomem *omap_control_status_reg;
+
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
 	if (omap2_globals->ctrl)
@@ -156,6 +158,20 @@ void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 
 	if (omap2_globals->ctrl_pad)
 		omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
+
+	omap_control_status_reg = omap2_ctrl_base;
+	if (cpu_is_omap24xx())
+		omap_control_status_reg += OMAP24XX_CONTROL_STATUS;
+	else if (soc_is_am33xx())
+		omap_control_status_reg += AM33XX_CONTROL_STATUS;
+	else if (cpu_is_omap34xx())
+		omap_control_status_reg += OMAP343X_CONTROL_STATUS;
+	else if (cpu_is_omap44xx())
+		omap_control_status_reg += OMAP4_CTRL_MODULE_CORE_STATUS;
+	else if (soc_is_omap54xx())
+		omap_control_status_reg += OMAP5XXX_CONTROL_STATUS;
+	else
+		omap_control_status_reg = 0;
 }
 
 void __iomem *omap_ctrl_base_get(void)

Then omap_type() can be changed:

arch/arm/mach-omap2/id.c +11 -15
index 8018cad..916b3f6 100644
@@ -39,31 +39,27 @@ unsigned int omap_rev(void)
 }
 EXPORT_SYMBOL(omap_rev);
 
+extern void __iomem *omap_control_status_reg;
+
 int omap_type(void)
 {
 	u32 val = 0;
 
-	if (cpu_is_omap24xx()) {
-		val = omap_control_status_read();
-	} else if (soc_is_am33xx()) {
-		val = omap_control_status_read();
-	} else if (cpu_is_omap34xx()) {
-		val = omap_control_status_read();
-	} else if (cpu_is_omap44xx()) {
+	if(!omap_control_status_reg) {
+		pr_err("Cannot detect omap type!\n");
+		goto out;
+	}
+
+	if(!soc_is_omap54xx()) {
 		val = omap_control_status_read();
-	} else if (soc_is_omap54xx()) {
+		val &= OMAP2_DEVICETYPE_MASK;
+		val >>= 8;
+	} else {
 		val = omap_control_status_read();
 		val &= OMAP5_DEVICETYPE_MASK;
 		val >>= 6;
-		goto out;
-	} else {
-		pr_err("Cannot detect omap type!\n");
-		goto out;
 	}
 
-	val &= OMAP2_DEVICETYPE_MASK;
-	val >>= 8;
-
 out:
 	return val;
 }

BR,
Konstantin Baydarov.

Quoted 42 lines

Or you suggest to move
void __init of_omap_control_init(const struct of_device_id *matches)

{
    struct device_node *np;
    struct property *pp = 0;

    for_each_matching_node(np, matches) {
        pp = of_find_property(np, "reg", NULL);
        if(pp) {
            omap_control_phys_base = (unsigned long)be32_to_cpup(pp->value);
            omap_control_mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
            /*
             * Map control module register CONTROL_STATUS register:
             * omap24xx - OMAP24XX_CONTROL_STATUS
             * am33xx   - AM33XX_CONTROL_STATUS
             * omap34xx - OMAP343X_CONTROL_STATUS
             * omap44xx - OMAP4_CTRL_MODULE_CORE_STATUS
             * omap54xx - OMAP5XXX_CONTROL_STATUS
             */
            omap_control_base = ioremap(omap_control_phys_base, omap_control_mapsize);
        }
    }
}

into omap2_set_globals_control() ?

Also if we move omap_control_base initialization to omap2_set_globals_control(), than the initialization routine of drivers/mfd/omap-control-core.c become empty, because omap_control_base is the only thing that is initialized in omap-control-core driver.

BR,
Konstantin Baydarov.

Quoted 7 lines

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer
#8 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

Quoted 11 lines · Konstantin Baydarov

Hi, Tony.

Quoted 8 lines · Konstantin Baydarov

Yes, omap_type() is called very early , that is why I'm using early_initcall for omap_control_base initialization.

Do you mean following?:
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)

{
    if (omap2_globals->ctrl)
        omap2_ctrl_base = omap2_globals->ctrl;
Quoted 6 lines
Quoted 5 lines
    if (omap2_globals->ctrl_pad)
        omap4_ctrl_pad_base = omap2_globals->ctrl_pad;

    omap_control_base = omap2_ctrl_base;  // this line is added
}

Sorry for the confusion - the code above isn't correct. First, as omap-control-core.c driver maps only control module status register the omap_control_base should be renamed to omap_control_status_reg:

Heh right :) And that makes the patch I posted wrong too.

Quoted 9 lines
(quoted diff) +5 -0
@@ -156,6 +158,20 @@ void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 
 	if (omap2_globals->ctrl_pad)
 		omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
+
+	omap_control_status_reg = omap2_ctrl_base;
+	if (cpu_is_omap24xx())
+		omap_control_status_reg += OMAP24XX_CONTROL_STATUS;
+	else if (soc_is_am33xx())

Review void __init omap2_set_globals_control(struct omap_globals *omap2_globals) · line 175

Quoted 10 lines
(quoted diff) +9 -0
+		omap_control_status_reg += AM33XX_CONTROL_STATUS;
+	else if (cpu_is_omap34xx())
+		omap_control_status_reg += OMAP343X_CONTROL_STATUS;
+	else if (cpu_is_omap44xx())
+		omap_control_status_reg += OMAP4_CTRL_MODULE_CORE_STATUS;
+	else if (soc_is_omap54xx())
+		omap_control_status_reg += OMAP5XXX_CONTROL_STATUS;
+	else
+		omap_control_status_reg = 0;
 }

We can get rid of the if else SoC check here too. And we can limit the control_status tinkering to id.c. Here's an updated clean-up patch.

Regards,

Tony

From: Tony Lindgren <[email protected]>
Date: Wed, 8 Aug 2012 23:13:03 -0700
Subject: [PATCH] ARM: OMAP2+: Initialize things for omap_type() to simplify
SoC detection

Let's rename omap2_set_globals_tap() to omap2_set_globals_id() and update the comments to remove old comments about map_io() as we don't need SoC detection for map_io() any longer.

Let's also initialize control_status_reg with omap2_set_globals_id() so we can avoid SoC tests every time omap_type() gets called.

Note that this patch sets the ti81xx to always return GP mode as the mode bits seem to be marked as reserved in ti81xx TRM.

arch/arm/mach-omap2/common.c +16 -2
index 069f972..64afeee 100644
@@ -31,7 +31,7 @@
 
 static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 {
-	omap2_set_globals_tap(omap2_globals);
+	omap2_set_globals_id(omap2_globals);
 	omap2_set_globals_sdrc(omap2_globals);
 	omap2_set_globals_control(omap2_globals);
 	omap2_set_globals_prcm(omap2_globals);
@@ -45,6 +45,8 @@ static struct omap_globals omap242x_globals = {
 	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
 	.sms	= OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE),
 	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
+	.ctrl_status	= OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE) +
+				OMAP24XX_CONTROL_STATUS,
 	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE),
 	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
 };
@@ -68,6 +70,8 @@ static struct omap_globals omap243x_globals = {
 	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
 	.sms	= OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE),
 	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
+	.ctrl_status	= OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE) +
+				OMAP24XX_CONTROL_STATUS,
 	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE),
 	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
 };
@@ -91,6 +95,8 @@ static struct omap_globals omap3_globals = {
 	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
 	.sms	= OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE),
 	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
+	.ctrl_status	= OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE) +
+				OMAP343X_CONTROL_STATUS,
 	.prm	= OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE),
 	.cm	= OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
 };
@@ -117,6 +123,8 @@ static struct omap_globals ti81xx_globals = {
 	.class  = OMAP343X_CLASS,
 	.tap    = OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE),
 	.ctrl   = OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE),
+	.ctrl_status   = OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE) +
+				TI81XX_CONTROL_STATUS,
 	.prm    = OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE),
 	.cm     = OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE),
 };
@@ -140,6 +148,8 @@ static struct omap_globals am33xx_globals = {
 	.class  = AM335X_CLASS,
 	.tap    = AM33XX_L4_WK_IO_ADDRESS(AM33XX_TAP_BASE),
 	.ctrl   = AM33XX_L4_WK_IO_ADDRESS(AM33XX_CTRL_BASE),
+	.ctrl_status = AM33XX_L4_WK_IO_ADDRESS(AM33XX_CTRL_BASE) +
+			AM33XX_CONTROL_STATUS,
 	.prm    = AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE),
 	.cm     = AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE),
 };
@@ -160,6 +170,8 @@ static struct omap_globals omap4_globals = {
 	.class	= OMAP443X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
 	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+	.ctrl_status	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE) +
+				OMAP4_CTRL_MODULE_CORE_STATUS,
 	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE),
 	.prm	= OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
 	.cm	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
@@ -183,6 +195,8 @@ static struct omap_globals omap5_globals = {
 	.class	= OMAP54XX_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
 	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
+	.ctrl_status	= OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE) +
+				OMAP5XXX_CONTROL_STATUS,
 	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE),
 	.prm	= OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE),
 	.cm	= OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
@@ -192,7 +206,7 @@ static struct omap_globals omap5_globals = {
 
 void __init omap2_set_globals_5xxx(void)
 {
-	omap2_set_globals_tap(&omap5_globals);
+	omap2_set_globals_id(&omap5_globals);
 	omap2_set_globals_control(&omap5_globals);
 	omap2_set_globals_prcm(&omap5_globals);
 }
arch/arm/mach-omap2/common.h +2 -1
index 1f65b18..a3cee8c 100644
@@ -168,6 +168,7 @@ struct omap_globals {
 	void __iomem	*sdrc;           /* SDRAM Controller */
 	void __iomem	*sms;            /* SDRAM Memory Scheduler */
 	void __iomem	*ctrl;           /* System Control Module */
+	void __iomem	*ctrl_status;	/* Control status register */
 	void __iomem	*ctrl_pad;	/* PAD Control Module */
 	void __iomem	*prm;            /* Power and Reset Management */
 	void __iomem	*cm;             /* Clock Management */
@@ -184,7 +185,7 @@ void omap2_set_globals_ti81xx(void);
 void omap2_set_globals_am33xx(void);
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
-void omap2_set_globals_tap(struct omap_globals *);
+void omap2_set_globals_id(struct omap_globals *);
 #if defined(CONFIG_SOC_HAS_OMAP2_SDRC)
 void omap2_set_globals_sdrc(struct omap_globals *);
 #else
arch/arm/mach-omap2/control.h +1 -0
index b8cdc85..cf92e06 100644
@@ -59,6 +59,7 @@
 
 /* TI81XX spefic control submodules */
 #define TI81XX_CONTROL_DEVCONF		0x600
+#define TI81XX_CONTROL_STATUS		0x040
 
 /* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
 
arch/arm/mach-omap2/id.c +20 -29

74 lines not on this page · raw message

#9 lore raw

PATCH v4 2/4 mfd: omap: control: core system control driver

In reply to Konstantin Baydarov

Hi Konstantin,

Quoted 165 lines · Konstantin Baydarov

This patch introduces a MFD core device driver for OMAP system control module.

The control module allows software control of various static modes supported by the device. It is composed of two control submodules: general control module and device (padconfiguration) control module.

Device driver is probed with postcore_initcall. Control module register CONTROL_STATUS that is needed by omap_type() is early mapped by postcore_initcall_sync.

---
 .../devicetree/bindings/mfd/omap_control.txt       |   32 ++++
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/plat-omap/Kconfig                         |    4 +
 drivers/mfd/Kconfig                                |    6 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  162 ++++++++++++++++++++
 include/linux/mfd/omap_control.h                   |   35 +++++
 7 files changed, 241 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/omap_control.txt
 create mode 100644 drivers/mfd/omap-control-core.c
 create mode 100644 include/linux/mfd/omap_control.h
Documentation/devicetree/bindings/mfd/omap_control.txt new file +32 -0
new file mode 100644
index 0000000..a9dca9e
@@ -0,0 +1,32 @@
+* Texas Instrument OMAP System Control Module (SCM) bindings
+
+The control module allows software control of various static modes supported by
+the device. The control module controls the settings of various device  modules
+through register configuration and internal signals. It also controls  the  pad
+configuration, pin functional multiplexing, and the routing of internal signals
+(such as PRCM  signals or DMA requests)  to output pins configured for hardware
+observability.
+
+Required properties:
+- compatible : Should be:
+  - "ti,omap3-control" for OMAP3 support
+  - "ti,omap4-control" for OMAP4 support
+  - "ti,omap5-control" for OMAP5 support
+
+OMAP specific properties:
+- ti,hwmods: Name of the hwmod associated to the control module:
+  Should be "ctrl_module_core";
+
+OMAP CONTROL_STATUS register:
+reg = <0x4A0022C4 0x4>; /* CONTROL_STATUS register */
+
+Examples:
+ctrl_module_core: ctrl_module_core at 4A0022C4 {
+	compatible = "ti,omap4-control";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/* ranges; */
+	ti,hwmods = "ctrl_module_core";
+	reg = <0x4A0022C4 0x4>; /* CONTROL_STATUS register */
+};
+
arch/arm/mach-omap2/Kconfig +1 -0
index dd0fbf7..1235576 100644
@@ -59,6 +59,7 @@ config ARCH_OMAP4
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
 	select PM_RUNTIME if CPU_IDLE
+	select ARCH_HAS_CONTROL_MODULE
 	select PM_OPP if PM
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select ARM_CPU_SUSPEND if PM
arch/arm/plat-omap/Kconfig +4 -0
index dd36eba..2b2c9d8 100644
@@ -5,6 +5,10 @@ menu "TI OMAP Common Features"
 config ARCH_OMAP_OTG
 	bool
 
+config ARCH_HAS_CONTROL_MODULE
+	bool
+	select MFD_OMAP_CONTROL
+
 choice
 	prompt "OMAP System Type"
 	default ARCH_OMAP2PLUS
drivers/mfd/Kconfig +6 -0
index 92144ed..530ac60 100644
@@ -823,6 +823,12 @@ config MFD_WL1273_CORE
 	  driver connects the radio-wl1273 V4L2 module and the wl1273
 	  audio codec.
 
+config MFD_OMAP_CONTROL
+	bool "Texas Instruments OMAP System control module"
+	depends on ARCH_HAS_CONTROL_MODULE
+	help
+	  This is the core driver for system control module.
+
 config MFD_OMAP_USB_HOST
 	bool "Support OMAP USBHS core driver"
 	depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
drivers/mfd/Makefile +1 -0
index 75f6ed6..b037443 100644
@@ -107,6 +107,7 @@ obj-$(CONFIG_MFD_TPS6586X)	+= tps6586x.o
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
+obj-$(CONFIG_MFD_OMAP_CONTROL)	+= omap-control-core.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
drivers/mfd/omap-control-core.c new file +35 -0
new file mode 100644
index 0000000..cefbc5a
@@ -0,0 +1,162 @@
+/*
+ * OMAP system control module driver file
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Contacts:
+ * Based on original code written by:
+ *    J Keerthy <[email protected]>
+ *    Moiz Sonasath <[email protected]>
+ * MFD clean up and re-factoring:
+ *    Eduardo Valentin <[email protected]>
+ *    Konstantin Baydarov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/omap_control.h>
+
+#include <linux/of.h>

drivers/mfd/omap-control-core.c line 45

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+#include <linux/of_address.h>
+
+void __iomem *omap_control_base;
+unsigned long omap_control_phys_base;
+size_t omap_control_mapsize;
+
+u32 omap_control_status_read(void)
+{
+	return __raw_readl(omap_control_base);
+}

In AM335X, D_CAN IP uses single CONTROL module register to initialize D_CAN ram (D_CAN_RAMINIT). In order to enable D_CAN RAM we have to write to that register in sync with clock enable/disable.

How can I use this driver to handle this usecase? Similar to above API?

Currently this is handled using platform call back (example below)

In arch/arm/mach-omap2/devices.c:
static void d_can_hw_raminit(unsigned int instance, unsigned int enable)

{
        u32 val;

        /* Read the value */
        val = readl(AM33XX_CTRL_REGADDR(AM33XX_DCAN_RAMINIT_OFFSET));
        if (enable) {
                /* Set to "1" */
                val &= ~AM33XX_DCAN_RAMINIT_START(instance);
                val |= AM33XX_DCAN_RAMINIT_START(instance);
                writel(val, AM33XX_CTRL_REGADDR(AM33XX_DCAN_RAMINIT_OFFSET));
        } else {
                /* Set to "0" */
                val &= ~AM33XX_DCAN_RAMINIT_START(instance);
                writel(val, AM33XX_CTRL_REGADDR(AM33XX_DCAN_RAMINIT_OFFSET));
        }
}

In drivers/net/can/c_can/c_can.c:
void d_can_reset_ram(struct d_can_priv *d_can, unsigned int instance,
unsigned int enable)

{
        if (d_can->ram_init)
                d_can->ram_init(instance, enable);
}

Thanks
AnilKumar