Skip to contentSkip to conversation

OMAP System Control Module

RFC PATCH New Eduardo Valentin 10 participants 99 messages May 25, 2012 – Jun 26, 2012 Page 1 of 2

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

cover OMAP System Control Module

Hello Paul and Tony,

This is a series of patches adding a basic support for system control module, on OMAP4+ context. It is a working in progress, but I wanted to share already to get your feedback.

I've modeled the driver as an MFD. You will see in this series:
. A rework of the system control module header (patch from Santosh, picked from the list) . Device creation for control module core
. Early device creation for control module core
. The MFD core driver for system control module
. The MFD child for usb-phy pin control
. The MFD child for bandgap sensor
. Very early exposure of OMAP4 thermal zone
. All added drivers are only supporting DT probing
. The series is based on linux-omap master, as it has the hwmod entries for SCM.

The overall idea of this series is to put in place the infrastructure. It is not touching nor removing the existing APIs under mach-omap2/control.c for now. But the target is to have these APIs moved to the MFD core driver.

For early access, like ID checking, I have written the platform driver as an early platform driver and you will see also early device addition and probing under device.c for this case. This is of course a proposal. I see that there are people that thing this is a bit of an overkill. Konstantin (CCd) was proposing a simpler solution by having APIs with early_* prefixes, and solve the IO address mapping with a DT entry, for instance. But feel free to propose better ways.

This code has been ripped off from the Android 3.1 branch. I have rewritten a couple of things, but the major driver functions and API's entries are kept.

So, based on this series, I see as a TODO list, for system control core driver:
- Start to move all the existing APIs under mach-omap2/control.c to the mfd core.
- Rewrite the users of the existing APIs, mentioned on previous item Once we decide the API and agree on how to deal with early calls.
- Add remaining children (from top of my head, the CAM is one of them, but I also think we should prob have one for HWOBS for instance)
- Test on boards that use the existing APIs.

TODO list for bandgap driver:
- Improve thermal zone definition for OMAP4
- Introduce the thermal zones for OMAP5

Amit, due to hwmod dep, I didn't include any cooling binding in this series, based on the generic CPU cooling device.

Overall series has been tested only with panda board OMAP4460.

Your comments are welcome.

All best,

Eduardo Valentin (9):
ARM: OMAP: expose control.h to mach area
OMAP: Add early device for system control module
mfd: omap: control: core system control driver
OMAP2+: use control module mfd driver in omap_type
mfd: omap: control: usb-phy: introduce the ctrl-module usb driver
ARM: OMAP4+: Adding the temperature sensor register set bit fields
ARM: OMAP4+: thermal: introduce bandgap temperature sensor
omap4: thermal: add basic CPU thermal zone
ARM: DT: Add support to system control module for OMAP4

Kishon Vijay Abraham I (1):
arm: omap: device: create a device for system control module

Santosh Shilimkar (1):
ARM: OMAP4: Remove un-used control module headers and defines.

 .../devicetree/bindings/mfd/omap_control.txt       |   44 +
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 arch/arm/boot/dts/omap4.dtsi                       |   13 +
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/mach-omap2/am35xx-emac.c                  |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c                |    2 +-
 arch/arm/mach-omap2/board-4430sdp.c                |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c            |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c              |    2 +-
 arch/arm/mach-omap2/board-apollon.c                |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |    2 +-
 arch/arm/mach-omap2/board-h4.c                     |    2 +-
 arch/arm/mach-omap2/board-igep0020.c               |    2 +-
 arch/arm/mach-omap2/board-ldp.c                    |    2 +-
 arch/arm/mach-omap2/board-omap3logic.c             |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c             |    2 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |    2 +-
 arch/arm/mach-omap2/clock2420_data.c               |    2 +-
 arch/arm/mach-omap2/clock2430_data.c               |    2 +-
 arch/arm/mach-omap2/clock3xxx_data.c               |    2 +-
 arch/arm/mach-omap2/clock44xx_data.c               |    2 +-
 arch/arm/mach-omap2/common.c                       |    2 +-
 arch/arm/mach-omap2/control.c                      |    2 +-
 arch/arm/mach-omap2/cpuidle34xx.c                  |    2 +-
 arch/arm/mach-omap2/devices.c                      |   57 +-
 arch/arm/mach-omap2/display.c                      |    2 +-
 arch/arm/mach-omap2/hsmmc.c                        |    2 +-
 arch/arm/mach-omap2/id.c                           |   18 +-
 arch/arm/mach-omap2/{ => include/mach}/control.h   |  163 ++-
 .../include/mach/ctrl_module_core_44xx.h           |  391 -----
 .../include/mach/ctrl_module_pad_core_44xx.h       | 1409 -----------------
 .../include/mach/ctrl_module_pad_wkup_44xx.h       |  236 ---
 .../include/mach/ctrl_module_wkup_44xx.h           |   92 --
 arch/arm/mach-omap2/mcbsp.c                        |    2 +-
 arch/arm/mach-omap2/mux.c                          |    2 +-
 arch/arm/mach-omap2/omap_phy_internal.c            |    2 +-
 arch/arm/mach-omap2/opp3xxx_data.c                 |    2 +-
 arch/arm/mach-omap2/opp4xxx_data.c                 |    2 +-
 arch/arm/mach-omap2/pm24xx.c                       |    2 +-
 arch/arm/mach-omap2/pm34xx.c                       |    2 +-
 arch/arm/mach-omap2/prcm.c                         |    2 +-
 arch/arm/mach-omap2/serial.c                       |    2 +-
 arch/arm/mach-omap2/sleep34xx.S                    |    2 +-
 arch/arm/mach-omap2/sr_device.c                    |    2 +-
 arch/arm/mach-omap2/usb-fs.c                       |    2 +-
 arch/arm/mach-omap2/voltage.c                      |    2 +-
 arch/arm/plat-omap/Kconfig                         |    3 +
 drivers/mfd/Kconfig                                |    9 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  211 +++
 drivers/thermal/Kconfig                            |   25 +
 drivers/thermal/Makefile                           |    5 +-
 drivers/thermal/omap-bandgap.c                     | 1602 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   75 +
 drivers/thermal/omap4-thermal.c                    |   72 +
 drivers/usb/otg/Kconfig                            |   13 +
 drivers/usb/otg/Makefile                           |    1 +
 drivers/usb/otg/omap4-usb-phy.c                    |  130 ++
 include/linux/mfd/omap_control.h                   |   69 +
 include/linux/usb/omap4_usb_phy.h                  |   53 +
 60 files changed, 2617 insertions(+), 2173 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/omap_control.txt
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 rename arch/arm/mach-omap2/{ => include/mach}/control.h (75%)
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
 create mode 100644 drivers/mfd/omap-control-core.c
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h
 create mode 100644 drivers/thermal/omap4-thermal.c
 create mode 100644 drivers/usb/otg/omap4-usb-phy.c
 create mode 100644 include/linux/mfd/omap_control.h
 create mode 100644 include/linux/usb/omap4_usb_phy.h
Signature · 1 line
1.7.7.1.488.ge8e1c
#1 lore raw

RFC PATCH 1/11 ARM: OMAP4: Remove un-used control module headers and defines.

From: Santosh Shilimkar <[email protected]>

Most of the OMAP4 control module register defines are not used and can be removed. Keep only needed defines and move them to common control module header just like other OMAP versions.

---
 arch/arm/mach-omap2/control.h                      |   45 +-
 .../include/mach/ctrl_module_core_44xx.h           |  391 ------
 .../include/mach/ctrl_module_pad_core_44xx.h       | 1409 --------------------
 .../include/mach/ctrl_module_pad_wkup_44xx.h       |  236 ----
 .../include/mach/ctrl_module_wkup_44xx.h           |   92 --
 5 files changed, 40 insertions(+), 2133 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
arch/arm/mach-omap2/control.h +40 -5
index a406fd0..dad2903 100644
@@ -16,11 +16,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
 #define __ARCH_ARM_MACH_OMAP2_CONTROL_H
 
-#include <mach/ctrl_module_core_44xx.h>
-#include <mach/ctrl_module_wkup_44xx.h>
-#include <mach/ctrl_module_pad_core_44xx.h>
-#include <mach/ctrl_module_pad_wkup_44xx.h>
-
 #ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)					\
 		OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
@@ -183,6 +178,43 @@
 #define OMAP3630_CONTROL_FUSE_OPP50_VDD2        (OMAP2_CONTROL_GENERAL + 0x0128)
 #define OMAP3630_CONTROL_FUSE_OPP100_VDD2       (OMAP2_CONTROL_GENERAL + 0x012C)
 
+/* OMAP4 IDCODE CONTROL */
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1		0x0218
+#define OMAP4_CTRL_MODULE_CORE_STATUS				0x02c4
+
+/* CONTROL_I2C_1 */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1		0x0624
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK			(1 << 28)
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK			(1 << 24)
+
+/* DSI CONTROL_DSIPHY */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY		0x0618
+#define OMAP4_DSI2_LANEENABLE_SHIFT				29
+#define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT				24
+#define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT					19
+#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT					14
+#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
+
+/* CONTROL_PBIASLITE */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE		0x0600
+#define OMAP4_MMC1_PWRDNZ_MASK					(1 << 26)
+#define OMAP4_MMC1_PBIASLITE_VMODE_MASK				(1 << 21)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK			(1 << 22)
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK			(1 << 23)
+
+/* CONTROL_MMC1 */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1			0x0628
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK			(1 << 31)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK			(1 << 30)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK			(1 << 29)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK			(1 << 28)
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK				(1 << 27)
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK				(1 << 26)
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK				(1 << 25)
+
 /* OMAP44xx control efuse offsets */
 #define OMAP44XX_CONTROL_FUSE_IVA_OPP50		0x22C
 #define OMAP44XX_CONTROL_FUSE_IVA_OPP100	0x22F
@@ -195,6 +227,9 @@
 #define OMAP44XX_CONTROL_FUSE_CORE_OPP50	0x254
 #define OMAP44XX_CONTROL_FUSE_CORE_OPP100	0x257
 
+/* OMAP44xx control McBSP padconf */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP	0x061c
+
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
 #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h deleted +0 -391

391 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h deleted +0 -1409

1,409 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h deleted +0 -236

236 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h deleted +0 -92

92 lines not on this page · raw message

Signature · 1 line
1.7.7.1.488.ge8e1c
#2 lore raw

RFC PATCH 1/11 ARM: OMAP4: Remove un-used control module headers and defines.

Quoted 9 lines · Eduardo Valentin

From: Santosh Shilimkar <[email protected]>

Most of the OMAP4 control module register defines are not used and can be removed. Keep only needed defines and move them to common control module header just like other OMAP versions.

---

Thanks for picking this up in your series

Regards
Santposh

#3 lore raw

RFC PATCH 2/11 ARM: OMAP: expose control.h to mach area

In reply to Eduardo Valentin

This patch exposes the definitions under control.h to drivers outside the machine code.

---
 arch/arm/mach-omap2/am35xx-emac.c                |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c              |    2 +-
 arch/arm/mach-omap2/board-4430sdp.c              |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c          |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c            |    2 +-
 arch/arm/mach-omap2/board-apollon.c              |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c             |    2 +-
 arch/arm/mach-omap2/board-h4.c                   |    2 +-
 arch/arm/mach-omap2/board-igep0020.c             |    2 +-
 arch/arm/mach-omap2/board-ldp.c                  |    2 +-
 arch/arm/mach-omap2/board-omap3logic.c           |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c           |    2 +-
 arch/arm/mach-omap2/board-omap4pcm049.c          |    2 +-
 arch/arm/mach-omap2/clock2420_data.c             |    2 +-
 arch/arm/mach-omap2/clock2430_data.c             |    2 +-
 arch/arm/mach-omap2/clock3xxx_data.c             |    2 +-
 arch/arm/mach-omap2/clock44xx_data.c             |    2 +-
 arch/arm/mach-omap2/common.c                     |    2 +-
 arch/arm/mach-omap2/control.c                    |    2 +-
 arch/arm/mach-omap2/cpuidle34xx.c                |    2 +-
 arch/arm/mach-omap2/devices.c                    |    2 +-
 arch/arm/mach-omap2/display.c                    |    2 +-
 arch/arm/mach-omap2/hsmmc.c                      |    2 +-
 arch/arm/mach-omap2/id.c                         |    2 +-
 arch/arm/mach-omap2/{ => include/mach}/control.h |    2 +-
 arch/arm/mach-omap2/mcbsp.c                      |    2 +-
 arch/arm/mach-omap2/mux.c                        |    2 +-
 arch/arm/mach-omap2/omap_phy_internal.c          |    2 +-
 arch/arm/mach-omap2/opp3xxx_data.c               |    2 +-
 arch/arm/mach-omap2/opp4xxx_data.c               |    2 +-
 arch/arm/mach-omap2/pm24xx.c                     |    2 +-
 arch/arm/mach-omap2/pm34xx.c                     |    2 +-
 arch/arm/mach-omap2/prcm.c                       |    2 +-
 arch/arm/mach-omap2/serial.c                     |    2 +-
 arch/arm/mach-omap2/sleep34xx.S                  |    2 +-
 arch/arm/mach-omap2/sr_device.c                  |    2 +-
 arch/arm/mach-omap2/usb-fs.c                     |    2 +-
 arch/arm/mach-omap2/voltage.c                    |    2 +-
 38 files changed, 38 insertions(+), 38 deletions(-)
 rename arch/arm/mach-omap2/{ => include/mach}/control.h (99%)
arch/arm/mach-omap2/am35xx-emac.c +1 -1
index 447682c..c3da28a 100644
@@ -21,7 +21,7 @@
 #include <plat/irqs.h>
 #include <mach/am35xx.h>
 
-#include "control.h"
+#include <mach/control.h>
 
 static struct mdio_platform_data am35xx_emac_mdio_pdata;
 
arch/arm/mach-omap2/board-3430sdp.c +1 -1
index 37abb0d..ad1132b 100644
@@ -46,7 +46,7 @@
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #define CONFIG_DISABLE_HFCLK 1
arch/arm/mach-omap2/board-4430sdp.c +1 -1
index 94af6cd..8f7f76b 100644
@@ -47,7 +47,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #define ETH_KS8851_IRQ			34
arch/arm/mach-omap2/board-am3517crane.c +1 -1
index 3b8a53c..2ad514d 100644
@@ -32,7 +32,7 @@
 
 #include "am35xx-emac.h"
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define GPIO_USB_POWER		35
 #define GPIO_USB_NRESET		38
arch/arm/mach-omap2/board-am3517evm.c +1 -1
index 99790eb..bef6586 100644
@@ -41,7 +41,7 @@
 
 #include "am35xx-emac.h"
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "hsmmc.h"
 
 #define LCD_PANEL_PWR		176
arch/arm/mach-omap2/board-apollon.c +1 -1
index 768ece2..bd04fe2 100644
@@ -44,7 +44,7 @@
 #include <video/omap-panel-generic-dpi.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* LED & Switch macros */
 #define LED0_GPIO13		13
arch/arm/mach-omap2/board-cm-t3517.c +1 -1
index 9e66e16..1d2b7a3 100644
@@ -47,7 +47,7 @@
 #include <mach/am35xx.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 #include "am35xx-emac.h"
 
arch/arm/mach-omap2/board-h4.c +1 -1
index 0bbbabe..623a231 100644
@@ -43,7 +43,7 @@
 #include <video/omap-panel-generic-dpi.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define H4_FLASH_CS	0
 #define H4_SMC91X_CS	1
arch/arm/mach-omap2/board-igep0020.c +1 -1
index 7a27409..ebef044 100644
@@ -42,7 +42,7 @@
 #include "sdram-numonyx-m65kxxxxam.h"
 #include "common-board-devices.h"
 #include "board-flash.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
arch/arm/mach-omap2/board-ldp.c +1 -1
index 1b60495..6383a76 100644
@@ -50,7 +50,7 @@
 #include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #define LDP_SMSC911X_CS		1
arch/arm/mach-omap2/board-omap3logic.c +1 -1
index c008bf8..ca3e075 100644
@@ -37,7 +37,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #include <plat/mux.h>
arch/arm/mach-omap2/board-omap4panda.c +1 -1
index 847a857..b1c8517 100644
@@ -45,7 +45,7 @@
 #include <video/omap-panel-tfp410.h>
 
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 #include "common-board-devices.h"
 
arch/arm/mach-omap2/board-omap4pcm049.c +1 -1
index a95f426..101e984 100644
@@ -48,7 +48,7 @@
 
 #include "common.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 #include "common-board-devices.h"
 
arch/arm/mach-omap2/clock2420_data.c +1 -1
index bace930..f350e96 100644
@@ -30,7 +30,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
 
arch/arm/mach-omap2/clock2430_data.c +1 -1
index 3b4d09a..dd08bcb 100644
@@ -29,7 +29,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
 
arch/arm/mach-omap2/clock3xxx_data.c +1 -1
index 4e1a3b0..694625f 100644
@@ -34,7 +34,7 @@
 #include "cm-regbits-34xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
-#include "control.h"
+#include <mach/control.h>
 
 /*
  * clocks
arch/arm/mach-omap2/clock44xx_data.c +1 -1
index 2172f66..ce11ee4 100644
@@ -39,7 +39,7 @@
 #include "cm-regbits-44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
-#include "control.h"
+#include <mach/control.h>
 #include "scrm44xx.h"
 
 /* OMAP4 modulemode control */
arch/arm/mach-omap2/common.c +1 -1
index 8a6953a..3dc94d0 100644
@@ -25,7 +25,7 @@
 #include "iomap.h"
 #include "common.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* Global address base setup code */
 
arch/arm/mach-omap2/control.c +1 -1
index 08e674b..92e35bf 100644
@@ -26,7 +26,7 @@
 #include "cm2xxx_3xxx.h"
 #include "sdrc.h"
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* Used by omap3_ctrl_save_padconf() */
 #define START_PADCONF_SAVE		0x2
arch/arm/mach-omap2/cpuidle34xx.c +1 -1
index 207bc1c..7d82c6bb 100644
@@ -33,7 +33,7 @@
 #include "clockdomain.h"
 
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common.h"
 
 #ifdef CONFIG_CPU_IDLE
arch/arm/mach-omap2/devices.c +1 -1
index 7b4b932..152c266 100644
@@ -34,7 +34,7 @@
 #include <plat/omap4-keypad.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "devices.h"
 
 #define L3_MODULES_MAX_LEN 12
arch/arm/mach-omap2/display.c +1 -1
index db5a88a..0681407 100644
@@ -32,7 +32,7 @@
 
 #include "iomap.h"
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "display.h"
 
 #define DISPC_CONTROL		0x0040
arch/arm/mach-omap2/hsmmc.c +1 -1
index be697d4..33b3d62 100644
@@ -22,7 +22,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
arch/arm/mach-omap2/id.c +1 -1
index 0389b32..5bb9746 100644
@@ -26,7 +26,7 @@
 
 #include <mach/id.h>
 
-#include "control.h"
+#include <mach/control.h>
 
 static unsigned int omap_revision;
 static const char *cpu_rev;
arch/arm/mach-omap2/include/mach/control.h renamed from arch/arm/mach-omap2/control.h +1 -1
similarity index 99%
rename from arch/arm/mach-omap2/control.h
rename to arch/arm/mach-omap2/include/mach/control.h
index dad2903..cf42764 100644
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-omap2/control.h
+ * arch/arm/mach-omap2/include/mach/control.h
  *
  * OMAP2/3/4 System Control Module definitions
  *
arch/arm/mach-omap2/mcbsp.c +1 -1
index 577cb77..0367035 100644
@@ -25,7 +25,7 @@
 #include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
 
-#include "control.h"
+#include <mach/control.h>
 
 /*
  * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
arch/arm/mach-omap2/mux.c +1 -1
index 3268ee2..f23e6618 100644
@@ -38,7 +38,7 @@
 
 #include <plat/omap_hwmod.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 #include "prm.h"
 
arch/arm/mach-omap2/omap_phy_internal.c +1 -1
index 4c90477..b2c9253 100644
@@ -29,7 +29,7 @@
 #include <linux/usb.h>
 
 #include <plat/usb.h>
-#include "control.h"
+#include <mach/control.h>
 
 /* OMAP control module register for UTMI PHY */
 #define CONTROL_DEV_CONF		0x300
arch/arm/mach-omap2/opp3xxx_data.c +1 -1
index d95f3f9..6dafdbb 100644
@@ -21,7 +21,7 @@
 
 #include <plat/cpu.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "omap_opp_data.h"
 #include "pm.h"
 
arch/arm/mach-omap2/opp4xxx_data.c +1 -1
index 2293ba2..27f823c 100644
@@ -22,7 +22,7 @@
 
 #include <plat/cpu.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "omap_opp_data.h"
 #include "pm.h"
 
arch/arm/mach-omap2/pm24xx.c +1 -1
index facfffc..7ebca30 100644
@@ -49,7 +49,7 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
 
arch/arm/mach-omap2/pm34xx.c +1 -1
index 8b43aef..1d2a51c 100644
@@ -49,7 +49,7 @@
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
arch/arm/mach-omap2/prcm.c +1 -1
index 480f40a..fff0b09 100644
@@ -37,7 +37,7 @@
 #include "prminst44xx.h"
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-44xx.h"
-#include "control.h"
+#include <mach/control.h>
 
 void __iomem *prm_base;
 void __iomem *cm_base;
arch/arm/mach-omap2/serial.c +1 -1
index 678dd1d..97b09da5 100644
@@ -39,7 +39,7 @@
 #include "pm.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 
 /*
arch/arm/mach-omap2/sleep34xx.S +1 -1
index 1f62f23..b3f6bfc 100644
@@ -33,7 +33,7 @@
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 /*
  * Registers access definitions
arch/arm/mach-omap2/sr_device.c +1 -1
index a503e1e..48a01f6 100644
@@ -26,7 +26,7 @@
 
 #include "smartreflex.h"
 #include "voltage.h"
-#include "control.h"
+#include <mach/control.h>
 #include "pm.h"
 
 static bool sr_enable_on_init;
arch/arm/mach-omap2/usb-fs.c +1 -1
index 1481078..94d471c 100644
@@ -32,7 +32,7 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 
 #define INT_USB_IRQ_GEN		INT_24XX_USB_IRQ_GEN
arch/arm/mach-omap2/voltage.c +1 -1
index 4dc60e8..d2f0644 100644
@@ -34,7 +34,7 @@
 #include "prm44xx.h"
 #include "prcm44xx.h"
 #include "prminst44xx.h"
-#include "control.h"
+#include <mach/control.h>
 
 #include "voltage.h"
 #include "powerdomain.h"
Signature · 1 line
1.7.7.1.488.ge8e1c
#4 lore raw

RFC PATCH 2/11 ARM: OMAP: expose control.h to mach area

Quoted 5 lines · Eduardo Valentin

This patch exposes the definitions under control.h to drivers outside the machine code.

---

After second thought, this complete header movement needs to avoided. Drivers should not anyway include something like <mach/control.h>

May be split the control.h header file data into ..
- defines used by mach-omap2/* files which can remain in "control.h" in existing location.
- common functions/defines used across drivers/*, mach-omap2/*, plat-omap/*, should
go to include/linux/omap_control.h
- Driver specific defines like thermal, usb etc, should go to respective drivers file.

What do you think ?

Regards
santosh

#5 lore raw

RFC PATCH 2/11 ARM: OMAP: expose control.h to mach area

Hello,

Quoted 5 lines · Santosh
Quoted 3 lines · Eduardo Valentin

This patch exposes the definitions under control.h to drivers outside the machine code.

Quoted 8 lines
Quoted 2 lines

---

After second thought, this complete header movement needs to avoided. Drivers should not anyway include something like <mach/control.h>

May be split the control.h header file data into ..
- defines used by mach-omap2/* files which can remain in "control.h" in existing location.

OK..

Quoted 3 lines

- common functions/defines used across drivers/*, mach-omap2/*, plat-omap/*, should
go to include/linux/omap_control.h

Right..

Quoted 2 lines

- Driver specific defines like thermal, usb etc, should go to respective drivers file.

Indeed.

Quoted 2 lines

What do you think ?

I think we are in line. And I believe I saw a similar comment by Benoit in other email thread.

Having a better thinking of this, it makes sense to have the definition specific to drivers in the driver scope only, as they are going to be used only there anyway.

I will drop this patch off and update the remaining changes accordingly (drop the change in control.h for thermal specific and move it to omap_bandgap.h).

Quoted 3 lines

Regards
santosh

Signature · 1 line
Eduardo Valentin
maintainer
#6 lore raw

RFC PATCH 2/11 ARM: OMAP: expose control.h to mach area

Quoted 37 lines · Valentin, Eduardo

Hello,

Quoted 5 lines · Santosh
Quoted 3 lines · Eduardo Valentin

This patch exposes the definitions under control.h to drivers outside the machine code.

Quoted 8 lines
Quoted 2 lines

---

After second thought, this complete header movement needs to avoided. Drivers should not anyway include something like <mach/control.h>

May be split the control.h header file data into ..
- defines used by mach-omap2/* files which can remain in "control.h" in existing location.

OK..

Quoted 3 lines

- common functions/defines used across drivers/*, mach-omap2/*, plat-omap/*, should
go to include/linux/omap_control.h

Right..

Quoted 2 lines

- Driver specific defines like thermal, usb etc, should go to respective drivers file.

Indeed.

Quoted 2 lines

What do you think ?

I think we are in line. And I believe I saw a similar comment by Benoit in other email thread.

Quoted 7 lines

Having a better thinking of this, it makes sense to have the definition specific to drivers in the driver scope only, as they are going to be used only there anyway.

I will drop this patch off and update the remaining changes accordingly (drop the change in control.h for thermal specific and move it to omap_bandgap.h).

Yes good, we should not expose these to the other drivers, that will lead into misuse of these defines from various other drivers that we may not notice until it's too late.

Regards,

Tony

#7 lore raw

RFC PATCH 3/11 arm: omap: device: create a device for system control module

In reply to Eduardo Valentin

From: Kishon Vijay Abraham I <[email protected]>

Extracts the device data from hwmod database and create a platform device using omap device build.

The device build is done during postcore_initcall.

---
 arch/arm/mach-omap2/devices.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +26 -0
index 152c266..9332673 100644
@@ -40,6 +40,32 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static int omap_init_control(void)
+{
+	struct omap_hwmod		*oh;
+	struct platform_device		*pdev;
+	const char			*oh_name, *name;
+
+	oh_name = "ctrl_module_core";
+	name = "omap-control-core";
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not lookup hwmod for %s\n", oh_name);
+		return PTR_ERR(oh);
+	}
+
+	pdev = omap_device_build(name, -1, oh, NULL, 0, NULL, 0, true);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build omap_device for %s %s\n",
+		       name, oh_name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+postcore_initcall(omap_init_control);
+
 static int __init omap3_l3_init(void)
 {
 	struct omap_hwmod *oh;
Signature · 1 line
1.7.7.1.488.ge8e1c
#8 lore raw

RFC PATCH 3/11 arm: omap: device: create a device for system control module

Quoted 6 lines · Eduardo Valentin

From: Kishon Vijay Abraham I<[email protected]>

Extracts the device data from hwmod database and create a platform device using omap device build.

The device build is done during postcore_initcall.

Do you still need that since you are supporting only DT? The device will be built automatically in the DT case.

Regards,
Benoit

Quoted 44 lines
---
  arch/arm/mach-omap2/devices.c |   26 ++++++++++++++++++++++++++
  1 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +26 -0
index 152c266..9332673 100644
@@ -40,6 +40,32 @@
  #define L3_MODULES_MAX_LEN 12
  #define L3_MODULES 3
 
+static int omap_init_control(void)
+{
+	struct omap_hwmod		*oh;
+	struct platform_device		*pdev;
+	const char			*oh_name, *name;
+
+	oh_name = "ctrl_module_core";
+	name = "omap-control-core";
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not lookup hwmod for %s\n", oh_name);
+		return PTR_ERR(oh);
+	}
+
+	pdev = omap_device_build(name, -1, oh, NULL, 0, NULL, 0, true);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build omap_device for %s %s\n",
+		       name, oh_name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+postcore_initcall(omap_init_control);
+
  static int __init omap3_l3_init(void)
  {
  	struct omap_hwmod *oh;
#9 lore raw

RFC PATCH 3/11 arm: omap: device: create a device for system control module

Quoted 10 lines · Cousson Benoit
Quoted 6 lines · Eduardo Valentin

From: Kishon Vijay Abraham I<[email protected]>

Extracts the device data from hwmod database and create a platform device using omap device build.

The device build is done during postcore_initcall.

Do you still need that since you are supporting only DT? The device will be built automatically in the DT case.

In fact this is not needed for DT only probing. Dropping this one.

Quoted 49 lines

Regards,
Benoit

Quoted 44 lines
---
 arch/arm/mach-omap2/devices.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +26 -0
index 152c266..9332673 100644
@@ -40,6 +40,32 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static int omap_init_control(void)
+{
+	struct omap_hwmod		*oh;
+	struct platform_device		*pdev;
+	const char			*oh_name, *name;
+
+	oh_name = "ctrl_module_core";
+	name = "omap-control-core";
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not lookup hwmod for %s\n", oh_name);
+		return PTR_ERR(oh);
+	}
+
+	pdev = omap_device_build(name, -1, oh, NULL, 0, NULL, 0, true);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build omap_device for %s %s\n",
+		       name, oh_name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+postcore_initcall(omap_init_control);
+
 static int __init omap3_l3_init(void)
 {
 	struct omap_hwmod *oh;
#10 lore raw

RFC PATCH 3/11 arm: omap: device: create a device for system control module

Hi.

Quoted 11 lines · Eduardo Valentin
Quoted 9 lines · Cousson Benoit
Quoted 6 lines · Eduardo Valentin

From: Kishon Vijay Abraham I<[email protected]>

Extracts the device data from hwmod database and create a platform device using omap device build.

The device build is done during postcore_initcall.

Do you still need that since you are supporting only DT? The device will be built automatically in the DT case.

In fact this is not needed for DT only probing. Dropping this one.

Yes, platform device(struct platform_device) will be built automatically, but omap device(struct omap_device) will not be built. Also when omap device is allocated(omap_device_alloc) hwmod_clocks are registered, but in case of ctrl_module_core device - no new clock are registered. So, is it fine to drop omap device and skip omap_device_build() call?

BR,
Konstantin Baydarov.

Quoted 47 lines
Quoted 47 lines

Regards,
Benoit

Quoted 43 lines
---
 arch/arm/mach-omap2/devices.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +26 -0
index 152c266..9332673 100644
@@ -40,6 +40,32 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static int omap_init_control(void)
+{
+	struct omap_hwmod		*oh;
+	struct platform_device		*pdev;
+	const char			*oh_name, *name;
+
+	oh_name = "ctrl_module_core";
+	name = "omap-control-core";
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not lookup hwmod for %s\n", oh_name);
+		return PTR_ERR(oh);
+	}
+
+	pdev = omap_device_build(name, -1, oh, NULL, 0, NULL, 0, true);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build omap_device for %s %s\n",
+		       name, oh_name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+postcore_initcall(omap_init_control);
+
 static int __init omap3_l3_init(void)
 {
 	struct omap_hwmod *oh;
#11 lore raw

RFC PATCH 3/11 arm: omap: device: create a device for system control module

Hello Konstantin,

Sorry for the delayed reply.

Quoted 7 lines · Konstantin Baydarov

?Hi.

Quoted 4 lines · Eduardo Valentin
Quoted 3 lines · Cousson Benoit
Quoted 2 lines · Eduardo Valentin

From: Kishon Vijay Abraham I<[email protected]>

Quoted 8 lines
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines

Extracts the device data from hwmod database and create a platform device using omap device build.

The device build is done during postcore_initcall.

Do you still need that since you are supporting only DT? The device will be built automatically in the DT case.

In fact this is not needed for DT only probing. Dropping this one.

Yes, platform device(struct platform_device) will be built automatically, but omap device(struct omap_device) will not be built.

The platform_device will be built as well as the omap_device. There are hooks at the platform_device creation that will proceed with the omap_device deployment. Please check:
arch/arm/plat-omap/omap_device.c: _omap_device_notifier_call and omap_device_build_from_dt

Quoted 2 lines

Also when omap device is allocated(omap_device_alloc) hwmod_clocks are registered, but in case of ctrl_module_core device - no new clock are registered. So, is it fine to drop omap device and skip omap_device_build() call?

As explained above, when booting with DT, you will get both, pdev and omap_dev.

Quoted 3 lines

?BR,
? ?Konstantin Baydarov.

All best,

Eduardo

Quoted 49 lines
Quoted 48 lines
Quoted 48 lines

Regards,
Benoit

Quoted 43 lines

---
?arch/arm/mach-omap2/devices.c | ? 26 ++++++++++++++++++++++++++ ?1 files changed, 26 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/devices.c +0 -0
index 152c266..9332673 100644
@@ -40,6 +40,32 @@

?#define L3_MODULES_MAX_LEN 12
?#define L3_MODULES 3

arch/arm/mach-omap2/devices.c +26 -0
+static int omap_init_control(void)
+{
+ ? struct omap_hwmod ? ? ? ? ? ? ? *oh;
+ ? struct platform_device ? ? ? ? ?*pdev;
+ ? const char ? ? ? ? ? ? ? ? ? ? ?*oh_name, *name;
+
+ ? oh_name = "ctrl_module_core";
+ ? name = "omap-control-core";
+
+ ? oh = omap_hwmod_lookup(oh_name);
+ ? if (!oh) {
+ ? ? ? ? ? pr_err("Could not lookup hwmod for %s\n", oh_name);
+ ? ? ? ? ? return PTR_ERR(oh);
+ ? }
+
+ ? pdev = omap_device_build(name, -1, oh, NULL, 0, NULL, 0, true);
+ ? if (IS_ERR(pdev)) {
+ ? ? ? ? ? pr_err("Could not build omap_device for %s %s\n",
+ ? ? ? ? ? ? ? ? ?name, oh_name);
+ ? ? ? ? ? return PTR_ERR(pdev);
+ ? }
+
+ ? return 0;
+}
+postcore_initcall(omap_init_control);
+

?static int __init omap3_l3_init(void)
?{
? ? struct omap_hwmod *oh;

Signature · 1 line
Eduardo Valentin
#12 lore raw

RFC PATCH 3/11 arm: omap: device: create a device for system control module

In reply to Eduardo Valentin

Hi.

Quoted 27 lines · Eduardo Valentin

From: Kishon Vijay Abraham I <[email protected]>

Extracts the device data from hwmod database and create a platform device using omap device build.

The device build is done during postcore_initcall.

---
 arch/arm/mach-omap2/devices.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +6 -0
index 152c266..9332673 100644
@@ -40,6 +40,32 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static int omap_init_control(void)
+{
+	struct omap_hwmod		*oh;
+	struct platform_device		*pdev;
+	const char			*oh_name, *name;
+

arch/arm/mach-omap2/devices.c line 58

Quoted 10 lines
arch/arm/mach-omap2/devices.c +10 -0
+	oh_name = "ctrl_module_core";
+	name = "omap-control-core";
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not lookup hwmod for %s\n", oh_name);
+		return PTR_ERR(oh);
+	}
+
+	pdev = omap_device_build(name, -1, oh, NULL, 0, NULL, 0, true);

I noticed that control module omap device is created and configured according to following idle flags:
static struct omap_hwmod_class_sysconfig omap44xx_ctrl_module_sysc = {
.rev_offs = 0x0000,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
SIDLE_SMART_WKUP),
.sysc_fields = &omap_hwmod_sysc_type2,
};

IIUC, ".idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | SIDLE_SMART_WKUP)" means that CONTROL_GEN_CORE idlemode will be set to
"0x2,0x3: Clock is automatically gated when there is no access to the Control Module through L4-interconnect". See CONTROL_GEN_CORE_SYSCONFIG register.
So IIUC theoretically CONTROL_GEN_CORE module clock can be automatically gated. Recalling that CONTROL_GEN_CORE module has an THERMAL_ALERT interrupt that is used by the bandgap driver, I'm wondering if the THERMAL_ALERT interrupt will be fired when CONTROL_GEN_CORE module clock is gated? Probably bandgap driver should set CONTROL_GEN_CORE idle mode to SIDLE_NO, to prevent loosing THERMAL_ALERT interrupt?

BR,
Konstantin Baydarov.

Quoted 13 lines
arch/arm/mach-omap2/devices.c +10 -0
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build omap_device for %s %s\n",
+		       name, oh_name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+postcore_initcall(omap_init_control);
+
 static int __init omap3_l3_init(void)
 {
 	struct omap_hwmod *oh;
#13 lore raw

RFC PATCH 4/11 OMAP: Add early device for system control module

In reply to Eduardo Valentin

This is a way to add an early device for system control module. the code is also requesting for driver registration and probing. Done at early_initcall because at that time, ioremapping is possible.

---
 arch/arm/mach-omap2/devices.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +29 -0
index 9332673..58cc5c3 100644
@@ -40,6 +40,35 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static struct resource control_resources[] = {
+	[0] = {
+		.start	= 0x4a002000,
+		.end	= 0x4a0027ff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+static struct platform_device control_device = {
+	.name		= "omap-control-core",
+	.id		= 0,
+	.resource	= control_resources,
+	.num_resources	= ARRAY_SIZE(control_resources),
+};
+
+static struct platform_device *early_devices[] __initdata = {
+	&control_device,
+};
+
+static int __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(early_devices,
+				   ARRAY_SIZE(early_devices));
+	early_platform_driver_register_all("early_omap_control");
+	early_platform_driver_probe("early_omap_control", 1, false);
+
+	return 0;
+}
+early_initcall(plat_early_device_setup);
+
 static int omap_init_control(void)
 {
 	struct omap_hwmod		*oh;
Signature · 1 line
1.7.7.1.488.ge8e1c
#14 lore raw

RFC PATCH 4/11 OMAP: Add early device for system control module

Hi , Eduardo.

Quoted 31 lines · Eduardo Valentin

This is a way to add an early device for system control module. the code is also requesting for driver registration and probing. Done at early_initcall because at that time, ioremapping is possible.

---
 arch/arm/mach-omap2/devices.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +14 -0
index 9332673..58cc5c3 100644
@@ -40,6 +40,35 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static struct resource control_resources[] = {
+	[0] = {
+		.start	= 0x4a002000,
+		.end	= 0x4a0027ff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+static struct platform_device control_device = {
+	.name		= "omap-control-core",
+	.id		= 0,
+	.resource	= control_resources,
+	.num_resources	= ARRAY_SIZE(control_resources),
+};
+

arch/arm/mach-omap2/devices.c line 66

Quoted 10 lines
arch/arm/mach-omap2/devices.c +10 -0
+static struct platform_device *early_devices[] __initdata = {
+	&control_device,
+};
+
+static int __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(early_devices,
+				   ARRAY_SIZE(early_devices));
+	early_platform_driver_register_all("early_omap_control");
+	early_platform_driver_probe("early_omap_control", 1, false);

I checked out git://gitorious.org/omap-thermal/omap-thermal.git omap_scm_dev.
Looks like that calling devm_kzalloc() and platform_get_resource() from early_initcall is too early. I get following backtrace (probably the backtrace is kernel config dependent):
...

[    0.198455] [<c00193b4>] (unwind_backtrace+0x0/0xe0) from [<c02b2a10>] (do_raw_spin_lock+0x20/0x134)
[    0.207977] [<c02b2a10>] (do_raw_spin_lock+0x20/0x134) from [<c05df068>] (_raw_spin_lock_irqsave+0x58/0x64)
[    0.218109] [<c05df068>] (_raw_spin_lock_irqsave+0x58/0x64) from [<c02f03bc>] (devres_add+0x18/0x38)
[    0.227600] [<c02f03bc>] (devres_add+0x18/0x38) from [<c02f07d0>] (devm_kzalloc+0x50/0x5c)
[    0.236206] [<c02f07d0>] (devm_kzalloc+0x50/0x5c) from [<c05c73a4>] (omap_control_probe+0x20/0xe4)
[    0.245544] [<c05c73a4>] (omap_control_probe+0x20/0xe4) from [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c)
[    0.256378] [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c) from [<c0798030>] (plat_early_device_setup+0x2c/0x3c)
[    0.267700] [<c0798030>] (plat_early_device_setup+0x2c/0x3c) from [<c078f8c4>] (do_one_initcall+0x90/0x164)
[    0.277801] [<c078f8c4>] (do_one_initcall+0x90/0x164) from [<c078f9ec>] (kernel_init+0x54/0x1a4)
[    0.286956] [<c078f9ec>] (kernel_init+0x54/0x1a4) from [<c0013818>] (kernel_thread_exit+0x0/0x8)
[    0.296203] ------------[ cut here ]------------
[    0.301086] WARNING: at include/linux/kref.h:41 kobject_get+0x24/0x48()
[    0.308044] [<c00193b4>] (unwind_backtrace+0x0/0xe0) from [<c00394a4>] (warn_slowpath_common+0x48/0x60)
[    0.317871] [<c00394a4>] (warn_slowpath_common+0x48/0x60) from [<c0039574>] (warn_slowpath_null+0x18/0x1c)
[    0.327941] [<c0039574>] (warn_slowpath_null+0x18/0x1c) from [<c02a59b4>] (kobject_get+0x24/0x48)
[    0.337219] [<c02a59b4>] (kobject_get+0x24/0x48) from [<c02eb588>] (get_device+0x14/0x1c)
[    0.345764] [<c02eb588>] (get_device+0x14/0x1c) from [<c02eb66c>] (device_add+0xc4/0x594)
[    0.354370] [<c02eb66c>] (device_add+0xc4/0x594) from [<c03eeab4>] (of_platform_device_create_pdata+0x5c/0x7c)
[    0.364807] [<c03eeab4>] (of_platform_device_create_pdata+0x5c/0x7c) from [<c03eec94>] (of_platform_bus_create+0x1c0/0x258)
[    0.376403] [<c03eec94>] (of_platform_bus_create+0x1c0/0x258) from [<c03eee4c>] (of_platform_populate+0x5c/0x88)
[    0.387023] [<c03eee4c>] (of_platform_populate+0x5c/0x88) from [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c)
[    0.398101] [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c) from [<c0798030>] (plat_early_device_setup+0x2c/0x3c)
[    0.409423] [<c0798030>] (plat_early_device_setup+0x2c/0x3c) from [<c078f8c4>] (do_one_initcall+0x90/0x164)
[    0.419586] [<c078f8c4>] (do_one_initcall+0x90/0x164) from [<c078f9ec>] (kernel_init+0x54/0x1a4)
[    0.428771] [<c078f9ec>] (kernel_init+0x54/0x1a4) from [<c0013818>] (kernel_thread_exit+0x0/0x8)
[    0.437957] ---[ end trace da227214a82491b7 ]--

...

BR,
Konstantin Baydarov.

Quoted 8 lines
arch/arm/mach-omap2/devices.c +5 -0
+
+	return 0;
+}
+early_initcall(plat_early_device_setup);
+
 static int omap_init_control(void)
 {
 	struct omap_hwmod		*oh;
#15 lore raw

RFC PATCH 4/11 OMAP: Add early device for system control module

Hello,

Quoted 6 lines · Konstantin Baydarov

?Hi , Eduardo.

Quoted 3 lines · Eduardo Valentin

This is a way to add an early device for system control module. the code is also requesting for driver registration and probing. Done at early_initcall because at that time, ioremapping is possible.

OK. Which debug config you have?

In any case, that can be solved by not requesting the resource and passing the address area by other means.

Quoted 82 lines
Quoted 28 lines

---
?arch/arm/mach-omap2/devices.c | ? 29 +++++++++++++++++++++++++++++ ?1 files changed, 29 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/devices.c +0 -0
index 9332673..58cc5c3 100644
@@ -40,6 +40,35 @@

?#define L3_MODULES_MAX_LEN 12
?#define L3_MODULES 3

arch/arm/mach-omap2/devices.c +14 -0
+static struct resource control_resources[] = {
+ ? ? [0] = {
+ ? ? ? ? ? ? .start ?= 0x4a002000,
+ ? ? ? ? ? ? .end ? ?= 0x4a0027ff,
+ ? ? ? ? ? ? .flags ?= IORESOURCE_MEM,
+ ? ? },
+};
+static struct platform_device control_device = {
+ ? ? .name ? ? ? ? ? = "omap-control-core",
+ ? ? .id ? ? ? ? ? ? = 0,
+ ? ? .resource ? ? ? = control_resources,
+ ? ? .num_resources ?= ARRAY_SIZE(control_resources),
+};
+

arch/arm/mach-omap2/devices.c

Quoted 10 lines
arch/arm/mach-omap2/devices.c +10 -0
+static struct platform_device *early_devices[] __initdata = {
+ ? ? &control_device,
+};
+
+static int __init plat_early_device_setup(void)
+{
+ ? ? early_platform_add_devices(early_devices,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ARRAY_SIZE(early_devices));
+ ? ? early_platform_driver_register_all("early_omap_control");
+ ? ? early_platform_driver_probe("early_omap_control", 1, false);

I checked out git://gitorious.org/omap-thermal/omap-thermal.git omap_scm_dev.
Looks like that calling devm_kzalloc() and platform_get_resource() from early_initcall is too early.
I get following backtrace (probably the backtrace is kernel config dependent):
...
[ ? ?0.198455] [<c00193b4>] (unwind_backtrace+0x0/0xe0) from [<c02b2a10>] (do_raw_spin_lock+0x20/0x134)
[ ? ?0.207977] [<c02b2a10>] (do_raw_spin_lock+0x20/0x134) from [<c05df068>] (_raw_spin_lock_irqsave+0x58/0x64) [ ? ?0.218109] [<c05df068>] (_raw_spin_lock_irqsave+0x58/0x64) from [<c02f03bc>] (devres_add+0x18/0x38)
[ ? ?0.227600] [<c02f03bc>] (devres_add+0x18/0x38) from [<c02f07d0>] (devm_kzalloc+0x50/0x5c)
[ ? ?0.236206] [<c02f07d0>] (devm_kzalloc+0x50/0x5c) from [<c05c73a4>] (omap_control_probe+0x20/0xe4)
[ ? ?0.245544] [<c05c73a4>] (omap_control_probe+0x20/0xe4) from [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c) [ ? ?0.256378] [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c) from [<c0798030>] (plat_early_device_setup+0x2c/0x3c) [ ? ?0.267700] [<c0798030>] (plat_early_device_setup+0x2c/0x3c) from [<c078f8c4>] (do_one_initcall+0x90/0x164) [ ? ?0.277801] [<c078f8c4>] (do_one_initcall+0x90/0x164) from [<c078f9ec>] (kernel_init+0x54/0x1a4)
[ ? ?0.286956] [<c078f9ec>] (kernel_init+0x54/0x1a4) from [<c0013818>] (kernel_thread_exit+0x0/0x8)
[ ? ?0.296203] ------------[ cut here ]------------
[ ? ?0.301086] WARNING: at include/linux/kref.h:41 kobject_get+0x24/0x48()
[ ? ?0.308044] [<c00193b4>] (unwind_backtrace+0x0/0xe0) from [<c00394a4>] (warn_slowpath_common+0x48/0x60) [ ? ?0.317871] [<c00394a4>] (warn_slowpath_common+0x48/0x60) from [<c0039574>] (warn_slowpath_null+0x18/0x1c) [ ? ?0.327941] [<c0039574>] (warn_slowpath_null+0x18/0x1c) from [<c02a59b4>] (kobject_get+0x24/0x48)
[ ? ?0.337219] [<c02a59b4>] (kobject_get+0x24/0x48) from [<c02eb588>] (get_device+0x14/0x1c)
[ ? ?0.345764] [<c02eb588>] (get_device+0x14/0x1c) from [<c02eb66c>] (device_add+0xc4/0x594)
[ ? ?0.354370] [<c02eb66c>] (device_add+0xc4/0x594) from [<c03eeab4>] (of_platform_device_create_pdata+0x5c/0x7c) [ ? ?0.364807] [<c03eeab4>] (of_platform_device_create_pdata+0x5c/0x7c) from [<c03eec94>] (of_platform_bus_create+0x1c0/0x258) [ ? ?0.376403] [<c03eec94>] (of_platform_bus_create+0x1c0/0x258) from [<c03eee4c>] (of_platform_populate+0x5c/0x88) [ ? ?0.387023] [<c03eee4c>] (of_platform_populate+0x5c/0x88) from [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c) [ ? ?0.398101] [<c07b3178>] (early_platform_driver_probe+0x1ac/0x23c) from [<c0798030>] (plat_early_device_setup+0x2c/0x3c) [ ? ?0.409423] [<c0798030>] (plat_early_device_setup+0x2c/0x3c) from [<c078f8c4>] (do_one_initcall+0x90/0x164) [ ? ?0.419586] [<c078f8c4>] (do_one_initcall+0x90/0x164) from [<c078f9ec>] (kernel_init+0x54/0x1a4)
[ ? ?0.428771] [<c078f9ec>] (kernel_init+0x54/0x1a4) from [<c0013818>] (kernel_thread_exit+0x0/0x8)
[ ? ?0.437957] ---[ end trace da227214a82491b7 ]--
...

?BR,
? ?Konstantin Baydarov.

Quoted 8 lines
arch/arm/mach-omap2/devices.c +5 -0
+
+ ? ? return 0;
+}
+early_initcall(plat_early_device_setup);
+

?static int omap_init_control(void)
?{
? ? ? struct omap_hwmod ? ? ? ? ? ? ? *oh;

Signature · 1 line
Eduardo Valentin
#16 lore raw

RFC PATCH 4/11 OMAP: Add early device for system control module

In reply to Eduardo Valentin

Hi.

Quoted 14 lines · Eduardo Valentin

This is a way to add an early device for system control module. the code is also requesting for driver registration and probing. Done at early_initcall because at that time, ioremapping is possible.

---
 arch/arm/mach-omap2/devices.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +0 -0
index 9332673..58cc5c3 100644

arch/arm/mach-omap2/devices.c line 49

Quoted 10 lines
arch/arm/mach-omap2/devices.c +7 -0
@@ -40,6 +40,35 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+static struct resource control_resources[] = {
+	[0] = {
+		.start	= 0x4a002000,
+		.end	= 0x4a0027ff,
+		.flags	= IORESOURCE_MEM,
+	},
+};

Init control module platform device resources from device tree instead of hard-coding them.
Prevent control module driver registering itself second time after it has already been registered by early_platform_driver_register_all().

arch/arm/boot/dts/omap4.dtsi +3 -0
Index: omap-thermal/arch/arm/boot/dts/omap4.dtsi
===================================================================
@@ -275,7 +275,10 @@
 
 		ctrl_module_core: ctrl_module_core at 4a002000 {
 			compatible = "ti,omap4-control";
+			#address-cells = <1>;
+			#size-cells = <1>;
 			ti,hwmods = "ctrl_module_core";
+			reg = <0x4a002000 0x1000>;
 			bandgap {
 				compatible = "ti,omap4460-bandgap";
 				interrupts = <0 126 4>; /* talert */
arch/arm/mach-omap2/devices.c +61 -0

87 lines not on this page · raw message

drivers/mfd/omap-control-core.c +4 -0
Index: omap-thermal/drivers/mfd/omap-control-core.c
===================================================================
@@ -194,6 +194,10 @@ static struct platform_driver omap_contr
 
 static int __init omap_control_init(void)
 {
+	/* Check is early driver probe is done */
+	if (!omap_control_module)
+		return 0;
+
 	return platform_driver_register(&omap_control_driver);
 }
 postcore_initcall_sync(omap_control_init);
#17 lore raw

RFC PATCH 4/11 OMAP: Add early device for system control module

In reply to Eduardo Valentin
Quoted 14 lines · Eduardo Valentin

This is a way to add an early device for system control module. the code is also requesting for driver registration and probing. Done at early_initcall because at that time, ioremapping is possible.

---
  arch/arm/mach-omap2/devices.c |   29 +++++++++++++++++++++++++++++
  1 files changed, 29 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +0 -0
index 9332673..58cc5c3 100644

arch/arm/mach-omap2/devices.c line 49

Quoted 10 lines
arch/arm/mach-omap2/devices.c +7 -0
@@ -40,6 +40,35 @@
  #define L3_MODULES_MAX_LEN 12
  #define L3_MODULES 3
 
+static struct resource control_resources[] = {
+	[0] = {
+		.start	= 0x4a002000,
+		.end	= 0x4a0027ff,
+		.flags	= IORESOURCE_MEM,
+	},
+};

I guess you should be able to do use DT to build the early device as well. It will avoid hard coding some physical address inside the devices.

Regards,
Benoit

Quoted 25 lines
arch/arm/mach-omap2/devices.c +22 -0
+static struct platform_device control_device = {
+	.name		= "omap-control-core",
+	.id		= 0,
+	.resource	= control_resources,
+	.num_resources	= ARRAY_SIZE(control_resources),
+};
+
+static struct platform_device *early_devices[] __initdata = {
+	&control_device,
+};
+
+static int __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(early_devices,
+				   ARRAY_SIZE(early_devices));
+	early_platform_driver_register_all("early_omap_control");
+	early_platform_driver_probe("early_omap_control", 1, false);
+
+	return 0;
+}
+early_initcall(plat_early_device_setup);
+
  static int omap_init_control(void)
  {
  	struct omap_hwmod		*oh;
#18 lore raw

RFC PATCH 4/11 OMAP: Add early device for system control module

In reply to Eduardo Valentin
Quoted 46 lines · Eduardo Valentin

This is a way to add an early device for system control module. the code is also requesting for driver registration and probing. Done at early_initcall because at that time, ioremapping is possible.

---
?arch/arm/mach-omap2/devices.c | ? 29 +++++++++++++++++++++++++++++ ?1 files changed, 29 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/devices.c +0 -0
index 9332673..58cc5c3 100644
@@ -40,6 +40,35 @@

?#define L3_MODULES_MAX_LEN 12
?#define L3_MODULES 3

arch/arm/mach-omap2/devices.c +29 -0
+static struct resource control_resources[] = {
+ ? ? ? [0] = {
+ ? ? ? ? ? ? ? .start ?= 0x4a002000,
+ ? ? ? ? ? ? ? .end ? ?= 0x4a0027ff,
+ ? ? ? ? ? ? ? .flags ?= IORESOURCE_MEM,
+ ? ? ? },
+};
+static struct platform_device control_device = {
+ ? ? ? .name ? ? ? ? ? = "omap-control-core",
+ ? ? ? .id ? ? ? ? ? ? = 0,
+ ? ? ? .resource ? ? ? = control_resources,
+ ? ? ? .num_resources ?= ARRAY_SIZE(control_resources),
+};
+
+static struct platform_device *early_devices[] __initdata = {
+ ? ? ? &control_device,
+};
+
+static int __init plat_early_device_setup(void)
+{
+ ? ? ? early_platform_add_devices(early_devices,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ARRAY_SIZE(early_devices));
+ ? ? ? early_platform_driver_register_all("early_omap_control");
+ ? ? ? early_platform_driver_probe("early_omap_control", 1, false);
+
+ ? ? ? return 0;
+}
+early_initcall(plat_early_device_setup);
+
Quoted 3 lines

?static int omap_init_control(void)
?{
? ? ? ?struct omap_hwmod ? ? ? ? ? ? ? *oh;

Nice !!
Apart from fix from Konstantin and Benoit's DT comment, patch looks fine to me.

Regards
Santosh

#19 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

In reply to Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---
 .../devicetree/bindings/mfd/omap_control.txt       |   44 ++++
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/plat-omap/Kconfig                         |    3 +
 drivers/mfd/Kconfig                                |    9 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  211 ++++++++++++++++++++
 include/linux/mfd/omap_control.h                   |   69 +++++++
 7 files changed, 338 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 +44 -0
new file mode 100644
index 0000000..46d5e7e
@@ -0,0 +1,44 @@
+* 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";
+
+Sub-nodes:
+- bandgap : contains the bandgap node
+
+  The bindings details of individual bandgap device can be found in:
+  Documentation/devicetree/bindings/thermal/omap_bandgap.txt
+
+- usb : contains the usb phy pin control node
+
+  The only required property for this child is:
+    - compatible = "ti,omap4-control-usb";
+
+Examples:
+
+ctrl_module_core: ctrl_module_core at 4a002000 {
+	compatible = "ti,omap4-control";
+	ti,hwmods = "ctrl_module_core";
+	bandgap {
+		compatible = "ti,omap4460-bandgap";
+		interrupts = <0 126 4>; /* talert */
+		ti,tshut-gpio = <86>; /* tshut */
+	};
+	usb {
+		compatible = "ti,omap4-usb-phy";
+	};
+};
arch/arm/mach-omap2/Kconfig +1 -0
index a2b946d..7dfe5e1 100644
@@ -52,6 +52,7 @@ config ARCH_OMAP4
 	select PL310_ERRATA_727915
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
+	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 +3 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"
 config ARCH_OMAP_OTG
 	bool
 
+config ARCH_HAS_CONTROL_MODULE
+	bool
+
 choice
 	prompt "OMAP System Type"
 	default ARCH_OMAP2PLUS
drivers/mfd/Kconfig +9 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ 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. This driver
+	  is responsible for creating the control module mfd child,
+	  like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+	  change for off mode.
+
 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 05fa538..00f99d6 100644
@@ -106,6 +106,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 +211 -0

211 lines not on this page · raw message

include/linux/mfd/omap_control.h new file +69 -0

69 lines not on this page · raw message

Signature · 1 line
1.7.7.1.488.ge8e1c
#20 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 172 lines · Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---
  .../devicetree/bindings/mfd/omap_control.txt       |   44 ++++
  arch/arm/mach-omap2/Kconfig                        |    1 +
  arch/arm/plat-omap/Kconfig                         |    3 +
  drivers/mfd/Kconfig                                |    9 +
  drivers/mfd/Makefile                               |    1 +
  drivers/mfd/omap-control-core.c                    |  211 ++++++++++++++++++++
  include/linux/mfd/omap_control.h                   |   69 +++++++
  7 files changed, 338 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 +44 -0
new file mode 100644
index 0000000..46d5e7e
@@ -0,0 +1,44 @@
+* 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";
+
+Sub-nodes:
+- bandgap : contains the bandgap node
+
+  The bindings details of individual bandgap device can be found in:
+  Documentation/devicetree/bindings/thermal/omap_bandgap.txt
+
+- usb : contains the usb phy pin control node
+
+  The only required property for this child is:
+    - compatible = "ti,omap4-control-usb";
+
+Examples:
+
+ctrl_module_core: ctrl_module_core at 4a002000 {
+	compatible = "ti,omap4-control";
+	ti,hwmods = "ctrl_module_core";
+	bandgap {
+		compatible = "ti,omap4460-bandgap";
+		interrupts =<0 126 4>; /* talert */
+		ti,tshut-gpio =<86>; /* tshut */
+	};
+	usb {
+		compatible = "ti,omap4-usb-phy";
+	};
+};
arch/arm/mach-omap2/Kconfig +1 -0
index a2b946d..7dfe5e1 100644
@@ -52,6 +52,7 @@ config ARCH_OMAP4
  	select PL310_ERRATA_727915
  	select ARM_ERRATA_720789
  	select ARCH_HAS_OPP
+	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 +3 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"
  config ARCH_OMAP_OTG
  	bool
 
+config ARCH_HAS_CONTROL_MODULE
+	bool
+
  choice
  	prompt "OMAP System Type"
  	default ARCH_OMAP2PLUS
drivers/mfd/Kconfig +9 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ 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. This driver
+	  is responsible for creating the control module mfd child,
+	  like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+	  change for off mode.
+
  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 05fa538..00f99d6 100644
@@ -106,6 +106,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 +24 -0
new file mode 100644
index 0000000..7d8d408
@@ -0,0 +1,211 @@
+/*
+ * 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]>
+ *
+ * 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>

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+#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>
+
+static struct omap_control *omap_control_module;

Mmm, we can have up to 4 control module instances in OMAP4.

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

But since they all have different base address, it will be trick to handle them with only a single entry.

Quoted 40 lines
drivers/mfd/omap-control-core.c new file +40 -0
+
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+
+	if (!omap_control)
+		return -EINVAL;
+
+	*val = readl(omap_control->base + reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+
+/**
+ * omap_control_writel: Write a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @val: value to write.
+ * @reg: register to write to.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_writel(struct device *dev, u32 val, u32 reg)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!omap_control)
+		return -EINVAL;
+

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+	spin_lock_irqsave(&omap_control->reg_lock, flags);
+	writel(val, omap_control->base + reg);
+	spin_unlock_irqrestore(&omap_control->reg_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+/**
+ * omap_control_get: returns the control module device pinter

typo

Quoted 4 lines
drivers/mfd/omap-control-core.c new file +4 -0
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+struct device *omap_control_get(void)
+{
+	unsigned long flags;
+
+	if (!omap_control_module)
+		return ERR_PTR(-ENODEV);
+
+	spin_lock_irqsave(&omap_control_module->reg_lock, flags);
+	omap_control_module->use_count++;
+	spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);

Don't we do have some better way to increment atomically a variable in Linux.

Quoted 29 lines
drivers/mfd/omap-control-core.c new file +29 -0
+
+	return omap_control_module->dev;
+}
+EXPORT_SYMBOL_GPL(omap_control_get);
+
+/**
+ * omap_control_put: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+void omap_control_put(struct device *dev)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!omap_control)
+		return;
+
+	spin_lock_irqsave(&omap_control->reg_lock, flags);
+	omap_control->use_count--;
+	spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(omap_control_put);
+
+static const struct of_device_id of_omap_control_match[] = {
+	{ .compatible = "ti,omap3-control", },
+	{ .compatible = "ti,omap4-control", },
+	{ .compatible = "ti,omap5-control", },

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+	{ },
+};
+
+static int __devinit omap_control_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *base;
+	struct device *dev =&pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct omap_control *omap_control;

Maybe omap_control_data instead? At least if this is drvdata only. If this is supposed to be the *handle* to the control module instance, it should be fine.

Quoted 105 lines
drivers/mfd/omap-control-core.c new file +74 -0
+
+	omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
+	if (!omap_control) {
+		dev_err(dev, "not enough memory for omap_control\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing memory base resource\n");
+		return -EINVAL;
+	}
+
+	base = devm_request_and_ioremap(dev, res);
+	if (!base) {
+		dev_err(dev, "ioremap failed\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	omap_control->base = base;
+	omap_control->dev = dev;
+	spin_lock_init(&omap_control->reg_lock);
+
+	platform_set_drvdata(pdev, omap_control);
+	omap_control_module = omap_control;
+
+	return of_platform_populate(np, of_omap_control_match, NULL, dev);
+}
+
+static int __devexit omap_control_remove(struct platform_device *pdev)
+{
+	struct omap_control *omap_control = platform_get_drvdata(pdev);
+
+	spin_lock(&omap_control->reg_lock);
+	if (omap_control->use_count>  0) {
+		spin_unlock(&omap_control->reg_lock);
+		dev_err(&pdev->dev, "device removed while still being used\n");
+		return -EBUSY;
+	}
+	spin_unlock(&omap_control->reg_lock);
+
+	iounmap(omap_control->base);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver omap_control_driver = {
+	.probe			= omap_control_probe,
+	.remove			= __devexit_p(omap_control_remove),
+	.driver = {
+		.name		= "omap-control-core",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_omap_control_match,
+	},
+};
+
+static int __init omap_control_init(void)
+{
+	return platform_driver_register(&omap_control_driver);
+}
+postcore_initcall_sync(omap_control_init);
+
+static void __exit omap_control_exit(void)
+{
+	platform_driver_unregister(&omap_control_driver);
+}
+module_exit(omap_control_exit);
+early_platform_init("early_omap_control",&omap_control_driver);
+
+MODULE_DESCRIPTION("OMAP system control module driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-control-core");
+MODULE_AUTHOR("Texas Instruments Inc.");
include/linux/mfd/omap_control.h new file +25 -0
new file mode 100644
index 0000000..7a33eda
@@ -0,0 +1,69 @@
+/*
+ * 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]>
+ *
+ * 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
+
+#include<linux/err.h>

include/linux/mfd/omap_control.h line 35

Quoted 10 lines
include/linux/mfd/omap_control.h new file +10 -0
+
+/**
+ * struct system control module - scm device structure
+ * @dev: device pointer
+ * @base: Base of the temp I/O
+ * @reg_lock: protect omap_control structure
+ * @use_count: track API users
+ */
+struct omap_control {
+	struct device		*dev;

Do you really need the dev?
You API is device based and not omap_control based, so it should not be needed.

I guess we should be consistent here. We can store the devices and used a device based API or store the omap_control and thus expose a omap_control API.

Regards,
Benoit

#21 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Hello,

Quoted 186 lines · Cousson Benoit
Quoted 172 lines · Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---
 .../devicetree/bindings/mfd/omap_control.txt       |   44 ++++
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/plat-omap/Kconfig                         |    3 +
 drivers/mfd/Kconfig                                |    9 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  211 ++++++++++++++++++++
 include/linux/mfd/omap_control.h                   |   69 +++++++
 7 files changed, 338 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 +44 -0
new file mode 100644
index 0000000..46d5e7e
@@ -0,0 +1,44 @@
+* 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";
+
+Sub-nodes:
+- bandgap : contains the bandgap node
+
+  The bindings details of individual bandgap device can be found in:
+  Documentation/devicetree/bindings/thermal/omap_bandgap.txt
+
+- usb : contains the usb phy pin control node
+
+  The only required property for this child is:
+    - compatible = "ti,omap4-control-usb";
+
+Examples:
+
+ctrl_module_core: ctrl_module_core at 4a002000 {
+	compatible = "ti,omap4-control";
+	ti,hwmods = "ctrl_module_core";
+	bandgap {
+		compatible = "ti,omap4460-bandgap";
+		interrupts =<0 126 4>; /* talert */
+		ti,tshut-gpio =<86>; /* tshut */
+	};
+	usb {
+		compatible = "ti,omap4-usb-phy";
+	};
+};
arch/arm/mach-omap2/Kconfig +1 -0
index a2b946d..7dfe5e1 100644
@@ -52,6 +52,7 @@ config ARCH_OMAP4
 	select PL310_ERRATA_727915
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
+	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 +3 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"
 config ARCH_OMAP_OTG
 	bool
 
+config ARCH_HAS_CONTROL_MODULE
+	bool
+
 choice
 	prompt "OMAP System Type"
 	default ARCH_OMAP2PLUS
drivers/mfd/Kconfig +9 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ 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. This driver
+	  is responsible for creating the control module mfd child,
+	  like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+	  change for off mode.
+
 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 05fa538..00f99d6 100644
@@ -106,6 +106,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 +24 -0
new file mode 100644
index 0000000..7d8d408
@@ -0,0 +1,211 @@
+/*
+ * 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]>
+ *
+ * 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>

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+#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>
+
+static struct omap_control *omap_control_module;

Mmm, we can have up to 4 control module instances in OMAP4.

Quoted 2 lines

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

Quoted 3 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Indeed. We can always add the support latter on.

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

Quoted 45 lines
Quoted 45 lines
drivers/mfd/omap-control-core.c new file +44 -0
+
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+
+	if (!omap_control)
+		return -EINVAL;
+
+	*val = readl(omap_control->base + reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+
+/**
+ * omap_control_writel: Write a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @val: value to write.
+ * @reg: register to write to.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_writel(struct device *dev, u32 val, u32 reg)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!omap_control)
+		return -EINVAL;
+
+	spin_lock_irqsave(&omap_control->reg_lock, flags);
+	writel(val, omap_control->base + reg);
+	spin_unlock_irqrestore(&omap_control->reg_lock, flags);
+
Quoted 8 lines

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

Quoted 6 lines
drivers/mfd/omap-control-core.c new file +6 -0
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+/**
+ * omap_control_get: returns the control module device pinter

typo

K

Quoted 10 lines
Quoted 10 lines
drivers/mfd/omap-control-core.c new file +9 -0
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+struct device *omap_control_get(void)
+{
+	unsigned long flags;
+
+	if (!omap_control_module)
Quoted 8 lines

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

Quoted 5 lines
drivers/mfd/omap-control-core.c new file +5 -0
+		return ERR_PTR(-ENODEV);
+
+	spin_lock_irqsave(&omap_control_module->reg_lock, flags);
+	omap_control_module->use_count++;
+	spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);

Don't we do have some better way to increment atomically a variable in Linux.

Yeah we have, atomic API. In general I think the SCM/bangap/phy APIs need to be revisited WRT locking, in general.

Quoted 36 lines
Quoted 36 lines
drivers/mfd/omap-control-core.c new file +35 -0
+
+	return omap_control_module->dev;
+}
+EXPORT_SYMBOL_GPL(omap_control_get);
+
+/**
+ * omap_control_put: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+void omap_control_put(struct device *dev)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!omap_control)
+		return;
+
+	spin_lock_irqsave(&omap_control->reg_lock, flags);
+	omap_control->use_count--;
+	spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(omap_control_put);
+
+static const struct of_device_id of_omap_control_match[] = {
+	{ .compatible = "ti,omap3-control", },
+	{ .compatible = "ti,omap4-control", },
+	{ .compatible = "ti,omap5-control", },
+	{ },
+};
+
+static int __devinit omap_control_probe(struct platform_device *pdev)
+{
+	struct resource *res;
Quoted 8 lines

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

Quoted 4 lines
drivers/mfd/omap-control-core.c new file +4 -0
+	void __iomem *base;
+	struct device *dev =&pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct omap_control *omap_control;

Maybe omap_control_data instead? At least if this is drvdata only. If this is supposed to be the *handle* to the control module instance, it should be fine.

That's suppose to be the phandle :-)

Quoted 121 lines
Quoted 106 lines
drivers/mfd/omap-control-core.c new file +74 -0
+
+	omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
+	if (!omap_control) {
+		dev_err(dev, "not enough memory for omap_control\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing memory base resource\n");
+		return -EINVAL;
+	}
+
+	base = devm_request_and_ioremap(dev, res);
+	if (!base) {
+		dev_err(dev, "ioremap failed\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	omap_control->base = base;
+	omap_control->dev = dev;
+	spin_lock_init(&omap_control->reg_lock);
+
+	platform_set_drvdata(pdev, omap_control);
+	omap_control_module = omap_control;
+
+	return of_platform_populate(np, of_omap_control_match, NULL, dev);
+}
+
+static int __devexit omap_control_remove(struct platform_device *pdev)
+{
+	struct omap_control *omap_control = platform_get_drvdata(pdev);
+
+	spin_lock(&omap_control->reg_lock);
+	if (omap_control->use_count>  0) {
+		spin_unlock(&omap_control->reg_lock);
+		dev_err(&pdev->dev, "device removed while still being used\n");
+		return -EBUSY;
+	}
+	spin_unlock(&omap_control->reg_lock);
+
+	iounmap(omap_control->base);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver omap_control_driver = {
+	.probe			= omap_control_probe,
+	.remove			= __devexit_p(omap_control_remove),
+	.driver = {
+		.name		= "omap-control-core",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_omap_control_match,
+	},
+};
+
+static int __init omap_control_init(void)
+{
+	return platform_driver_register(&omap_control_driver);
+}
+postcore_initcall_sync(omap_control_init);
+
+static void __exit omap_control_exit(void)
+{
+	platform_driver_unregister(&omap_control_driver);
+}
+module_exit(omap_control_exit);
+early_platform_init("early_omap_control",&omap_control_driver);
+
+MODULE_DESCRIPTION("OMAP system control module driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-control-core");
+MODULE_AUTHOR("Texas Instruments Inc.");
include/linux/mfd/omap_control.h new file +25 -0
new file mode 100644
index 0000000..7a33eda
@@ -0,0 +1,69 @@
+/*
+ * 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]>
+ *
+ * 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
+
+#include<linux/err.h>

include/linux/mfd/omap_control.h line 35

Quoted 10 lines
include/linux/mfd/omap_control.h new file +10 -0
+
+/**
+ * struct system control module - scm device structure
+ * @dev: device pointer
+ * @base: Base of the temp I/O
+ * @reg_lock: protect omap_control structure
+ * @use_count: track API users
+ */
+struct omap_control {
+	struct device		*dev;

Do you really need the dev?
You API is device based and not omap_control based, so it should not be needed.

Quoted 3 lines

I guess we should be consistent here. We can store the devices and used a device based API or store the omap_control and thus expose a omap_control API.

Yeah, this API structure is left over of the previous driver.

The omap_control_get returns the SCM device reference and the users of SCM use it as parameter for the SCM APIs.

We need to have in mind that, for SCM, the users are:
a. Its children (USB phy, BG, etc)
b. Non children users (mach code)

The refcounting and the locking needs to take care of both I'd say. The struct dev was just a way to pass the SCM phandle.

Quoted 3 lines

Regards,
Benoit

#22 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 189 lines · Eduardo Valentin

Hello,

Quoted 186 lines · Cousson Benoit
Quoted 172 lines · Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---
  .../devicetree/bindings/mfd/omap_control.txt       |   44 ++++
  arch/arm/mach-omap2/Kconfig                        |    1 +
  arch/arm/plat-omap/Kconfig                         |    3 +
  drivers/mfd/Kconfig                                |    9 +
  drivers/mfd/Makefile                               |    1 +
  drivers/mfd/omap-control-core.c                    |  211 ++++++++++++++++++++
  include/linux/mfd/omap_control.h                   |   69 +++++++
  7 files changed, 338 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 +44 -0
new file mode 100644
index 0000000..46d5e7e
@@ -0,0 +1,44 @@
+* 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";
+
+Sub-nodes:
+- bandgap : contains the bandgap node
+
+  The bindings details of individual bandgap device can be found in:
+  Documentation/devicetree/bindings/thermal/omap_bandgap.txt
+
+- usb : contains the usb phy pin control node
+
+  The only required property for this child is:
+    - compatible = "ti,omap4-control-usb";
+
+Examples:
+
+ctrl_module_core: ctrl_module_core at 4a002000 {
+	compatible = "ti,omap4-control";
+	ti,hwmods = "ctrl_module_core";
+	bandgap {
+		compatible = "ti,omap4460-bandgap";
+		interrupts =<0 126 4>; /* talert */
+		ti,tshut-gpio =<86>; /* tshut */
+	};
+	usb {
+		compatible = "ti,omap4-usb-phy";
+	};
+};
arch/arm/mach-omap2/Kconfig +1 -0
index a2b946d..7dfe5e1 100644
@@ -52,6 +52,7 @@ config ARCH_OMAP4
  	select PL310_ERRATA_727915
  	select ARM_ERRATA_720789
  	select ARCH_HAS_OPP
+	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 +3 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"
  config ARCH_OMAP_OTG
  	bool
 
+config ARCH_HAS_CONTROL_MODULE
+	bool
+
  choice
  	prompt "OMAP System Type"
  	default ARCH_OMAP2PLUS
drivers/mfd/Kconfig +9 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ 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. This driver
+	  is responsible for creating the control module mfd child,
+	  like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+	  change for off mode.
+
  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 05fa538..00f99d6 100644
@@ -106,6 +106,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 +24 -0
new file mode 100644
index 0000000..7d8d408
@@ -0,0 +1,211 @@
+/*
+ * 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]>
+ *
+ * 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>

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+#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>
+
+static struct omap_control *omap_control_module;

Mmm, we can have up to 4 control module instances in OMAP4.

Quoted 4 lines
Quoted 2 lines

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

OK, that's a good start already :-)

Quoted 8 lines
Quoted 2 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Indeed. We can always add the support latter on.

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

We should not go to that path I guess. We should have an API at children level independent of the underlying control module partitioning.

Regards,
Benoit

Quoted 264 lines
Quoted 44 lines
Quoted 44 lines
drivers/mfd/omap-control-core.c new file +44 -0
+
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+
+	if (!omap_control)
+		return -EINVAL;
+
+	*val = readl(omap_control->base + reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+
+/**
+ * omap_control_writel: Write a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @val: value to write.
+ * @reg: register to write to.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_writel(struct device *dev, u32 val, u32 reg)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!omap_control)
+		return -EINVAL;
+
+	spin_lock_irqsave(&omap_control->reg_lock, flags);
+	writel(val, omap_control->base + reg);
+	spin_unlock_irqrestore(&omap_control->reg_lock, flags);
+
Quoted 8 lines

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

Quoted 6 lines
drivers/mfd/omap-control-core.c new file +6 -0
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+/**
+ * omap_control_get: returns the control module device pinter

typo

K

Quoted 10 lines
Quoted 10 lines
drivers/mfd/omap-control-core.c new file +9 -0
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+struct device *omap_control_get(void)
+{
+	unsigned long flags;
+
+	if (!omap_control_module)
Quoted 8 lines

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

Quoted 5 lines
drivers/mfd/omap-control-core.c new file +5 -0
+		return ERR_PTR(-ENODEV);
+
+	spin_lock_irqsave(&omap_control_module->reg_lock, flags);
+	omap_control_module->use_count++;
+	spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);

Don't we do have some better way to increment atomically a variable in Linux.

Yeah we have, atomic API. In general I think the SCM/bangap/phy APIs need to be revisited WRT locking, in general.

Quoted 36 lines
Quoted 36 lines
drivers/mfd/omap-control-core.c new file +35 -0
+
+	return omap_control_module->dev;
+}
+EXPORT_SYMBOL_GPL(omap_control_get);
+
+/**
+ * omap_control_put: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+void omap_control_put(struct device *dev)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!omap_control)
+		return;
+
+	spin_lock_irqsave(&omap_control->reg_lock, flags);
+	omap_control->use_count--;
+	spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(omap_control_put);
+
+static const struct of_device_id of_omap_control_match[] = {
+	{ .compatible = "ti,omap3-control", },
+	{ .compatible = "ti,omap4-control", },
+	{ .compatible = "ti,omap5-control", },
+	{ },
+};
+
+static int __devinit omap_control_probe(struct platform_device *pdev)
+{
+	struct resource *res;
Quoted 8 lines

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

Quoted 4 lines
drivers/mfd/omap-control-core.c new file +4 -0
+	void __iomem *base;
+	struct device *dev =&pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct omap_control *omap_control;

Maybe omap_control_data instead? At least if this is drvdata only. If this is supposed to be the *handle* to the control module instance, it should be fine.

That's suppose to be the phandle :-)

Quoted 121 lines
Quoted 106 lines
drivers/mfd/omap-control-core.c new file +74 -0
+
+	omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
+	if (!omap_control) {
+		dev_err(dev, "not enough memory for omap_control\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing memory base resource\n");
+		return -EINVAL;
+	}
+
+	base = devm_request_and_ioremap(dev, res);
+	if (!base) {
+		dev_err(dev, "ioremap failed\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	omap_control->base = base;
+	omap_control->dev = dev;
+	spin_lock_init(&omap_control->reg_lock);
+
+	platform_set_drvdata(pdev, omap_control);
+	omap_control_module = omap_control;
+
+	return of_platform_populate(np, of_omap_control_match, NULL, dev);
+}
+
+static int __devexit omap_control_remove(struct platform_device *pdev)
+{
+	struct omap_control *omap_control = platform_get_drvdata(pdev);
+
+	spin_lock(&omap_control->reg_lock);
+	if (omap_control->use_count>   0) {
+		spin_unlock(&omap_control->reg_lock);
+		dev_err(&pdev->dev, "device removed while still being used\n");
+		return -EBUSY;
+	}
+	spin_unlock(&omap_control->reg_lock);
+
+	iounmap(omap_control->base);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver omap_control_driver = {
+	.probe			= omap_control_probe,
+	.remove			= __devexit_p(omap_control_remove),
+	.driver = {
+		.name		= "omap-control-core",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_omap_control_match,
+	},
+};
+
+static int __init omap_control_init(void)
+{
+	return platform_driver_register(&omap_control_driver);
+}
+postcore_initcall_sync(omap_control_init);
+
+static void __exit omap_control_exit(void)
+{
+	platform_driver_unregister(&omap_control_driver);
+}
+module_exit(omap_control_exit);
+early_platform_init("early_omap_control",&omap_control_driver);
+
+MODULE_DESCRIPTION("OMAP system control module driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-control-core");
+MODULE_AUTHOR("Texas Instruments Inc.");
include/linux/mfd/omap_control.h new file +25 -0
new file mode 100644
index 0000000..7a33eda
@@ -0,0 +1,69 @@
+/*
+ * 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]>
+ *
+ * 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
+
+#include<linux/err.h>

include/linux/mfd/omap_control.h line 35

Quoted 10 lines
include/linux/mfd/omap_control.h new file +10 -0
+
+/**
+ * struct system control module - scm device structure
+ * @dev: device pointer
+ * @base: Base of the temp I/O
+ * @reg_lock: protect omap_control structure
+ * @use_count: track API users
+ */
+struct omap_control {
+	struct device		*dev;

Do you really need the dev?
You API is device based and not omap_control based, so it should not be needed.

Quoted 3 lines

I guess we should be consistent here. We can store the devices and used a device based API or store the omap_control and thus expose a omap_control API.

Yeah, this API structure is left over of the previous driver.

The omap_control_get returns the SCM device reference and the users of SCM use it as parameter for the SCM APIs.

We need to have in mind that, for SCM, the users are:
a. Its children (USB phy, BG, etc)
b. Non children users (mach code)

The refcounting and the locking needs to take care of both I'd say. The struct dev was just a way to pass the SCM phandle.

Quoted 3 lines

Regards,
Benoit

maintainer
#23 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 16 lines · Cousson, Benoit
Quoted 7 lines · Eduardo Valentin
Quoted 5 lines

Mmm, we can have up to 4 control module instances in OMAP4.

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

OK, that's a good start already :-)

Quoted 5 lines
Quoted 2 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Indeed. We can always add the support latter on.

Quoted 7 lines
Quoted 3 lines

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

We should not go to that path I guess. We should have an API at children level independent of the underlying control module partitioning.

These should be separate driver instances for the control modules.

And then the ioremapped area should ignore at least the padconf registers so drivers/pinctrl/pinctrl-simple can handle those. There should not be any dependencies to the SCM driver from pinctrl-simple, the core SCM driver can manage the clocks and trigger the save of padconf regs.

Also we should allow MMC driver handle the MMC specific registers and USB driver(s) handle the USB specific registers if possible. Those should not live under drivers/mfd unless there are some dependencies other than trying to ioremap the whole SCM module instead of ioremapping in each driver.

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

Regards,

Tony

#24 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 33 lines · Tony Lindgren
Quoted 16 lines · Cousson, Benoit
Quoted 7 lines · Eduardo Valentin
Quoted 5 lines

Mmm, we can have up to 4 control module instances in OMAP4.

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

OK, that's a good start already :-)

Quoted 5 lines
Quoted 2 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Indeed. We can always add the support latter on.

Quoted 7 lines
Quoted 3 lines

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

We should not go to that path I guess. We should have an API at children level independent of the underlying control module partitioning.

These should be separate driver instances for the control modules.

And then the ioremapped area should ignore at least the padconf registers so drivers/pinctrl/pinctrl-simple can handle those. There should not be any dependencies to the SCM driver from pinctrl-simple, the core SCM driver can manage the clocks and trigger the save of padconf regs.

Quoted 9 lines

Also we should allow MMC driver handle the MMC specific registers and USB driver(s) handle the USB specific registers if possible. Those should not live under drivers/mfd unless there are some dependencies other than trying to ioremap the whole SCM module instead of ioremapping in each driver.

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

This sounds a good idea. With this we may not even need a core control module drivers if all the individual drivers take care of the registers they care. Mapping shouldn't be a problem as you mentioned.

Regards
Santosh

#25 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 40 lines · Santosh
Quoted 39 lines · Tony Lindgren
Quoted 16 lines · Cousson, Benoit
Quoted 7 lines · Eduardo Valentin
Quoted 5 lines

Mmm, we can have up to 4 control module instances in OMAP4.

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

OK, that's a good start already :-)

Quoted 5 lines
Quoted 2 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Indeed. We can always add the support latter on.

Quoted 7 lines
Quoted 3 lines

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

We should not go to that path I guess. We should have an API at children level independent of the underlying control module partitioning.

These should be separate driver instances for the control modules.

And then the ioremapped area should ignore at least the padconf registers so drivers/pinctrl/pinctrl-simple can handle those. There should not be any dependencies to the SCM driver from pinctrl-simple, the core SCM driver can manage the clocks and trigger the save of padconf regs.

Also we should allow MMC driver handle the MMC specific registers and USB driver(s) handle the USB specific registers if possible. Those should not live under drivers/mfd unless there are some dependencies other than trying to ioremap the whole SCM module instead of ioremapping in each driver.

Quoted 6 lines
Quoted 3 lines

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

This sounds a good idea. With this we may not even need a core control module drivers if all the individual drivers take care of the registers they care. Mapping shouldn't be a problem as you mentioned.

We should keep the MFD for PM / OCP single port correctness. Other than that it will be mostly useless, indeed.

Regards,
Benoit

#26 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Hello,

Quoted 35 lines · Cousson Benoit
Quoted 34 lines · Santosh
Quoted 33 lines · Tony Lindgren
Quoted 16 lines · Cousson, Benoit
Quoted 7 lines · Eduardo Valentin
Quoted 5 lines

Mmm, we can have up to 4 control module instances in OMAP4.

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

OK, that's a good start already :-)

Quoted 5 lines
Quoted 2 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Indeed. We can always add the support latter on.

Quoted 7 lines
Quoted 3 lines

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

We should not go to that path I guess. We should have an API at children level independent of the underlying control module partitioning.

These should be separate driver instances for the control modules.

And then the ioremapped area should ignore at least the padconf registers so drivers/pinctrl/pinctrl-simple can handle those. There should not be any dependencies to the SCM driver from pinctrl-simple, the core SCM driver can manage the clocks and trigger the save of padconf regs.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Also we should allow MMC driver handle the MMC specific registers and USB driver(s) handle the USB specific registers if possible. Those should not live under drivers/mfd unless there are some dependencies other than trying to ioremap the whole SCM module instead of ioremapping in each driver.

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

Within this series I kept the original MFD setup in the original driver found in the TI Android tree. But in fact, I agree with Tony here.

In general, ideally it would be good if we could setup this driver family, having for each driver their respective resources; a separated individual io area, IRQs, locking, APIs, etc.

But, the issue is to avoid having hard coded io areas in the code, and move them to auto generated data, DT/hwmod.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

This sounds a good idea. With this we may not even need a core control module drivers if all the individual drivers take care of the registers they care. Mapping shouldn't be a problem as you mentioned.

We should keep the MFD for PM / OCP single port correctness. Other than that it will be mostly useless, indeed.

Then, I guess the idea of having 1 static mapping for the MFD core, either in DT or hwmod, is to maintain the single OCP port we have today for SCM.

But, Benoit, IIRC, from our previous discussions, we won't have the io area for children autogenerated anyway, as they don't have any OCP. I suppose this applies also for clock data?

If children data won't be autogenerated, assuming we are relying on the autogenerated data, it means that SCM core area is the boundary that will be ioremapped and protected. But then we still have a flaw because children can still stomp between each other. Not to mention non-children users and the pin ctrl simple.

That said, if we want to have these io areas properly assigned to their drivers, we either have children area autogenerated, in DT / hwmod. Or we have them in the code.

Assuming you still want to have the MFD core, for matching w/ the OCP single port, it would still need to have the resources for its children in the driver code.

Or we hack them in the DT entries. Like I already did in this series for the thermal IRQ :-)

Quoted 4 lines

Regards,
Benoit

#27 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

In reply to Tony Lindgren

Hi, Tony.

Quoted 27 lines · Tony Lindgren
Quoted 10 lines · Cousson, Benoit
Quoted 5 lines · Eduardo Valentin
Quoted 4 lines

Mmm, we can have up to 4 control module instances in OMAP4.

Well, I'm not sure it worth considering them as separate devices. Is that your plan as well?

At least for now I was focusing on the ctrl_module_core ...

OK, that's a good start already :-)

Quoted 2 lines
Quoted 2 lines

But since they all have different base address, it will be trick to handle them with only a single entry.

Quoted 8 lines
Quoted 5 lines

Indeed. We can always add the support latter on.

I am not sure what would be the best way to handle those instances though, and how they are going to expose APIs. Would need to have an instance bound to API set?

We should not go to that path I guess. We should have an API at children level independent of the underlying control module partitioning.

These should be separate driver instances for the control modules.

And then the ioremapped area should ignore at least the padconf registers so drivers/pinctrl/pinctrl-simple can handle those. There should not be any dependencies to the SCM driver from pinctrl-simple, the core SCM driver can manage the clocks and trigger the save of padconf regs.

Quoted 8 lines

Also we should allow MMC driver handle the MMC specific registers and USB driver(s) handle the USB specific registers if possible. Those should not live under drivers/mfd unless there are some dependencies other than trying to ioremap the whole SCM module instead of ioremapping in each driver.

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

Actually SCM registers window is mapped statically. Mapping is defined in omap44xx_io_desc[] in arch/arm/mach-omap2/io.c:

...

        .virtual    = L4_44XX_VIRT,
        .pfn        = __phys_to_pfn(L4_44XX_PHYS),
        .length        = L4_44XX_SIZE,
        .type        = MT_DEVICE,

...

So ioremap() always returns same virtual address (0xfc002000).

BR,
Konstantin Baydarov.

Quoted 9 lines

Regards,

Tony

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

maintainer
#28 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 7 lines · Konstantin Baydarov
Quoted 3 lines · Tony Lindgren

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

Actually SCM registers window is mapped statically. Mapping is defined in omap44xx_io_desc[] in arch/arm/mach-omap2/io.c:

...

Quoted 8 lines
        .virtual    = L4_44XX_VIRT,
        .pfn        = __phys_to_pfn(L4_44XX_PHYS),
        .length        = L4_44XX_SIZE,
        .type        = MT_DEVICE,

...

So ioremap() always returns same virtual address (0xfc002000).

Hmm I guess you mean L4_44XX_VIRT + offset. Otherwise drivers would not work at all.. Or else I don't follow you.

Regards,

Tony

#29 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 14 lines · Tony Lindgren
Quoted 13 lines · Konstantin Baydarov
Quoted 2 lines · Tony Lindgren

We can have a static map for the SCM, so ioremapping each driver individually should not be an issue.

Actually SCM registers window is mapped statically. Mapping is defined in omap44xx_io_desc[] in arch/arm/mach-omap2/io.c:

...

        .virtual    = L4_44XX_VIRT,
        .pfn        = __phys_to_pfn(L4_44XX_PHYS),
        .length        = L4_44XX_SIZE,
        .type        = MT_DEVICE,

...

Quoted 3 lines
Quoted 1 line

So ioremap() always returns same virtual address (0xfc002000).

Hmm I guess you mean L4_44XX_VIRT + offset. Otherwise drivers would not work at all.. Or else I don't follow you.

Right. I mean when 0x4A00 2000(scm base) is remapped in scm driver, ioremap() always returns same virtual address (0xfc002000).

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

#30 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

In reply to Eduardo Valentin
Quoted 22 lines · Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---

[..]

arch/arm/plat-omap/Kconfig menu "TI OMAP Common Features" · line 10

Quoted 11 lines
arch/arm/plat-omap/Kconfig +0 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"

?config ARCH_OMAP_OTG
? ? ? ?bool

arch/arm/plat-omap/Kconfig +3 -0
+config ARCH_HAS_CONTROL_MODULE
+ ? ? ? bool
+

Thanks for getting rid of OMAP CONFIG here.

Quoted 88 lines

?choice
? ? ? ?prompt "OMAP System Type"
? ? ? ?default ARCH_OMAP2PLUS

drivers/mfd/Kconfig +0 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ config MFD_WL1273_CORE

? ? ? ? ?driver connects the radio-wl1273 V4L2 module and the wl1273 ? ? ? ? ?audio codec.

drivers/mfd/Kconfig +9 -0
+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. This driver
+ ? ? ? ? is responsible for creating the control module mfd child,
+ ? ? ? ? like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+ ? ? ? ? change for off mode.
+

?config MFD_OMAP_USB_HOST
? ? ? ?bool "Support OMAP USBHS core driver"
? ? ? ?depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3

drivers/mfd/Makefile +0 -0
index 05fa538..00f99d6 100644
@@ -106,6 +106,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 +47 -0
new file mode 100644
index 0000000..7d8d408
@@ -0,0 +1,211 @@
+/*
+ * 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]>
+ *
+ * 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>
+
+static struct omap_control *omap_control_module;
+
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return -EINVAL;
+
+ ? ? ? *val = readl(omap_control->base + reg);
+
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+

I might have missed in the last scan, but can you let function return the register value.

I am guessing, you did this for error case handling. You might want to stick to read API semantic and just have WARN_ON() to take care of error case.

Quoted 99 lines
drivers/mfd/omap-control-core.c new file +99 -0
+/**
+ * omap_control_writel: Write a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @val: value to write.
+ * @reg: register to write to.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_writel(struct device *dev, u32 val, u32 reg)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return -EINVAL;
+
+ ? ? ? spin_lock_irqsave(&omap_control->reg_lock, flags);
+ ? ? ? writel(val, omap_control->base + reg);
+ ? ? ? spin_unlock_irqrestore(&omap_control->reg_lock, flags);
+
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+/**
+ * omap_control_get: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+struct device *omap_control_get(void)
+{
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control_module)
+ ? ? ? ? ? ? ? return ERR_PTR(-ENODEV);
+
+ ? ? ? spin_lock_irqsave(&omap_control_module->reg_lock, flags);
+ ? ? ? omap_control_module->use_count++;
+ ? ? ? spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+
+ ? ? ? return omap_control_module->dev;
+}
+EXPORT_SYMBOL_GPL(omap_control_get);
+
+/**
+ * omap_control_put: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+void omap_control_put(struct device *dev)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return;
+
+ ? ? ? spin_lock_irqsave(&omap_control->reg_lock, flags);
+ ? ? ? omap_control->use_count--;
+ ? ? ? spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(omap_control_put);
+
+static const struct of_device_id of_omap_control_match[] = {
+ ? ? ? { .compatible = "ti,omap3-control", },
+ ? ? ? { .compatible = "ti,omap4-control", },
+ ? ? ? { .compatible = "ti,omap5-control", },
+ ? ? ? { },
+};
+
+static int __devinit omap_control_probe(struct platform_device *pdev)
+{
+ ? ? ? struct resource *res;
+ ? ? ? void __iomem *base;
+ ? ? ? struct device *dev = &pdev->dev;
+ ? ? ? struct device_node *np = dev->of_node;
+ ? ? ? struct omap_control *omap_control;
+
+ ? ? ? omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
+ ? ? ? if (!omap_control) {
+ ? ? ? ? ? ? ? dev_err(dev, "not enough memory for omap_control\n");
+ ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? }
+
+ ? ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ? ? ? if (!res) {
+ ? ? ? ? ? ? ? dev_err(dev, "missing memory base resource\n");
+ ? ? ? ? ? ? ? return -EINVAL;
+ ? ? ? }
+
+ ? ? ? base = devm_request_and_ioremap(dev, res);
+ ? ? ? if (!base) {
+ ? ? ? ? ? ? ? dev_err(dev, "ioremap failed\n");
+ ? ? ? ? ? ? ? return -EADDRNOTAVAIL;
+ ? ? ? }
+

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+ ? ? ? omap_control->base = base;
+ ? ? ? omap_control->dev = dev;
+ ? ? ? spin_lock_init(&omap_control->reg_lock);
+
+ ? ? ? platform_set_drvdata(pdev, omap_control);
+ ? ? ? omap_control_module = omap_control;
+
+ ? ? ? return of_platform_populate(np, of_omap_control_match, NULL, dev);
+}
+

Will the probe get called on multiple devices and race ?

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

Quoted 12 lines
drivers/mfd/omap-control-core.c new file +12 -0
+static int __devexit omap_control_remove(struct platform_device *pdev)
+{
+ ? ? ? struct omap_control *omap_control = platform_get_drvdata(pdev);
+
+ ? ? ? spin_lock(&omap_control->reg_lock);
+ ? ? ? if (omap_control->use_count > 0) {
+ ? ? ? ? ? ? ? spin_unlock(&omap_control->reg_lock);
+ ? ? ? ? ? ? ? dev_err(&pdev->dev, "device removed while still being used\n");
+ ? ? ? ? ? ? ? return -EBUSY;
+ ? ? ? }
+ ? ? ? spin_unlock(&omap_control->reg_lock);
+

Do you really need above lock where you are just doing the register read. smp_rmb(), should be enough, I guess.

Regards
Santosh

#31 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Hello,

Quoted 34 lines · Santosh
Quoted 22 lines · Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---

[..]

Quoted 8 lines
arch/arm/plat-omap/Kconfig +0 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"

?config ARCH_OMAP_OTG
? ? ? ?bool

Quoted 4 lines

arch/arm/plat-omap/Kconfig menu "TI OMAP Common Features" · line 10

Quoted 3 lines
arch/arm/plat-omap/Kconfig +3 -0
+config ARCH_HAS_CONTROL_MODULE
+ ? ? ? bool
+

Thanks for getting rid of OMAP CONFIG here.

OK. ARCH_HAS_CONTROL_MODULE is a bit too generic though..

Quoted 93 lines
Quoted 93 lines

?choice
? ? ? ?prompt "OMAP System Type"
? ? ? ?default ARCH_OMAP2PLUS

drivers/mfd/Kconfig +0 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ config MFD_WL1273_CORE

? ? ? ? ?driver connects the radio-wl1273 V4L2 module and the wl1273 ? ? ? ? ?audio codec.

drivers/mfd/Kconfig +9 -0
+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. This driver
+ ? ? ? ? is responsible for creating the control module mfd child,
+ ? ? ? ? like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+ ? ? ? ? change for off mode.
+

?config MFD_OMAP_USB_HOST
? ? ? ?bool "Support OMAP USBHS core driver"
? ? ? ?depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3

drivers/mfd/Makefile +0 -0
index 05fa538..00f99d6 100644
@@ -106,6 +106,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 +51 -0
new file mode 100644
index 0000000..7d8d408
@@ -0,0 +1,211 @@
+/*
+ * 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]>
+ *
+ * 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>
+
+static struct omap_control *omap_control_module;
+
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return -EINVAL;
+
Quoted 8 lines

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

Quoted 6 lines
drivers/mfd/omap-control-core.c new file +6 -0
+ ? ? ? *val = readl(omap_control->base + reg);
+
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+

I might have missed in the last scan, but can you let function return the register value.

Why?

Quoted 4 lines

I am guessing, you did this for error case handling. You might want to stick to read API semantic and just have WARN_ON() to take care of error case.

Yeah, that was for error handling and to do not confuse register values with error values.

Quoted 104 lines
Quoted 104 lines
drivers/mfd/omap-control-core.c new file +103 -0
+/**
+ * omap_control_writel: Write a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @val: value to write.
+ * @reg: register to write to.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_writel(struct device *dev, u32 val, u32 reg)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return -EINVAL;
+
+ ? ? ? spin_lock_irqsave(&omap_control->reg_lock, flags);
+ ? ? ? writel(val, omap_control->base + reg);
+ ? ? ? spin_unlock_irqrestore(&omap_control->reg_lock, flags);
+
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+/**
+ * omap_control_get: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+struct device *omap_control_get(void)
+{
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control_module)
+ ? ? ? ? ? ? ? return ERR_PTR(-ENODEV);
+
+ ? ? ? spin_lock_irqsave(&omap_control_module->reg_lock, flags);
+ ? ? ? omap_control_module->use_count++;
+ ? ? ? spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+
+ ? ? ? return omap_control_module->dev;
+}
+EXPORT_SYMBOL_GPL(omap_control_get);
+
+/**
+ * omap_control_put: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+void omap_control_put(struct device *dev)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return;
+
+ ? ? ? spin_lock_irqsave(&omap_control->reg_lock, flags);
+ ? ? ? omap_control->use_count--;
+ ? ? ? spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(omap_control_put);
+
+static const struct of_device_id of_omap_control_match[] = {
+ ? ? ? { .compatible = "ti,omap3-control", },
+ ? ? ? { .compatible = "ti,omap4-control", },
+ ? ? ? { .compatible = "ti,omap5-control", },
+ ? ? ? { },
+};
+
+static int __devinit omap_control_probe(struct platform_device *pdev)
+{
+ ? ? ? struct resource *res;
+ ? ? ? void __iomem *base;
+ ? ? ? struct device *dev = &pdev->dev;
+ ? ? ? struct device_node *np = dev->of_node;
+ ? ? ? struct omap_control *omap_control;
+
+ ? ? ? omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
+ ? ? ? if (!omap_control) {
+ ? ? ? ? ? ? ? dev_err(dev, "not enough memory for omap_control\n");
+ ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? }
+
+ ? ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ? ? ? if (!res) {
+ ? ? ? ? ? ? ? dev_err(dev, "missing memory base resource\n");
+ ? ? ? ? ? ? ? return -EINVAL;
+ ? ? ? }
+
+ ? ? ? base = devm_request_and_ioremap(dev, res);
+ ? ? ? if (!base) {
+ ? ? ? ? ? ? ? dev_err(dev, "ioremap failed\n");
+ ? ? ? ? ? ? ? return -EADDRNOTAVAIL;
+ ? ? ? }
+
+ ? ? ? omap_control->base = base;
+ ? ? ? omap_control->dev = dev;
+ ? ? ? spin_lock_init(&omap_control->reg_lock);
+
Quoted 8 lines

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

Quoted 6 lines
drivers/mfd/omap-control-core.c new file +6 -0
+ ? ? ? platform_set_drvdata(pdev, omap_control);
+ ? ? ? omap_control_module = omap_control;
+
+ ? ? ? return of_platform_populate(np, of_omap_control_match, NULL, dev);
+}
+

Will the probe get called on multiple devices and race ?

It depends. If we decide to have an early device for scm, then the probe will be called more than once. If not, then only once.

Quoted 15 lines

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

Quoted 13 lines
drivers/mfd/omap-control-core.c new file +12 -0
+static int __devexit omap_control_remove(struct platform_device *pdev)
+{
+ ? ? ? struct omap_control *omap_control = platform_get_drvdata(pdev);
+
+ ? ? ? spin_lock(&omap_control->reg_lock);
+ ? ? ? if (omap_control->use_count > 0) {
+ ? ? ? ? ? ? ? spin_unlock(&omap_control->reg_lock);
+ ? ? ? ? ? ? ? dev_err(&pdev->dev, "device removed while still being used\n");
+ ? ? ? ? ? ? ? return -EBUSY;
+ ? ? ? }
+ ? ? ? spin_unlock(&omap_control->reg_lock);
+

Do you really need above lock where you are just doing the register read. smp_rmb(), should be enough, I guess.

It is locking the use counter not a register..

Quoted 3 lines

Regards
Santosh

#32 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 146 lines · Eduardo Valentin

Hello,

Quoted 34 lines · Santosh
Quoted 22 lines · Eduardo Valentin

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.

In this patch, the children defined are for:
. USB-phy pin control
. Bangap temperature sensor

Device driver is probed with postcore_initcall. However, as some of the APIs exposed by this driver may be needed in very early init phase, an early init class is also available: "early_omap_control".

---

[..]

Quoted 8 lines
arch/arm/plat-omap/Kconfig +0 -0
index ad95c7a..222dbad 100644
@@ -5,6 +5,9 @@ menu "TI OMAP Common Features"

?config ARCH_OMAP_OTG
? ? ? ?bool

Quoted 4 lines

arch/arm/plat-omap/Kconfig menu "TI OMAP Common Features" · line 10

Quoted 3 lines
arch/arm/plat-omap/Kconfig +3 -0
+config ARCH_HAS_CONTROL_MODULE
+ ? ? ? bool
+

Thanks for getting rid of OMAP CONFIG here.

OK. ARCH_HAS_CONTROL_MODULE is a bit too generic though..

Quoted 93 lines
Quoted 93 lines

?choice
? ? ? ?prompt "OMAP System Type"
? ? ? ?default ARCH_OMAP2PLUS

drivers/mfd/Kconfig +0 -0
index 11e4438..25a66d8 100644
@@ -795,6 +795,15 @@ config MFD_WL1273_CORE

? ? ? ? ?driver connects the radio-wl1273 V4L2 module and the wl1273 ? ? ? ? ?audio codec.

drivers/mfd/Kconfig +9 -0
+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. This driver
+ ? ? ? ? is responsible for creating the control module mfd child,
+ ? ? ? ? like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+ ? ? ? ? change for off mode.
+

?config MFD_OMAP_USB_HOST
? ? ? ?bool "Support OMAP USBHS core driver"
? ? ? ?depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3

drivers/mfd/Makefile +0 -0
index 05fa538..00f99d6 100644
@@ -106,6 +106,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 +51 -0
new file mode 100644
index 0000000..7d8d408
@@ -0,0 +1,211 @@
+/*
+ * 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]>
+ *
+ * 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>
+
+static struct omap_control *omap_control_module;
+
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return -EINVAL;
+
Quoted 8 lines

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

Quoted 6 lines
drivers/mfd/omap-control-core.c new file +6 -0
+ ? ? ? *val = readl(omap_control->base + reg);
+
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+

I might have missed in the last scan, but can you let function return the register value.

Quoted 2 lines

Why?

Because thats how typical read 1 value kind of functions look like..

Quoted 8 lines
Quoted 4 lines

I am guessing, you did this for error case handling. You might want to stick to read API semantic and just have WARN_ON() to take care of error case.

Yeah, that was for error handling and to do not confuse register values with error values.

No strong opinion if you like it that way but it just appeared odd to me from a caller perspective.

Quoted 113 lines
Quoted 104 lines
Quoted 104 lines
drivers/mfd/omap-control-core.c new file +103 -0
+/**
+ * omap_control_writel: Write a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @val: value to write.
+ * @reg: register to write to.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_writel(struct device *dev, u32 val, u32 reg)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return -EINVAL;
+
+ ? ? ? spin_lock_irqsave(&omap_control->reg_lock, flags);
+ ? ? ? writel(val, omap_control->base + reg);
+ ? ? ? spin_unlock_irqrestore(&omap_control->reg_lock, flags);
+
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+/**
+ * omap_control_get: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+struct device *omap_control_get(void)
+{
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control_module)
+ ? ? ? ? ? ? ? return ERR_PTR(-ENODEV);
+
+ ? ? ? spin_lock_irqsave(&omap_control_module->reg_lock, flags);
+ ? ? ? omap_control_module->use_count++;
+ ? ? ? spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+
+ ? ? ? return omap_control_module->dev;
+}
+EXPORT_SYMBOL_GPL(omap_control_get);
+
+/**
+ * omap_control_put: returns the control module device pinter
+ *
+ * The modules which has to use control module API's to read or write should
+ * call this API to get the control module device pointer.
+ */
+void omap_control_put(struct device *dev)
+{
+ ? ? ? struct omap_control *omap_control = dev_get_drvdata(dev);
+ ? ? ? unsigned long flags;
+
+ ? ? ? if (!omap_control)
+ ? ? ? ? ? ? ? return;
+
+ ? ? ? spin_lock_irqsave(&omap_control->reg_lock, flags);
+ ? ? ? omap_control->use_count--;
+ ? ? ? spin_unlock_irqrestore(&omap_control_module->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(omap_control_put);
+
+static const struct of_device_id of_omap_control_match[] = {
+ ? ? ? { .compatible = "ti,omap3-control", },
+ ? ? ? { .compatible = "ti,omap4-control", },
+ ? ? ? { .compatible = "ti,omap5-control", },
+ ? ? ? { },
+};
+
+static int __devinit omap_control_probe(struct platform_device *pdev)
+{
+ ? ? ? struct resource *res;
+ ? ? ? void __iomem *base;
+ ? ? ? struct device *dev = &pdev->dev;
+ ? ? ? struct device_node *np = dev->of_node;
+ ? ? ? struct omap_control *omap_control;
+
+ ? ? ? omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
+ ? ? ? if (!omap_control) {
+ ? ? ? ? ? ? ? dev_err(dev, "not enough memory for omap_control\n");
+ ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? }
+
+ ? ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ? ? ? if (!res) {
+ ? ? ? ? ? ? ? dev_err(dev, "missing memory base resource\n");
+ ? ? ? ? ? ? ? return -EINVAL;
+ ? ? ? }
+
+ ? ? ? base = devm_request_and_ioremap(dev, res);
+ ? ? ? if (!base) {
+ ? ? ? ? ? ? ? dev_err(dev, "ioremap failed\n");
+ ? ? ? ? ? ? ? return -EADDRNOTAVAIL;
+ ? ? ? }
+
+ ? ? ? omap_control->base = base;
+ ? ? ? omap_control->dev = dev;
+ ? ? ? spin_lock_init(&omap_control->reg_lock);
+
Quoted 8 lines

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

Quoted 6 lines
drivers/mfd/omap-control-core.c new file +6 -0
+ ? ? ? platform_set_drvdata(pdev, omap_control);
+ ? ? ? omap_control_module = omap_control;
+
+ ? ? ? return of_platform_populate(np, of_omap_control_match, NULL, dev);
+}
+

Will the probe get called on multiple devices and race ?

Quoted 3 lines

It depends. If we decide to have an early device for scm, then the probe will be called more than once. If not, then only once.

OK. But in either case it won't race so that's fine.

Quoted 16 lines
Quoted 15 lines

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

Quoted 13 lines
drivers/mfd/omap-control-core.c new file +12 -0
+static int __devexit omap_control_remove(struct platform_device *pdev)
+{
+ ? ? ? struct omap_control *omap_control = platform_get_drvdata(pdev);
+
+ ? ? ? spin_lock(&omap_control->reg_lock);
+ ? ? ? if (omap_control->use_count > 0) {
+ ? ? ? ? ? ? ? spin_unlock(&omap_control->reg_lock);
+ ? ? ? ? ? ? ? dev_err(&pdev->dev, "device removed while still being used\n");
+ ? ? ? ? ? ? ? return -EBUSY;
+ ? ? ? }
+ ? ? ? spin_unlock(&omap_control->reg_lock);
+

Do you really need above lock where you are just doing the register read. smp_rmb(), should be enough, I guess.

Quoted 2 lines

It is locking the use counter not a register..

Yes I know. But is just read and you can do away and hence you can avoid the lock.

Regards
Santosh

#33 lore raw

RFC PATCH 5/11 mfd: omap: control: core system control driver

Quoted 1 line · Santosh

On Mon, May 28, 2012 at 5:12 PM, Eduardo Valentin

[...]

Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
Quoted 12 lines
drivers/mfd/omap-control-core.c new file +12 -0
+/**
+ * omap_control_readl: Read a single omap control module register.
+ *
+ * @dev: device to read from.
+ * @reg: register to read.
+ * @val: output with register value.
+ *
+ * returns 0 on success or -EINVAL in case struct device is invalid.
+ */
+int omap_control_readl(struct device *dev, u32 reg, u32 *val)
+{
+       struct omap_control *omap_control = dev_get_drvdata(dev);

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

Quoted 10 lines
drivers/mfd/omap-control-core.c new file +10 -0
+
+       if (!omap_control)
+               return -EINVAL;
+
+       *val = readl(omap_control->base + reg);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_readl);
+

I might have missed in the last scan, but can you let function return the register value.

Quoted 4 lines
Quoted 2 lines

Why?

Because thats how typical read 1 value kind of functions look like..

Yeah, I tend to agree with Santosh here as well. I'm expecting such API to return the value.
Moreover the error handling in that case is really an exception and thus a WARM is enough since it should never ever happen except if there is a bug during the probe. And in that case, it should already fail at probe time.

Quoted 9 lines
Quoted 7 lines
Quoted 3 lines

I am guessing, you did this for error case handling. You might want to stick to read API semantic and just have WARN_ON() to take care of error case.

Yeah, that was for error handling and to do not confuse register values with error values.

No strong opinion if you like it that way but it just appeared odd to me from a caller perspective.

Yep, I do agree.

Benoit

#34 lore raw

RFC PATCH 6/11 OMAP2+: use control module mfd driver in omap_type

In reply to Eduardo Valentin

OMAP system control module can be probed early, then omap_type is safe to use its APIs.

TODO: add support for other omap versions

---
 arch/arm/mach-omap2/id.c |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/id.c +15 -1
index 5bb9746..acfd698 100644
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/mfd/omap_control.h>
 
 #include <asm/cputype.h>
 
@@ -40,8 +41,14 @@ EXPORT_SYMBOL(omap_rev);
 
 int omap_type(void)
 {
+	struct device *scm;
+	int ret = 0;
 	u32 val = 0;
 
+	scm = omap_control_get();
+	if (IS_ERR_OR_NULL(scm))
+		return 0;
+
 	if (cpu_is_omap24xx()) {
 		val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
 	} else if (cpu_is_am33xx()) {
@@ -49,16 +56,23 @@ int omap_type(void)
 	} 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);
+		ret = omap_control_readl(scm, OMAP4_CTRL_MODULE_CORE_STATUS,
+					 &val);
 	} else {
 		pr_err("Cannot detect omap type!\n");
 		goto out;
 	}
 
+	if (ret) {
+		pr_err("problem while fetching omap type\n");
+		goto out;
+	}
+
 	val &= OMAP2_DEVICETYPE_MASK;
 	val >>= 8;
 
 out:
+	omap_control_put(scm);
 	return val;
 }
 EXPORT_SYMBOL(omap_type);
Signature · 1 line
1.7.7.1.488.ge8e1c
#35 lore raw

RFC PATCH 6/11 OMAP2+: use control module mfd driver in omap_type

Hi Eduardo,

Quoted 25 lines · Eduardo Valentin

OMAP system control module can be probed early, then omap_type is safe to use its APIs.

TODO: add support for other omap versions

---
  arch/arm/mach-omap2/id.c |   16 +++++++++++++++-
  1 files changed, 15 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/id.c +1 -0
index 5bb9746..acfd698 100644
@@ -18,6 +18,7 @@
  #include<linux/kernel.h>
  #include<linux/init.h>
  #include<linux/io.h>
+#include<linux/mfd/omap_control.h>
 
  #include<asm/cputype.h>
 
@@ -40,8 +41,14 @@ EXPORT_SYMBOL(omap_rev);
 
  int omap_type(void)

arch/arm/mach-omap2/id.c EXPORT_SYMBOL(omap_rev); · line 52

Quoted 10 lines
arch/arm/mach-omap2/id.c +6 -0
  {
+	struct device *scm;
+	int ret = 0;
  	u32 val = 0;
 
+	scm = omap_control_get();
+	if (IS_ERR_OR_NULL(scm))
+		return 0;
+
  	if (cpu_is_omap24xx()) {

OK, not really related to that patch, but the previous cpu_is_omap24xx makes me think of that :-)

What about the omap<X>_check_revision used by cpu_is_XXX?

This call is the very first one to require the control module access in order to get the ID_CODE inside the control module.

So far it still use that ugly hard coded phys -> virtual address macro that is sued for that.

arch/arm/mach-omap2/id.c int omap_type(void) · line 60

Quoted 9 lines
arch/arm/mach-omap2/id.c +2 -1
  		val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
  	} else if (cpu_is_am33xx()) {
@@ -49,16 +56,23 @@ int omap_type(void)
  	} 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);
+		ret = omap_control_readl(scm, OMAP4_CTRL_MODULE_CORE_STATUS,
+					&val);

I guess you should get rid of these cpu_is_omap44xx and store the omap_type somewhere to avoid further access to the control module since there are a couple of places that use that API.

Not necessarily in this patch for sure, but something that might be done in this series.

Regards,
Benoit

#36 lore raw

RFC PATCH 6/11 OMAP2+: use control module mfd driver in omap_type

Quoted 45 lines · Benoit

Hi Eduardo,

Quoted 26 lines · Eduardo Valentin

OMAP system control module can be probed early, then omap_type is safe to use its APIs.

TODO: add support for other omap versions

---
?arch/arm/mach-omap2/id.c | ? 16 +++++++++++++++- ?1 files changed, 15 insertions(+), 1 deletions(-)

arch/arm/mach-omap2/id.c +0 -0
index 5bb9746..acfd698 100644
@@ -18,6 +18,7 @@

?#include<linux/kernel.h>
?#include<linux/init.h>
?#include<linux/io.h>
+#include<linux/mfd/omap_control.h>

?#include<asm/cputype.h>

arch/arm/mach-omap2/id.c +0 -0
@@ -40,8 +41,14 @@ EXPORT_SYMBOL(omap_rev);
 
 ?int omap_type(void)

arch/arm/mach-omap2/id.c EXPORT_SYMBOL(omap_rev); · line 52

Quoted 10 lines
arch/arm/mach-omap2/id.c +6 -0
 ?{
+ ? ? ? struct device *scm;
+ ? ? ? int ret = 0;
 ? ? ? ?u32 val = 0;
 
+ ? ? ? scm = omap_control_get();
+ ? ? ? if (IS_ERR_OR_NULL(scm))
+ ? ? ? ? ? ? ? return 0;
+
 ? ? ? ?if (cpu_is_omap24xx()) {

OK, not really related to that patch, but the previous cpu_is_omap24xx makes me think of that :-)

Quoted 8 lines

What about the omap<X>_check_revision used by cpu_is_XXX?

This call is the very first one to require the control module access in order to get the ID_CODE inside the control module.

So far it still use that ugly hard coded phys -> virtual address macro that is sued for that.

Agree with Benoits comment. One way to deal with this is, store the register offset with init and then just use it here.

That way you can get rid of all cpu_is_XXXX() from this function.

Regards
Santosh

#37 lore raw

RFC PATCH 6/11 OMAP2+: use control module mfd driver in omap_type

Hello,

Quoted 51 lines · Santosh
Quoted 50 lines · Benoit

Hi Eduardo,

Quoted 26 lines · Eduardo Valentin

OMAP system control module can be probed early, then omap_type is safe to use its APIs.

TODO: add support for other omap versions

---
?arch/arm/mach-omap2/id.c | ? 16 +++++++++++++++- ?1 files changed, 15 insertions(+), 1 deletions(-)

arch/arm/mach-omap2/id.c +0 -0
index 5bb9746..acfd698 100644
@@ -18,6 +18,7 @@

?#include<linux/kernel.h>
?#include<linux/init.h>
?#include<linux/io.h>
+#include<linux/mfd/omap_control.h>

?#include<asm/cputype.h>

arch/arm/mach-omap2/id.c +0 -0
@@ -40,8 +41,14 @@ EXPORT_SYMBOL(omap_rev);
 
 ?int omap_type(void)

arch/arm/mach-omap2/id.c EXPORT_SYMBOL(omap_rev); · line 52

Quoted 10 lines
arch/arm/mach-omap2/id.c +6 -0
 ?{
+ ? ? ? struct device *scm;
+ ? ? ? int ret = 0;
 ? ? ? ?u32 val = 0;
 
+ ? ? ? scm = omap_control_get();
+ ? ? ? if (IS_ERR_OR_NULL(scm))
+ ? ? ? ? ? ? ? return 0;
+
 ? ? ? ?if (cpu_is_omap24xx()) {

OK, not really related to that patch, but the previous cpu_is_omap24xx makes me think of that :-)

What about the omap<X>_check_revision used by cpu_is_XXX?

This call is the very first one to require the control module access in order to get the ID_CODE inside the control module.

Quoted 7 lines
Quoted 3 lines

So far it still use that ugly hard coded phys -> virtual address macro that is sued for that.

Agree with Benoits comment. One way to deal with this is, store the register offset with init and then just use it here.

That way you can get rid of all cpu_is_XXXX() from this function.

I see. I need to check how this storing would look like. Probably we can do the storing when the early device gets probed.

Quoted 3 lines

Regards
Santosh

maintainer
#38 lore raw

RFC PATCH 6/11 OMAP2+: use control module mfd driver in omap_type

Quoted 14 lines · Eduardo Valentin
Quoted 13 lines · Santosh
Quoted 12 lines · Benoit

OK, not really related to that patch, but the previous cpu_is_omap24xx makes me think of that :-)

What about the omap<X>_check_revision used by cpu_is_XXX?

This call is the very first one to require the control module access in order to get the ID_CODE inside the control module.

So far it still use that ugly hard coded phys -> virtual address macro that is sued for that.

Quoted 7 lines
Quoted 4 lines

Agree with Benoits comment. One way to deal with this is, store the register offset with init and then just use it here.

That way you can get rid of all cpu_is_XXXX() from this function.

I see. I need to check how this storing would look like. Probably we can do the storing when the early device gets probed.

As this needs to be initialized very early I'd rather avoid dependencies to drivers for this. Maybe that register can be read and saved when the device gets built? It's ioremapped anyways at that point.

That is assuming we don't need to export it to drivers or constantly read it..

Tony

#39 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

In reply to Eduardo Valentin

Created a new platform driver for the platform device created by the control module mfd core, wrt usb. This driver has API's to power on/off the phy and the API's to write to musb mailbox.

(p.s. the mailbox for musb in omap4 is present in system control module)

[kishon at ti.com: wrote the original API's related to USB functions]
---
 drivers/usb/otg/Kconfig           |   13 ++++
 drivers/usb/otg/Makefile          |    1 +
 drivers/usb/otg/omap4-usb-phy.c   |  130 +++++++++++++++++++++++++++++++++++++
 include/linux/usb/omap4_usb_phy.h |   53 +++++++++++++++
 4 files changed, 197 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/otg/omap4-usb-phy.c
 create mode 100644 include/linux/usb/omap4_usb_phy.h
drivers/usb/otg/Kconfig +13 -0
index 5c87db0..e2840f1 100644
@@ -78,6 +78,19 @@ config TWL6030_USB
 	  are hooked to this driver through platform_data structure.
 	  The definition of internal PHY APIs are in the mach-omap2 layer.
 
+config OMAP4_USB_PHY
+	tristate "Texas Instruments OMAP4+ USB pin control driver"
+	depends on MFD_OMAP_CONTROL
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  OMAP4+ USB pin control driver. The register set is part of system
+	  control module.
+
+	  USB phy in OMAP configures control module register for powering on
+	  the phy, configuring VBUSVALID, AVALID, IDDIG and SESSEND. For
+	  performing the above mentioned configuration, API's are added in
+	  by this children of the control module driver.
+
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
 	select USB_OTG_UTILS
drivers/usb/otg/Makefile +1 -0
index 41aa509..60c8c83 100644
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
+obj-$(CONFIG_OMAP4_USB_PHY)	+= omap4-usb-phy.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o
drivers/usb/otg/omap4-usb-phy.c new file +130 -0

130 lines not on this page · raw message

include/linux/usb/omap4_usb_phy.h new file +53 -0

53 lines not on this page · raw message

Signature · 1 line
1.7.7.1.488.ge8e1c
#40 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

Hi Edurardo,
A few doubts,

Quoted 88 lines · Eduardo Valentin

Created a new platform driver for the platform device created by the control module mfd core, wrt usb. This driver has API's to power on/off the phy and the API's to write to musb mailbox.

(p.s. the mailbox for musb in omap4 is present in system control module)

[kishon at ti.com: wrote the original API's related to USB functions]

---

?drivers/usb/otg/Kconfig ? ? ? ? ? | ? 13 ++++
?drivers/usb/otg/Makefile ? ? ? ? ?| ? ?1 +
?drivers/usb/otg/omap4-usb-phy.c ? | ?130 +++++++++++++++++++++++++++++++++++++
?include/linux/usb/omap4_usb_phy.h | ? 53 +++++++++++++++

?4 files changed, 197 insertions(+), 0 deletions(-) ?create mode 100644 drivers/usb/otg/omap4-usb-phy.c ?create mode 100644 include/linux/usb/omap4_usb_phy.h

drivers/usb/otg/Kconfig +0 -0
index 5c87db0..e2840f1 100644
@@ -78,6 +78,19 @@ config TWL6030_USB

? ? ? ? ?are hooked to this driver through platform_data structure. ? ? ? ? ?The definition of internal PHY APIs are in the mach-omap2 layer.

drivers/usb/otg/Kconfig +13 -0
+config OMAP4_USB_PHY
+ ? ? ? tristate "Texas Instruments OMAP4+ USB pin control driver"
+ ? ? ? depends on MFD_OMAP_CONTROL
+ ? ? ? help
+ ? ? ? ? If you say yes here you get support for the Texas Instruments
+ ? ? ? ? OMAP4+ USB pin control driver. The register set is part of system
+ ? ? ? ? control module.
+
+ ? ? ? ? USB phy in OMAP configures control module register for powering on
+ ? ? ? ? the phy, configuring VBUSVALID, AVALID, IDDIG and SESSEND. For
+ ? ? ? ? performing the above mentioned configuration, API's are added in
+ ? ? ? ? by this children of the control module driver.
+

?config NOP_USB_XCEIV
? ? ? ?tristate "NOP USB Transceiver Driver"
? ? ? ?select USB_OTG_UTILS

drivers/usb/otg/Makefile +0 -0
index 41aa509..60c8c83 100644
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_GPIO_VBUS) ? += gpio_vbus.o

?obj-$(CONFIG_ISP1301_OMAP) ? ? += isp1301_omap.o ?obj-$(CONFIG_TWL4030_USB) ? ? ?+= twl4030-usb.o ?obj-$(CONFIG_TWL6030_USB) ? ? ?+= twl6030-usb.o +obj-$(CONFIG_OMAP4_USB_PHY) ? ?+= omap4-usb-phy.o ?obj-$(CONFIG_NOP_USB_XCEIV) ? ?+= nop-usb-xceiv.o ?obj-$(CONFIG_USB_ULPI) ? ? ? ? += ulpi.o ?obj-$(CONFIG_USB_ULPI_VIEWPORT) ? ? ? ?+= ulpi_viewport.o

drivers/usb/otg/omap4-usb-phy.c new file +27 -0
new file mode 100644
index 0000000..a29ea45
@@ -0,0 +1,130 @@
+/*
+ * OMAP4 system control module driver, USB control children
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Contact:
+ * ? ?Kishon Vijay Abraham I <[email protected]>
+ * ? ?Eduardo Valentin <[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>

drivers/usb/otg/omap4-usb-phy.c line 37

Quoted 10 lines
drivers/usb/otg/omap4-usb-phy.c new file +10 -0
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/omap_control.h>
+#include <linux/usb/omap4_usb_phy.h>
+
+/**
+ * omap4_usb_phy_power - power on/off the phy using control module reg
+ * @dev: struct device *
+ * @on: 0 or 1, based on powering on or off the PHY

Could it be bool ?

Quoted 5 lines
drivers/usb/otg/omap4-usb-phy.c new file +5 -0
+ *
+ * omap_usb2 can call this API to power on or off the PHY.
+ */
+int omap4_usb_phy_power(struct device *dev, int on)
+{

drivers/usb/otg/omap4-usb-phy.c line 52

Quoted 10 lines
drivers/usb/otg/omap4-usb-phy.c new file +10 -0
+ ? ? ? u32 val;
+ ? ? ? int ret;
+
+ ? ? ? if (on) {
+ ? ? ? ? ? ? ? ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
+ ? ? ? ? ? ? ? if (!ret && (val & PHY_PD)) {
+ ? ? ? ? ? ? ? ? ? ? ? ret = omap_control_writel(dev, ~PHY_PD,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CONTROL_DEV_CONF);
+ ? ? ? ? ? ? ? ? ? ? ? /* XXX: add proper documentation for this delay */
+ ? ? ? ? ? ? ? ? ? ? ? mdelay(200);

Also does it have to be a busy one?

#41 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

In reply to Eduardo Valentin
Quoted 10 lines · Eduardo Valentin

Created a new platform driver for the platform device created by the control module mfd core, wrt usb. This driver has API's to power on/off the phy and the API's to write to musb mailbox.

(p.s. the mailbox for musb in omap4 is present in system control module)

[kishon at ti.com: wrote the original API's related to USB functions]

...

Quoted 6 lines
drivers/usb/otg/omap4-usb-phy.c new file +6 -0
+/**
+ * omap4_usb_phy_mailbox - write to usb otg mailbox
+ * @dev: struct device *
+ * @val: the value to be written to the mailbox
+ *
+ * On detection of a device (ID pin is grounded), the phy should call this API

drivers/usb/otg/omap4-usb-phy.c line 77

Quoted 10 lines
drivers/usb/otg/omap4-usb-phy.c new file +10 -0
+ * to set AVALID, VBUSVALID and ID pin is grounded.
+ *
+ * When OMAP is connected to a host (OMAP in device mode), the phy should call
+ * this API to set AVALID, VBUSVALID and ID pin in high impedance.
+ *
+ * The phy should call this API, if OMAP is disconnected from host or device.
+ */
+int omap4_usb_phy_mailbox(struct device *dev, u32 val)
+{
+	return omap_control_writel(dev, val, CONTROL_USBOTGHS_CONTROL);

Mmm, I'm missing something. The device for usb_phy mailbox cannot be the same than the device for the scm...

drivers/usb/otg/omap4-usb-phy.c line 85

Quoted 8 lines
drivers/usb/otg/omap4-usb-phy.c new file +8 -0
+}
+EXPORT_SYMBOL_GPL(omap4_usb_phy_mailbox);
+
+static int __devinit omap_usb_phy_probe(struct platform_device *pdev)
+{
+	struct omap_control *omap_control;
+
+	omap_control = dev_get_drvdata(pdev->dev.parent);

Directly accessing your parent device data does not looks very nice to me. Maybe that's only me, but I'll never try to sneak into my parents stuff :-)

You previously exposed an API to get/put the control module device, so I guess you should use it from the probe.

drivers/usb/otg/omap4-usb-phy.c line 90

Quoted 5 lines
drivers/usb/otg/omap4-usb-phy.c new file +5 -0
+
+	if (!omap_control) {
+		dev_err(&pdev->dev, "no omap_control in our parent\n");
+		return -EINVAL;
+	}

BTW, where is the omap_control struct used?

I'm not sure to understand how the user is supposed to call that API?

Regards,
Benoit

maintainer
#42 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

In reply to Eduardo Valentin
Quoted 10 lines · Eduardo Valentin
drivers/usb/otg/omap4-usb-phy.c new file +10 -0
+int omap4_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	int ret;
+
+	if (on) {
+		ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
+		if (!ret && (val & PHY_PD)) {
+			ret = omap_control_writel(dev, ~PHY_PD,
+						  CONTROL_DEV_CONF);

drivers/usb/otg/omap4-usb-phy.c line 60

Quoted 10 lines
drivers/usb/otg/omap4-usb-phy.c new file +10 -0
+			/* XXX: add proper documentation for this delay */
+			mdelay(200);
+		}
+	} else {
+		ret = omap_control_writel(dev, PHY_PD, CONTROL_DEV_CONF);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(omap4_usb_phy_power);

I'm not quite convinced that we should export omap_control_read/write to drivers. If there's a clear register area this USB phy driver can manage, then ioremaping it separately makes sense. If it's just one register, then exporting something like omap_control_usb_phy_set() might be better for ensuring that drivers don't mess up things for other drivers.

Regards,

Tony

maintainer
#43 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

Quoted 20 lines · Tony Lindgren
Quoted 19 lines · Eduardo Valentin
drivers/usb/otg/omap4-usb-phy.c new file +19 -0
+int omap4_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	int ret;
+
+	if (on) {
+		ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
+		if (!ret && (val & PHY_PD)) {
+			ret = omap_control_writel(dev, ~PHY_PD,
+						  CONTROL_DEV_CONF);
+			/* XXX: add proper documentation for this delay */
+			mdelay(200);
+		}
+	} else {
+		ret = omap_control_writel(dev, PHY_PD, CONTROL_DEV_CONF);
+	}
+
+	return ret;
+}
Quoted 8 lines
Quoted 1 line

+EXPORT_SYMBOL_GPL(omap4_usb_phy_power);

I'm not quite convinced that we should export omap_control_read/write to drivers. If there's a clear register area this USB phy driver can manage, then ioremaping it separately makes sense. If it's just one register, then exporting something like omap_control_usb_phy_set() might be better for ensuring that drivers don't mess up things for other drivers.

After chatting with Benoit a bit we came to the conclusion that the clock and powerdomain state needs to be managed for the children by the SCM core driver so the children can't be completely independent.

But rather than exporting omap_control_read/write, maybe you can register the usb/bandgap whatever children with SCM core driver, then have the runtime PM calls from children be passthrough calls to the parent?

Maybe Kevin has some better ideas here?

Regards,

Tony

#44 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

Quoted 34 lines · Tony Lindgren
Quoted 20 lines · Tony Lindgren
Quoted 19 lines · Eduardo Valentin
drivers/usb/otg/omap4-usb-phy.c new file +19 -0
+int omap4_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	int ret;
+
+	if (on) {
+		ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
+		if (!ret && (val & PHY_PD)) {
+			ret = omap_control_writel(dev, ~PHY_PD,
+						  CONTROL_DEV_CONF);
+			/* XXX: add proper documentation for this delay */
+			mdelay(200);
+		}
+	} else {
+		ret = omap_control_writel(dev, PHY_PD, CONTROL_DEV_CONF);
+	}
+
+	return ret;
+}
Quoted 8 lines
Quoted 1 line

+EXPORT_SYMBOL_GPL(omap4_usb_phy_power);

I'm not quite convinced that we should export omap_control_read/write to drivers. If there's a clear register area this USB phy driver can manage, then ioremaping it separately makes sense. If it's just one register, then exporting something like omap_control_usb_phy_set() might be better for ensuring that drivers don't mess up things for other drivers.

After chatting with Benoit a bit we came to the conclusion that the clock and powerdomain state needs to be managed for the children by the SCM core driver so the children can't be completely independent.

Quoted 6 lines

But rather than exporting omap_control_read/write, maybe you can register the usb/bandgap whatever children with SCM core driver, then have the runtime PM calls from children be passthrough calls to the parent?

Maybe Kevin has some better ideas here?

Handling this with parent/child relationships is the way to go for runtime PM.

In MFD, are all sub-devices always children of the core device in the LDM? If so, it seems relatively easy to handle. If the parent/child relationships are modeled correctly in the LDM, then the children do not have to know anything about their parent, the runtime PM core will handle this (parent will not be runtime suspended until all the children are.)

Kevin

maintainer
#45 lore raw

RFC PATCH 7/11 mfd: omap: control: usb-phy: introduce the ctrl-module usb driver

Quoted 43 lines · Kevin Hilman
Quoted 34 lines · Tony Lindgren
Quoted 20 lines · Tony Lindgren
Quoted 19 lines · Eduardo Valentin
drivers/usb/otg/omap4-usb-phy.c new file +19 -0
+int omap4_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	int ret;
+
+	if (on) {
+		ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
+		if (!ret && (val & PHY_PD)) {
+			ret = omap_control_writel(dev, ~PHY_PD,
+						  CONTROL_DEV_CONF);
+			/* XXX: add proper documentation for this delay */
+			mdelay(200);
+		}
+	} else {
+		ret = omap_control_writel(dev, PHY_PD, CONTROL_DEV_CONF);
+	}
+
+	return ret;
+}
Quoted 8 lines
Quoted 1 line

+EXPORT_SYMBOL_GPL(omap4_usb_phy_power);

I'm not quite convinced that we should export omap_control_read/write to drivers. If there's a clear register area this USB phy driver can manage, then ioremaping it separately makes sense. If it's just one register, then exporting something like omap_control_usb_phy_set() might be better for ensuring that drivers don't mess up things for other drivers.

After chatting with Benoit a bit we came to the conclusion that the clock and powerdomain state needs to be managed for the children by the SCM core driver so the children can't be completely independent.

Quoted 6 lines

But rather than exporting omap_control_read/write, maybe you can register the usb/bandgap whatever children with SCM core driver, then have the runtime PM calls from children be passthrough calls to the parent?

Maybe Kevin has some better ideas here?

Quoted 8 lines

Handling this with parent/child relationships is the way to go for runtime PM.

In MFD, are all sub-devices always children of the core device in the LDM? If so, it seems relatively easy to handle. If the parent/child relationships are modeled correctly in the LDM, then the children do not have to know anything about their parent, the runtime PM core will handle this (parent will not be runtime suspended until all the children are.)

OK, so the parent-child relationship is there for DT case, but how do we set it for non-DT case? Call something like this from children:

omap_scm_register(dev, OMAP_SCM_USB_PHY) that then does device_move?

Tony

#46 lore raw

RFC PATCH 8/11 ARM: OMAP4+: Adding the temperature sensor register set bit fields

In reply to Eduardo Valentin

OMAP4460 specific temperature sensor register bit fields are added. Existing OMAP4 entries are renamed to OMAP4430.

---
 arch/arm/mach-omap2/include/mach/control.h |  116 ++++++++++++++++++++++++++++
 1 files changed, 116 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/include/mach/control.h +116 -0
index cf42764..171b504 100644
@@ -230,6 +230,122 @@
 /* OMAP44xx control McBSP padconf */
 #define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP	0x061c
 
+/* TEMP_SENSOR OMAP4430 */
+#define OMAP4430_BGAP_TEMPSOFF_SHIFT			12
+#define OMAP4430_BGAP_TEMPSOFF_MASK			(1 << 12)
+#define OMAP4430_BGAP_TSHUT_SHIFT				11
+#define OMAP4430_BGAP_TSHUT_MASK				(1 << 11)
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT		9
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
+
+/* TEMP_SENSOR OMAP4460 */
+#define OMAP4460_BGAP_TEMPSOFF_SHIFT			13
+#define OMAP4460_BGAP_TEMPSOFF_MASK			(1 << 13)
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT		11
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 11)
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 10)
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
+
+/* BANDGAP_CTRL */
+#define OMAP4460_SINGLE_MODE_SHIFT			31
+#define OMAP4460_SINGLE_MODE_MASK			(1 << 31)
+#define OMAP4460_MASK_HOT_SHIFT				1
+#define OMAP4460_MASK_HOT_MASK				(1 << 1)
+#define OMAP4460_MASK_COLD_SHIFT			0
+#define OMAP4460_MASK_COLD_MASK				(1 << 0)
+
+/* BANDGAP_COUNTER */
+#define OMAP4460_COUNTER_SHIFT				0
+#define OMAP4460_COUNTER_MASK				(0xffffff << 0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP4460_T_HOT_SHIFT				16
+#define OMAP4460_T_HOT_MASK				(0x3ff << 16)
+#define OMAP4460_T_COLD_SHIFT				0
+#define OMAP4460_T_COLD_MASK				(0x3ff << 0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP4460_TSHUT_HOT_SHIFT			16
+#define OMAP4460_TSHUT_HOT_MASK				(0x3ff << 16)
+#define OMAP4460_TSHUT_COLD_SHIFT			0
+#define OMAP4460_TSHUT_COLD_MASK			(0x3ff << 0)
+
+/* BANDGAP_STATUS */
+#define OMAP4460_CLEAN_STOP_SHIFT			3
+#define OMAP4460_CLEAN_STOP_MASK			(1 << 3)
+#define OMAP4460_BGAP_ALERT_SHIFT			2
+#define OMAP4460_BGAP_ALERT_MASK			(1 << 2)
+#define OMAP4460_HOT_FLAG_SHIFT				1
+#define OMAP4460_HOT_FLAG_MASK				(1 << 1)
+#define OMAP4460_COLD_FLAG_SHIFT			0
+#define OMAP4460_COLD_FLAG_MASK				(1 << 0)
+
+/* TEMP_SENSOR OMAP5430 */
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT		12
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 12)
+#define OMAP5430_BGAP_TEMPSOFF_SHIFT			11
+#define OMAP5430_BGAP_TEMPSOFF_MASK			(1 << 11)
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 10)
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
+
+/* BANDGAP_CTRL */
+#define OMAP5430_MASK_HOT_CORE_SHIFT			5
+#define OMAP5430_MASK_HOT_CORE_MASK			(1 << 5)
+#define OMAP5430_MASK_COLD_CORE_SHIFT			4
+#define OMAP5430_MASK_COLD_CORE_MASK			(1 << 4)
+#define OMAP5430_MASK_HOT_MM_SHIFT			3
+#define OMAP5430_MASK_HOT_MM_MASK			(1 << 3)
+#define OMAP5430_MASK_COLD_MM_SHIFT			2
+#define OMAP5430_MASK_COLD_MM_MASK			(1 << 2)
+#define OMAP5430_MASK_HOT_MPU_SHIFT			1
+#define OMAP5430_MASK_HOT_MPU_MASK			(1 << 1)
+#define OMAP5430_MASK_COLD_MPU_SHIFT			0
+#define OMAP5430_MASK_COLD_MPU_MASK			(1 << 0)
+
+/* BANDGAP_COUNTER */
+#define OMAP5430_REPEAT_MODE_SHIFT			31
+#define OMAP5430_REPEAT_MODE_MASK			(1 << 31)
+#define OMAP5430_COUNTER_SHIFT				0
+#define OMAP5430_COUNTER_MASK				(0xffffff << 0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP5430_T_HOT_SHIFT				16
+#define OMAP5430_T_HOT_MASK				(0x3ff << 16)
+#define OMAP5430_T_COLD_SHIFT				0
+#define OMAP5430_T_COLD_MASK				(0x3ff << 0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP5430_TSHUT_HOT_SHIFT			16
+#define OMAP5430_TSHUT_HOT_MASK				(0x3ff << 16)
+#define OMAP5430_TSHUT_COLD_SHIFT			0
+#define OMAP5430_TSHUT_COLD_MASK			(0x3ff << 0)
+
+/* BANDGAP_STATUS */
+#define OMAP5430_BGAP_ALERT_SHIFT			31
+#define OMAP5430_BGAP_ALERT_MASK			(1 << 31)
+#define OMAP5430_HOT_CORE_FLAG_SHIFT			5
+#define OMAP5430_HOT_CORE_FLAG_MASK			(1 << 5)
+#define OMAP5430_COLD_CORE_FLAG_SHIFT			4
+#define OMAP5430_COLD_CORE_FLAG_MASK			(1 << 4)
+#define OMAP5430_HOT_MM_FLAG_SHIFT			3
+#define OMAP5430_HOT_MM_FLAG_MASK			(1 << 3)
+#define OMAP5430_COLD_MM_FLAG_SHIFT			2
+#define OMAP5430_COLD_MM_FLAG_MASK			(1 << 2)
+#define OMAP5430_HOT_MPU_FLAG_SHIFT			1
+#define OMAP5430_HOT_MPU_FLAG_MASK			(1 << 1)
+#define OMAP5430_COLD_MPU_FLAG_SHIFT			0
+#define OMAP5430_COLD_MPU_FLAG_MASK			(1 << 0)
+
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
 #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
Signature · 1 line
1.7.7.1.488.ge8e1c
#47 lore raw

RFC PATCH 8/11 ARM: OMAP4+: Adding the temperature sensor register set bit fields

Quoted 7 lines · Eduardo Valentin

OMAP4460 specific temperature sensor register bit fields are added. Existing OMAP4 entries are renamed to OMAP4430.

---
  arch/arm/mach-omap2/include/mach/control.h |  116 ++++++++++++++++++++++++++++

Now that we do have a dedicated driver for the bandgap, I guess it will be better to put these defines inside the driver directly.

Benoit

Quoted 129 lines
  1 files changed, 116 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/include/mach/control.h +116 -0
index cf42764..171b504 100644
@@ -230,6 +230,122 @@
  /* OMAP44xx control McBSP padconf */
  #define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP	0x061c
 
+/* TEMP_SENSOR OMAP4430 */
+#define OMAP4430_BGAP_TEMPSOFF_SHIFT			12
+#define OMAP4430_BGAP_TEMPSOFF_MASK			(1<<  12)
+#define OMAP4430_BGAP_TSHUT_SHIFT				11
+#define OMAP4430_BGAP_TSHUT_MASK				(1<<  11)
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1<<  10)
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT		9
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK			(1<<  9)
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1<<  8)
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff<<  0)
+
+/* TEMP_SENSOR OMAP4460 */
+#define OMAP4460_BGAP_TEMPSOFF_SHIFT			13
+#define OMAP4460_BGAP_TEMPSOFF_MASK			(1<<  13)
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT		11
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK		(1<<  11)
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK		(1<<  10)
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff<<  0)
+
+/* BANDGAP_CTRL */
+#define OMAP4460_SINGLE_MODE_SHIFT			31
+#define OMAP4460_SINGLE_MODE_MASK			(1<<  31)
+#define OMAP4460_MASK_HOT_SHIFT				1
+#define OMAP4460_MASK_HOT_MASK				(1<<  1)
+#define OMAP4460_MASK_COLD_SHIFT			0
+#define OMAP4460_MASK_COLD_MASK				(1<<  0)
+
+/* BANDGAP_COUNTER */
+#define OMAP4460_COUNTER_SHIFT				0
+#define OMAP4460_COUNTER_MASK				(0xffffff<<  0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP4460_T_HOT_SHIFT				16
+#define OMAP4460_T_HOT_MASK				(0x3ff<<  16)
+#define OMAP4460_T_COLD_SHIFT				0
+#define OMAP4460_T_COLD_MASK				(0x3ff<<  0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP4460_TSHUT_HOT_SHIFT			16
+#define OMAP4460_TSHUT_HOT_MASK				(0x3ff<<  16)
+#define OMAP4460_TSHUT_COLD_SHIFT			0
+#define OMAP4460_TSHUT_COLD_MASK			(0x3ff<<  0)
+
+/* BANDGAP_STATUS */
+#define OMAP4460_CLEAN_STOP_SHIFT			3
+#define OMAP4460_CLEAN_STOP_MASK			(1<<  3)
+#define OMAP4460_BGAP_ALERT_SHIFT			2
+#define OMAP4460_BGAP_ALERT_MASK			(1<<  2)
+#define OMAP4460_HOT_FLAG_SHIFT				1
+#define OMAP4460_HOT_FLAG_MASK				(1<<  1)
+#define OMAP4460_COLD_FLAG_SHIFT			0
+#define OMAP4460_COLD_FLAG_MASK				(1<<  0)
+
+/* TEMP_SENSOR OMAP5430 */
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT		12
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK		(1<<  12)
+#define OMAP5430_BGAP_TEMPSOFF_SHIFT			11
+#define OMAP5430_BGAP_TEMPSOFF_MASK			(1<<  11)
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1<<  10)
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff<<  0)
+
+/* BANDGAP_CTRL */
+#define OMAP5430_MASK_HOT_CORE_SHIFT			5
+#define OMAP5430_MASK_HOT_CORE_MASK			(1<<  5)
+#define OMAP5430_MASK_COLD_CORE_SHIFT			4
+#define OMAP5430_MASK_COLD_CORE_MASK			(1<<  4)
+#define OMAP5430_MASK_HOT_MM_SHIFT			3
+#define OMAP5430_MASK_HOT_MM_MASK			(1<<  3)
+#define OMAP5430_MASK_COLD_MM_SHIFT			2
+#define OMAP5430_MASK_COLD_MM_MASK			(1<<  2)
+#define OMAP5430_MASK_HOT_MPU_SHIFT			1
+#define OMAP5430_MASK_HOT_MPU_MASK			(1<<  1)
+#define OMAP5430_MASK_COLD_MPU_SHIFT			0
+#define OMAP5430_MASK_COLD_MPU_MASK			(1<<  0)
+
+/* BANDGAP_COUNTER */
+#define OMAP5430_REPEAT_MODE_SHIFT			31
+#define OMAP5430_REPEAT_MODE_MASK			(1<<  31)
+#define OMAP5430_COUNTER_SHIFT				0
+#define OMAP5430_COUNTER_MASK				(0xffffff<<  0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP5430_T_HOT_SHIFT				16
+#define OMAP5430_T_HOT_MASK				(0x3ff<<  16)
+#define OMAP5430_T_COLD_SHIFT				0
+#define OMAP5430_T_COLD_MASK				(0x3ff<<  0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP5430_TSHUT_HOT_SHIFT			16
+#define OMAP5430_TSHUT_HOT_MASK				(0x3ff<<  16)
+#define OMAP5430_TSHUT_COLD_SHIFT			0
+#define OMAP5430_TSHUT_COLD_MASK			(0x3ff<<  0)
+
+/* BANDGAP_STATUS */
+#define OMAP5430_BGAP_ALERT_SHIFT			31
+#define OMAP5430_BGAP_ALERT_MASK			(1<<  31)
+#define OMAP5430_HOT_CORE_FLAG_SHIFT			5
+#define OMAP5430_HOT_CORE_FLAG_MASK			(1<<  5)
+#define OMAP5430_COLD_CORE_FLAG_SHIFT			4
+#define OMAP5430_COLD_CORE_FLAG_MASK			(1<<  4)
+#define OMAP5430_HOT_MM_FLAG_SHIFT			3
+#define OMAP5430_HOT_MM_FLAG_MASK			(1<<  3)
+#define OMAP5430_COLD_MM_FLAG_SHIFT			2
+#define OMAP5430_COLD_MM_FLAG_MASK			(1<<  2)
+#define OMAP5430_HOT_MPU_FLAG_SHIFT			1
+#define OMAP5430_HOT_MPU_FLAG_MASK			(1<<  1)
+#define OMAP5430_COLD_MPU_FLAG_SHIFT			0
+#define OMAP5430_COLD_MPU_FLAG_MASK			(1<<  0)
+
  /* AM35XX only CONTROL_GENERAL register offsets */
  #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
  #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
#48 lore raw

RFC PATCH 8/11 ARM: OMAP4+: Adding the temperature sensor register set bit fields

Quoted 11 lines · Cousson Benoit
Quoted 7 lines · Eduardo Valentin

OMAP4460 specific temperature sensor register bit fields are added. Existing OMAP4 entries are renamed to OMAP4430.

---
 arch/arm/mach-omap2/include/mach/control.h |  116 ++++++++++++++++++++++++++++

Now that we do have a dedicated driver for the bandgap, I guess it will be better to put these defines inside the driver directly.

Agreed

Quoted 133 lines

Benoit

Quoted 129 lines
 1 files changed, 116 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/include/mach/control.h +116 -0
index cf42764..171b504 100644
@@ -230,6 +230,122 @@
 /* OMAP44xx control McBSP padconf */
 #define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP	0x061c
 
+/* TEMP_SENSOR OMAP4430 */
+#define OMAP4430_BGAP_TEMPSOFF_SHIFT			12
+#define OMAP4430_BGAP_TEMPSOFF_MASK			(1<<  12)
+#define OMAP4430_BGAP_TSHUT_SHIFT				11
+#define OMAP4430_BGAP_TSHUT_MASK				(1<<  11)
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1<<  10)
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT		9
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK			(1<<  9)
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1<<  8)
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff<<  0)
+
+/* TEMP_SENSOR OMAP4460 */
+#define OMAP4460_BGAP_TEMPSOFF_SHIFT			13
+#define OMAP4460_BGAP_TEMPSOFF_MASK			(1<<  13)
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT		11
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK		(1<<  11)
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK		(1<<  10)
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff<<  0)
+
+/* BANDGAP_CTRL */
+#define OMAP4460_SINGLE_MODE_SHIFT			31
+#define OMAP4460_SINGLE_MODE_MASK			(1<<  31)
+#define OMAP4460_MASK_HOT_SHIFT				1
+#define OMAP4460_MASK_HOT_MASK				(1<<  1)
+#define OMAP4460_MASK_COLD_SHIFT			0
+#define OMAP4460_MASK_COLD_MASK				(1<<  0)
+
+/* BANDGAP_COUNTER */
+#define OMAP4460_COUNTER_SHIFT				0
+#define OMAP4460_COUNTER_MASK				(0xffffff<<  0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP4460_T_HOT_SHIFT				16
+#define OMAP4460_T_HOT_MASK				(0x3ff<<  16)
+#define OMAP4460_T_COLD_SHIFT				0
+#define OMAP4460_T_COLD_MASK				(0x3ff<<  0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP4460_TSHUT_HOT_SHIFT			16
+#define OMAP4460_TSHUT_HOT_MASK				(0x3ff<<  16)
+#define OMAP4460_TSHUT_COLD_SHIFT			0
+#define OMAP4460_TSHUT_COLD_MASK			(0x3ff<<  0)
+
+/* BANDGAP_STATUS */
+#define OMAP4460_CLEAN_STOP_SHIFT			3
+#define OMAP4460_CLEAN_STOP_MASK			(1<<  3)
+#define OMAP4460_BGAP_ALERT_SHIFT			2
+#define OMAP4460_BGAP_ALERT_MASK			(1<<  2)
+#define OMAP4460_HOT_FLAG_SHIFT				1
+#define OMAP4460_HOT_FLAG_MASK				(1<<  1)
+#define OMAP4460_COLD_FLAG_SHIFT			0
+#define OMAP4460_COLD_FLAG_MASK				(1<<  0)
+
+/* TEMP_SENSOR OMAP5430 */
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT		12
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK		(1<<  12)
+#define OMAP5430_BGAP_TEMPSOFF_SHIFT			11
+#define OMAP5430_BGAP_TEMPSOFF_MASK			(1<<  11)
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1<<  10)
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff<<  0)
+
+/* BANDGAP_CTRL */
+#define OMAP5430_MASK_HOT_CORE_SHIFT			5
+#define OMAP5430_MASK_HOT_CORE_MASK			(1<<  5)
+#define OMAP5430_MASK_COLD_CORE_SHIFT			4
+#define OMAP5430_MASK_COLD_CORE_MASK			(1<<  4)
+#define OMAP5430_MASK_HOT_MM_SHIFT			3
+#define OMAP5430_MASK_HOT_MM_MASK			(1<<  3)
+#define OMAP5430_MASK_COLD_MM_SHIFT			2
+#define OMAP5430_MASK_COLD_MM_MASK			(1<<  2)
+#define OMAP5430_MASK_HOT_MPU_SHIFT			1
+#define OMAP5430_MASK_HOT_MPU_MASK			(1<<  1)
+#define OMAP5430_MASK_COLD_MPU_SHIFT			0
+#define OMAP5430_MASK_COLD_MPU_MASK			(1<<  0)
+
+/* BANDGAP_COUNTER */
+#define OMAP5430_REPEAT_MODE_SHIFT			31
+#define OMAP5430_REPEAT_MODE_MASK			(1<<  31)
+#define OMAP5430_COUNTER_SHIFT				0
+#define OMAP5430_COUNTER_MASK				(0xffffff<<  0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP5430_T_HOT_SHIFT				16
+#define OMAP5430_T_HOT_MASK				(0x3ff<<  16)
+#define OMAP5430_T_COLD_SHIFT				0
+#define OMAP5430_T_COLD_MASK				(0x3ff<<  0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP5430_TSHUT_HOT_SHIFT			16
+#define OMAP5430_TSHUT_HOT_MASK				(0x3ff<<  16)
+#define OMAP5430_TSHUT_COLD_SHIFT			0
+#define OMAP5430_TSHUT_COLD_MASK			(0x3ff<<  0)
+
+/* BANDGAP_STATUS */
+#define OMAP5430_BGAP_ALERT_SHIFT			31
+#define OMAP5430_BGAP_ALERT_MASK			(1<<  31)
+#define OMAP5430_HOT_CORE_FLAG_SHIFT			5
+#define OMAP5430_HOT_CORE_FLAG_MASK			(1<<  5)
+#define OMAP5430_COLD_CORE_FLAG_SHIFT			4
+#define OMAP5430_COLD_CORE_FLAG_MASK			(1<<  4)
+#define OMAP5430_HOT_MM_FLAG_SHIFT			3
+#define OMAP5430_HOT_MM_FLAG_MASK			(1<<  3)
+#define OMAP5430_COLD_MM_FLAG_SHIFT			2
+#define OMAP5430_COLD_MM_FLAG_MASK			(1<<  2)
+#define OMAP5430_HOT_MPU_FLAG_SHIFT			1
+#define OMAP5430_HOT_MPU_FLAG_MASK			(1<<  1)
+#define OMAP5430_COLD_MPU_FLAG_SHIFT			0
+#define OMAP5430_COLD_MPU_FLAG_MASK			(1<<  0)
+
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
 #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
#49 lore raw

RFC PATCH 8/11 ARM: OMAP4+: Adding the temperature sensor register set bit fields

In reply to Eduardo Valentin
Quoted 6 lines · Eduardo Valentin

OMAP4460 specific temperature sensor register bit fields are added. Existing OMAP4 entries are renamed to OMAP4430.

---

Once you split the header, as mentioned in earlier comment, you can move those defines in driver file directly.

Regards
Santsoh

#50 lore raw

RFC PATCH 8/11 ARM: OMAP4+: Adding the temperature sensor register set bit fields

Quoted 10 lines · Santosh
Quoted 6 lines · Eduardo Valentin

OMAP4460 specific temperature sensor register bit fields are added. Existing OMAP4 entries are renamed to OMAP4430.

---

Once you split the header, as mentioned in earlier comment, you can move those defines in driver file directly.

Agreed, this patch is gonna be dropped and the definition will be part of patch introducing the bandgap driver

Quoted 3 lines

Regards
Santsoh

#51 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

In reply to Eduardo Valentin

In the System Control Module, OMAP supplies a voltage reference and a temperature sensor feature that are gathered in the band gap voltage and temperature sensor (VBGAPTS) module. The band gap provides current and voltage reference for its internal circuits and other analog IP blocks. The analog-to-digital converter (ADC) produces an output value that is proportional to the silicon temperature.

This patch provides a platform driver which expose this feature. It is moduled as a MFD child of the System Control Module core MFD driver.

This driver provides only APIs to access the device properties, like temperature, thresholds and update rate.

---
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 drivers/thermal/Kconfig                            |   13 +
 drivers/thermal/Makefile                           |    4 +-
 drivers/thermal/omap-bandgap.c                     | 1601 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   63 +
 5 files changed, 1707 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h
Documentation/devicetree/bindings/thermal/omap_bandgap.txt new file +27 -0
new file mode 100644
index 0000000..430bcf8
@@ -0,0 +1,27 @@
+* Texas Instrument OMAP SCM bandgap bindings
+
+In the System Control Module, OMAP supplies a voltage reference
+and a temperature sensor feature that are gathered in the band
+gap voltage and temperature sensor (VBGAPTS) module. The band
+gap provides current and voltage reference for its internal
+circuits and other analog IP blocks. The analog-to-digital
+converter (ADC) produces an output value that is proportional
+to the silicon temperature.
+
+Required properties:
+- compatible : Should be:
+  - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap
+  - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap
+- interrupts : this entry should indicate which interrupt line
+the talert signal is routed to;
+Specific:
+- ti,tshut-gpio : this entry should be used to inform which GPIO
+line the tshut signal is routed to;
+
+Example:
+
+bandgap {
+	compatible = "ti,omap4460-control-bandgap";
+	interrupts = <0 126 4>; /* talert */
+	ti,tshut-gpio = <86>;
+};
drivers/thermal/Kconfig +13 -0
index 514a691..ffdd240 100644
@@ -26,3 +26,16 @@ config SPEAR_THERMAL
 	help
 	  Enable this to plug the SPEAr thermal sensor driver into the Linux
 	  thermal framework
+
+config OMAP_BANDGAP
+	tristate "Texas Instruments OMAP4+ temperature sensor driver"
+	depends on THERMAL
+	depends on MFD_OMAP_CONTROL
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  OMAP4460+ on die bandgap temperature sensor support. The register
+	  set is part of system control module.
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
+
drivers/thermal/Makefile +3 -1
index a9fff0b..5ff1af1 100644
@@ -3,4 +3,6 @@
 #
 
 obj-$(CONFIG_THERMAL)		+= thermal_sys.o
-obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
\ No newline at end of file
+obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
+obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal.o
+omap-thermal-y			:= omap-bandgap.o
drivers/thermal/omap-bandgap.c new file +1601 -0

1,601 lines not on this page · raw message

drivers/thermal/omap-bandgap.h new file +63 -0

63 lines not on this page · raw message

Signature · 1 line
1.7.7.1.488.ge8e1c
#52 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

Quoted 366 lines · Eduardo Valentin

In the System Control Module, OMAP supplies a voltage reference and a temperature sensor feature that are gathered in the band gap voltage and temperature sensor (VBGAPTS) module. The band gap provides current and voltage reference for its internal circuits and other analog IP blocks. The analog-to-digital converter (ADC) produces an output value that is proportional to the silicon temperature.

This patch provides a platform driver which expose this feature. It is moduled as a MFD child of the System Control Module core MFD driver.

This driver provides only APIs to access the device properties, like temperature, thresholds and update rate.

---
  .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
  drivers/thermal/Kconfig                            |   13 +
  drivers/thermal/Makefile                           |    4 +-
  drivers/thermal/omap-bandgap.c                     | 1601 ++++++++++++++++++++
  drivers/thermal/omap-bandgap.h                     |   63 +
  5 files changed, 1707 insertions(+), 1 deletions(-)

create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt create mode 100644 drivers/thermal/omap-bandgap.c
create mode 100644 drivers/thermal/omap-bandgap.h

Documentation/devicetree/bindings/thermal/omap_bandgap.txt new file +27 -0
new file mode 100644
index 0000000..430bcf8
@@ -0,0 +1,27 @@
+* Texas Instrument OMAP SCM bandgap bindings
+
+In the System Control Module, OMAP supplies a voltage reference
+and a temperature sensor feature that are gathered in the band
+gap voltage and temperature sensor (VBGAPTS) module. The band
+gap provides current and voltage reference for its internal
+circuits and other analog IP blocks. The analog-to-digital
+converter (ADC) produces an output value that is proportional
+to the silicon temperature.
+
+Required properties:
+- compatible : Should be:
+  - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap
+  - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap
+- interrupts : this entry should indicate which interrupt line
+the talert signal is routed to;
+Specific:
+- ti,tshut-gpio : this entry should be used to inform which GPIO
+line the tshut signal is routed to;
+
+Example:
+
+bandgap {
+	compatible = "ti,omap4460-control-bandgap";
+	interrupts =<0 126 4>; /* talert */
+	ti,tshut-gpio =<86>;
+};
drivers/thermal/Kconfig +13 -0
index 514a691..ffdd240 100644
@@ -26,3 +26,16 @@ config SPEAR_THERMAL
  	help
  	  Enable this to plug the SPEAr thermal sensor driver into the Linux
  	  thermal framework
+
+config OMAP_BANDGAP
+	tristate "Texas Instruments OMAP4+ temperature sensor driver"
+	depends on THERMAL
+	depends on MFD_OMAP_CONTROL
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  OMAP4460+ on die bandgap temperature sensor support. The register
+	  set is part of system control module.
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
+
drivers/thermal/Makefile +3 -1
index a9fff0b..5ff1af1 100644
@@ -3,4 +3,6 @@
  #
 
  obj-$(CONFIG_THERMAL)		+= thermal_sys.o
-obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
\ No newline at end of file
+obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
+obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal.o
+omap-thermal-y			:= omap-bandgap.o
drivers/thermal/omap-bandgap.c new file +265 -0
new file mode 100644
index 0000000..3d5a12b
@@ -0,0 +1,1601 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy<[email protected]>
+ * Author: Moiz Sonasath<[email protected]>
+ * Couple of fixes, DT and MFD adaptation:
+ *   Eduardo Valentin<[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include<linux/module.h>
+#include<linux/export.h>
+#include<linux/init.h>
+#include<linux/kernel.h>
+#include<linux/interrupt.h>
+#include<linux/clk.h>
+#include<linux/gpio.h>
+#include<linux/platform_device.h>
+#include<linux/err.h>
+#include<linux/types.h>
+#include<linux/mutex.h>
+#include<linux/reboot.h>
+#include<linux/of_platform.h>
+#include<linux/of_irq.h>
+#include<linux/mfd/omap_control.h>
+
+#include<mach/control.h>
+
+#include "omap-bandgap.h"
+
+/* Offsets from the base of temperature sensor registers */
+
+#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x32C
+#define OMAP4460_BGAP_CTRL_OFFSET		0x378
+#define OMAP4460_BGAP_COUNTER_OFFSET		0x37C
+#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x380
+#define OMAP4460_BGAP_TSHUT_OFFSET		0x384
+#define OMAP4460_BGAP_STATUS_OFFSET		0x388
+#define OMAP4460_FUSE_OPP_BGAP			0x260
+
+#define OMAP5430_TEMP_SENSOR_MPU_OFFSET		0x32C
+#define OMAP5430_BGAP_CTRL_OFFSET		0x380
+#define OMAP5430_BGAP_COUNTER_MPU_OFFSET	0x39C
+#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET	0x384
+#define OMAP5430_BGAP_TSHUT_MPU_OFFSET		0x390
+#define OMAP5430_BGAP_STATUS_OFFSET		0x3A8
+#define OMAP5430_FUSE_OPP_BGAP_MPU		0x1E4
+
+#define OMAP5430_TEMP_SENSOR_GPU_OFFSET		0x330
+#define OMAP5430_BGAP_COUNTER_GPU_OFFSET	0x3A0
+#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET	0x388
+#define OMAP5430_BGAP_TSHUT_GPU_OFFSET		0x394
+#define OMAP5430_FUSE_OPP_BGAP_GPU		0x1E0
+
+#define OMAP5430_TEMP_SENSOR_CORE_OFFSET	0x334
+#define OMAP5430_BGAP_COUNTER_CORE_OFFSET	0x3A4
+#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET	0x38C
+#define OMAP5430_BGAP_TSHUT_CORE_OFFSET		0x398
+#define OMAP5430_FUSE_OPP_BGAP_CORE		0x1E8
+
+#define OMAP4460_TSHUT_HOT		900	/* 122 deg C */
+#define OMAP4460_TSHUT_COLD		895	/* 100 deg C */
+#define OMAP4460_T_HOT			800	/* 73 deg C */
+#define OMAP4460_T_COLD			795	/* 71 deg C */
+#define OMAP4460_MAX_FREQ		1500000
+#define OMAP4460_MIN_FREQ		1000000
+#define OMAP4460_MIN_TEMP		-40000
+#define OMAP4460_MAX_TEMP		123000
+#define OMAP4460_HYST_VAL		5000
+#define OMAP4460_ADC_START_VALUE	530
+#define OMAP4460_ADC_END_VALUE		932
+
+#define OMAP5430_MPU_TSHUT_HOT		915
+#define OMAP5430_MPU_TSHUT_COLD		900
+#define OMAP5430_MPU_T_HOT		800
+#define OMAP5430_MPU_T_COLD		795
+#define OMAP5430_MPU_MAX_FREQ		1500000
+#define OMAP5430_MPU_MIN_FREQ		1000000
+#define OMAP5430_MPU_MIN_TEMP		-40000
+#define OMAP5430_MPU_MAX_TEMP		125000
+#define OMAP5430_MPU_HYST_VAL		5000
+#define OMAP5430_ADC_START_VALUE	532
+#define OMAP5430_ADC_END_VALUE		934
+
+#define OMAP5430_GPU_TSHUT_HOT		915
+#define OMAP5430_GPU_TSHUT_COLD		900
+#define OMAP5430_GPU_T_HOT		800
+#define OMAP5430_GPU_T_COLD		795
+#define OMAP5430_GPU_MAX_FREQ		1500000
+#define OMAP5430_GPU_MIN_FREQ		1000000
+#define OMAP5430_GPU_MIN_TEMP		-40000
+#define OMAP5430_GPU_MAX_TEMP		125000
+#define OMAP5430_GPU_HYST_VAL		5000
+
+#define OMAP5430_CORE_TSHUT_HOT		915
+#define OMAP5430_CORE_TSHUT_COLD	900
+#define OMAP5430_CORE_T_HOT		800
+#define OMAP5430_CORE_T_COLD		795
+#define OMAP5430_CORE_MAX_FREQ		1500000
+#define OMAP5430_CORE_MIN_FREQ		1000000
+#define OMAP5430_CORE_MIN_TEMP		-40000
+#define OMAP5430_CORE_MAX_TEMP		125000
+#define OMAP5430_CORE_HYST_VAL		5000
+
+/**
+ * The register offsets and bit fields might change across
+ * OMAP versions hence populating them in this structure.
+ */
+
+struct temp_sensor_registers {
+	u32	temp_sensor_ctrl;
+	u32	bgap_tempsoff_mask;
+	u32	bgap_soc_mask;
+	u32	bgap_eocz_mask;
+	u32	bgap_dtemp_mask;
+
+	u32	bgap_mask_ctrl;
+	u32	mask_hot_mask;
+	u32	mask_cold_mask;
+
+	u32	bgap_mode_ctrl;
+	u32	mode_ctrl_mask;
+
+	u32	bgap_counter;
+	u32	counter_mask;
+
+	u32	bgap_threshold;
+	u32	threshold_thot_mask;
+	u32	threshold_tcold_mask;
+
+	u32	tshut_threshold;
+	u32	tshut_hot_mask;
+	u32	tshut_cold_mask;
+
+	u32	bgap_status;
+	u32	status_clean_stop_mask;
+	u32	status_bgap_alert_mask;
+	u32	status_hot_mask;
+	u32	status_cold_mask;
+
+	u32	bgap_efuse;
+};
+
+/**
+ * The thresholds and limits for temperature sensors.
+ */
+struct temp_sensor_data {
+	u32	tshut_hot;
+	u32	tshut_cold;
+	u32	t_hot;
+	u32	t_cold;
+	u32	min_freq;
+	u32	max_freq;
+	int	max_temp;
+	int	min_temp;
+	int	hyst_val;
+	u32	adc_start_val;
+	u32	adc_end_val;
+	u32	update_int1;
+	u32	update_int2;
+};
+
+/**
+ * struct temp_sensor_regval - temperature sensor register values
+ * @bg_mode_ctrl: temp sensor control register value
+ * @bg_ctrl: bandgap ctrl register value
+ * @bg_counter: bandgap counter value
+ * @bg_threshold: bandgap threshold register value
+ * @tshut_threshold: bandgap tshut register value
+ */
+struct temp_sensor_regval {
+	u32			bg_mode_ctrl;
+	u32			bg_ctrl;
+	u32			bg_counter;
+	u32			bg_threshold;
+	u32			tshut_threshold;
+};
+
+/**
+ * struct omap_temp_sensor - bandgap temperature sensor platform data
+ * @ts_data: pointer to struct with thresholds, limits of temperature sensor
+ * @registers: pointer to the list of register offsets and bitfields
+ * @regval: temperature sensor register values
+ * @domain: the name of the domain where the sensor is located
+ */
+struct omap_temp_sensor {
+	struct temp_sensor_data		*ts_data;
+	struct temp_sensor_registers	*registers;
+	struct temp_sensor_regval	*regval;
+	char				*domain;
+};
+
+/**
+ * struct omap_bandgap_data - bandgap platform data structure
+ * @has_talert: indicates if the chip has talert output line
+ * @has_tshut: indicates if the chip has tshut output line
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @fclock_name: clock name of the functional clock
+ * @div_ck_nme: clock name of the clock divisor
+ * @sensor_count: count of temperature sensor device in scm
+ * @sensors: array of sensors present in this bandgap instance
+ * @expose_sensor: callback to export sensor to thermal API
+ */
+struct omap_bandgap_data {
+	bool				has_talert;
+	bool				has_tshut;
+	const int			*conv_table;
+	char				*fclock_name;
+	char				*div_ck_name;
+	int				sensor_count;
+	int (*report_temperature)(struct omap_bandgap *bg_ptr, int id);
+	int (*expose_sensor)(struct omap_bandgap *bg_ptr, int id, char *domain);
+
+	/* this needs to be at the end */
+	struct omap_temp_sensor		sensors[];
+};
+
+/* TODO: provide data structures for 4430 */
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap4460_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
+	.bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP4460_MASK_HOT_MASK,
+	.mask_cold_mask = OMAP4460_MASK_COLD_MASK,
+
+	.bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+	.mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
+
+	.bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
+	.counter_mask = OMAP4460_COUNTER_MASK,
+
+	.bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
+	.threshold_thot_mask = OMAP4460_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP4460_T_COLD_MASK,
+
+	.tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
+	.tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP4460_BGAP_STATUS_OFFSET,

drivers/thermal/omap-bandgap.c line 275

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	.status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
+	.status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP4460_HOT_FLAG_MASK,
+	.status_cold_mask = OMAP4460_COLD_FLAG_MASK,
+
+	.bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU

Bad copy paste.

Quoted 31 lines
drivers/thermal/omap-bandgap.c new file +31 -0
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap5430_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
+
+	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
+	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,

drivers/thermal/omap-bandgap.c line 316

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	.status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */

Ditto

Quoted 29 lines
drivers/thermal/omap-bandgap.c new file +29 -0
+static struct temp_sensor_registers
+omap5430_gpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_MM_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_MM_MASK,
+
+	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
+	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,

drivers/thermal/omap-bandgap.c line 355

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	.status_hot_mask = OMAP5430_HOT_MM_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_MM_FLAG_MASK,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */

Ditto

Quoted 215 lines
drivers/thermal/omap-bandgap.c new file +215 -0
+static struct temp_sensor_registers
+omap5430_core_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
+
+	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
+	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
+};
+
+/* Thresholds and limits for OMAP4460 MPU temperature sensor */
+static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
+	.tshut_hot = OMAP4460_TSHUT_HOT,
+	.tshut_cold = OMAP4460_TSHUT_COLD,
+	.t_hot = OMAP4460_T_HOT,
+	.t_cold = OMAP4460_T_COLD,
+	.min_freq = OMAP4460_MIN_FREQ,
+	.max_freq = OMAP4460_MAX_FREQ,
+	.max_temp = OMAP4460_MAX_TEMP,
+	.min_temp = OMAP4460_MIN_TEMP,
+	.hyst_val = OMAP4460_HYST_VAL,
+	.adc_start_val = OMAP4460_ADC_START_VALUE,
+	.adc_end_val = OMAP4460_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 MPU temperature sensor */
+static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
+	.tshut_hot = OMAP5430_MPU_TSHUT_HOT,
+	.tshut_cold = OMAP5430_MPU_TSHUT_COLD,
+	.t_hot = OMAP5430_MPU_T_HOT,
+	.t_cold = OMAP5430_MPU_T_COLD,
+	.min_freq = OMAP5430_MPU_MIN_FREQ,
+	.max_freq = OMAP5430_MPU_MAX_FREQ,
+	.max_temp = OMAP5430_MPU_MAX_TEMP,
+	.min_temp = OMAP5430_MPU_MIN_TEMP,
+	.hyst_val = OMAP5430_MPU_HYST_VAL,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 GPU temperature sensor */
+static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
+	.tshut_hot = OMAP5430_GPU_TSHUT_HOT,
+	.tshut_cold = OMAP5430_GPU_TSHUT_COLD,
+	.t_hot = OMAP5430_GPU_T_HOT,
+	.t_cold = OMAP5430_GPU_T_COLD,
+	.min_freq = OMAP5430_GPU_MIN_FREQ,
+	.max_freq = OMAP5430_GPU_MAX_FREQ,
+	.max_temp = OMAP5430_GPU_MAX_TEMP,
+	.min_temp = OMAP5430_GPU_MIN_TEMP,
+	.hyst_val = OMAP5430_GPU_HYST_VAL,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 CORE temperature sensor */
+static struct temp_sensor_data omap5430_core_temp_sensor_data = {
+	.tshut_hot = OMAP5430_CORE_TSHUT_HOT,
+	.tshut_cold = OMAP5430_CORE_TSHUT_COLD,
+	.t_hot = OMAP5430_CORE_T_HOT,
+	.t_cold = OMAP5430_CORE_T_COLD,
+	.min_freq = OMAP5430_CORE_MIN_FREQ,
+	.max_freq = OMAP5430_CORE_MAX_FREQ,
+	.max_temp = OMAP5430_CORE_MAX_TEMP,
+	.min_temp = OMAP5430_CORE_MIN_TEMP,
+	.hyst_val = OMAP5430_CORE_HYST_VAL,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static const int
+omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
+	-37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
+	-34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
+	-30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
+	-27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
+	-24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+	-20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
+	-17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
+	-13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
+	-10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
+	-6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
+	-2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
+	2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
+	6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
+	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
+	15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
+	19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
+	23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
+	26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
+	30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+	34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
+	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
+	42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
+	45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
+	49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
+	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
+	57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
+	60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
+	64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
+	68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
+	72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+	75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
+	79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
+	83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
+	86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
+	90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
+	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
+	98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
+	101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
+	104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
+	108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
+	111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
+	114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
+	117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+	124600, 124900, 125000, 125000, 125000, 125000
+};
+
+static const int
+omap5430_adc_to_temp[OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600,
+	-38200, -37800, -37300, -36800,
+	-36400, -36000, -35600, -35200, -34800, -34300, -33800, -33400, -33000,
+	-32600,
+	-32200, -31800, -31300, -30800, -30400, -30000, -29600, -29200, -28700,
+	-28200, -27800, -27400, -27000, -26600, -26200, -25700, -25200, -24800,
+	-24400, -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+	-20600, -20200, -19700, -19200, -9300, -18400, -18000, -17600, -17200,
+	-16700, -16200, -15800, -15400, -15000, -14600, -14200, -13700, -13200,
+	-12800, -12400, -12000, -11600, -11200, -10700, -10200, -9800, -9400,
+	-9000,
+	-8600, -8200, -7700, -7200, -6800, -6400, -6000, -5600, -5200, -4800,
+	-4300,
+	-3800, -3400, -3000, -2600, -2200, -1800, -1300, -800, -400, 0, 400,
+	800,
+	1200, 1600, 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000,
+	6400, 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10800,
+	11100,
+	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, 15300,
+	15800,
+	16200, 16600, 17000, 17400, 17800, 18200, 18700, 19200, 19600, 20000,
+	20400,
+	20800, 21200, 21600, 22100, 22600, 23000, 23400, 23800, 24200, 24600,
+	25000,
+	25400, 25900, 26400, 26800, 27200, 27600, 28000, 28400, 28800, 29300,
+	29800,
+	30200, 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+	34400,
+	34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, 38200, 38600,
+	39000,
+	39400, 39800, 40200, 40600, 41100, 41600, 42000, 42400, 42800, 43200,
+	43600,
+	44000, 44400, 44800, 45300, 45800, 46200, 46600, 47000, 47400, 47800,
+	48200,
+	48600, 49000, 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400,
+	52800,
+	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, 57000,
+	57400,
+	57800, 58200, 58700, 59200, 59600, 60000, 60400, 60800, 61200, 61600,
+	62000,
+	62400, 62800, 63300, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
+	66600,
+	67000, 67400, 67800, 68200, 68700, 69200, 69600, 70000, 70400, 70800,
+	71200,
+	71600, 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+	75800,
+	76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, 79400, 79800,
+	80300,
+	80800, 81200, 81600, 82000, 82400, 82800, 83200, 83600, 84000, 84400,
+	84800,
+	85200, 85600, 86000, 86400, 86800, 87300, 87800, 88200, 88600, 89000,
+	89400,
+	89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400,
+	93800,
+	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, 98000,
+	98400,

drivers/thermal/omap-bandgap.c line 580

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	98800, 99200, 99600, 100000, 100400, 100800, 101200, 101600, 102000,
+	102400,
+	102800, 103200, 103600, 104000, 104400, 104800, 105200, 105600, 106100,
+	106600, 107000, 107400, 107800, 108200, 108600, 109000, 109400, 109800,
+	110200, 110600, 111000, 111400, 111800, 112200, 112600, 113000, 113400,
+	113800, 114200, 114600, 115000, 115400, 115800, 116200, 116600, 117000,
+	117400, 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+	124600, 124900, 125000, 125000, 125000, 125000,
+};

It might be good to store the per SoC data in dedicated files or at least put some #ifdef around to avoid wasting memory for a non-multi OMAP boot.

Quoted 603 lines
drivers/thermal/omap-bandgap.c new file +603 -0
+
+static irqreturn_t talert_irq_handler(int irq, void *data)
+{
+	struct omap_bandgap *bg_ptr = data;
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 t_hot = 0, t_cold = 0, temp, ctrl;
+	int i, r;
+
+	bg_ptr = data;
+	/* Read the status of t_hot */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		r = omap_control_readl(cdev, tsr->bgap_status,&t_hot);
+		t_hot&= tsr->status_hot_mask;
+
+		/* Read the status of t_cold */
+		r |= omap_control_readl(cdev, tsr->bgap_status,&t_cold);
+		t_cold&= tsr->status_cold_mask;
+
+		if (!t_cold&&  !t_hot)
+			continue;
+
+		r |= omap_control_readl(cdev, tsr->bgap_mask_ctrl,&ctrl);
+		/*
+		 * One TALERT interrupt: Two sources
+		 * If the interrupt is due to t_hot then mask t_hot and
+		 * and unmask t_cold else mask t_cold and unmask t_hot
+		 */
+		if (t_hot) {
+			ctrl&= ~tsr->mask_hot_mask;
+			ctrl |= tsr->mask_cold_mask;
+		} else if (t_cold) {
+			ctrl&= ~tsr->mask_cold_mask;
+			ctrl |= tsr->mask_hot_mask;
+		}
+
+		r |= omap_control_writel(cdev, ctrl, tsr->bgap_mask_ctrl);
+
+		if (r) {
+			dev_err(bg_ptr->dev, "failed to ack talert interrupt\n");
+			return IRQ_NONE;
+		}
+
+		/* read temperature */
+		r = omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+		temp&= tsr->bgap_dtemp_mask;
+
+		/* report temperature to whom may concern */
+		if (bg_ptr->pdata->report_temperature)
+			bg_ptr->pdata->report_temperature(bg_ptr, i);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
+{
+	orderly_poweroff(true);
+
+	return IRQ_HANDLED;
+}
+
+static
+int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
+			   int *t)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+
+	/* look up for temperature in the table and return the temperature */
+	if (adc_val<  ts_data->adc_start_val || adc_val>  ts_data->adc_end_val)
+		return -ERANGE;
+
+	*t = bg_ptr->conv_table[adc_val - ts_data->adc_start_val];
+
+	return 0;
+}
+
+static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
+				  int *adc)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[i].ts_data;
+	int high, low, mid;
+
+	low = 0;
+	high = ts_data->adc_end_val - ts_data->adc_start_val;
+	mid = (high + low) / 2;
+
+	if (temp<  bg_ptr->conv_table[high] || temp>  bg_ptr->conv_table[high])
+		return -EINVAL;
+
+	while (low<  high) {
+		if (temp<  bg_ptr->conv_table[mid])
+			high = mid - 1;
+		else
+			low = mid + 1;
+		mid = (low + high) / 2;
+	}
+
+	*adc = ts_data->adc_start_val + low;
+
+	return 0;
+}
+
+static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
+					 u32 t_hot, u32 t_cold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp, reg_val;
+	int err;
+
+	/* Read the current on die temperature */
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= tsr->bgap_dtemp_mask;
+
+	err |= omap_control_readl(cdev, tsr->bgap_mask_ctrl,&reg_val);
+	if (temp<  t_hot)
+		reg_val |= tsr->mask_hot_mask;
+	else
+		reg_val&= ~tsr->mask_hot_mask;
+
+	if (t_cold<  temp)
+		reg_val |= tsr->mask_cold_mask;
+	else
+		reg_val&= ~tsr->mask_cold_mask;
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_mask_ctrl);
+
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to unmask interrupts\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static
+int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
+	     u32 *sum)
+{
+	int temp, ret;
+
+	ret = adc_to_temp_conversion(bg_ptr, i, adc_val,&temp);
+	if (ret<  0)
+		return ret;
+
+	temp += hyst_val;
+
+	return temp_to_adc_conversion(temp, bg_ptr, i, sum);
+}
+
+static
+int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 thresh_val, reg_val;
+	int cold, err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+
+	/* obtain the T cold value */
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+	cold = (thresh_val&  tsr->threshold_tcold_mask)>>
+	    __ffs(tsr->threshold_tcold_mask);
+	if (t_hot<= cold) {
+		/* change the t_cold to t_hot - 5000 millidegrees */
+		err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id,&cold);
+		/* write the new t_cold value */
+		reg_val = thresh_val&  (~tsr->threshold_tcold_mask);
+		reg_val |= cold<<  __ffs(tsr->threshold_tcold_mask);
+		err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+		thresh_val = reg_val;
+	}
+
+	/* write the new t_hot value */
+	reg_val = thresh_val&  ~tsr->threshold_thot_mask;
+	reg_val |= (t_hot<<  __ffs(tsr->threshold_thot_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+		return -EIO;
+	}
+
+	return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
+}
+
+static
+int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
+				       int t_hot, int t_cold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 reg_val, thresh_val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+
+	/* write the new t_cold value */
+	reg_val = thresh_val&  ~tsr->threshold_tcold_mask;
+	reg_val |= (t_cold<<  __ffs(tsr->threshold_tcold_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
+		return -EIO;
+	}
+
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+
+	/* write the new t_hot value */
+	reg_val = thresh_val&  ~tsr->threshold_thot_mask;
+	reg_val |= (t_hot<<  __ffs(tsr->threshold_thot_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+		return -EIO;
+	}
+
+	err = omap_control_readl(cdev, tsr->bgap_mask_ctrl,&reg_val);
+	reg_val |= tsr->mask_hot_mask;
+	reg_val |= tsr->mask_cold_mask;
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_mask_ctrl);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+		return -EIO;
+	}
+
+	return err;
+}
+
+static
+int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
+				int t_cold)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 thresh_val, reg_val;
+	int hot, err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	/* obtain the T cold value */
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+	hot = (thresh_val&  tsr->threshold_thot_mask)>>
+	    __ffs(tsr->threshold_thot_mask);
+
+	if (t_cold>= hot) {
+		/* change the t_hot to t_cold + 5000 millidegrees */
+		err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id,&hot);
+		/* write the new t_hot value */
+		reg_val = thresh_val&  (~tsr->threshold_thot_mask);
+		reg_val |= hot<<  __ffs(tsr->threshold_thot_mask);
+		err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+		thresh_val = reg_val;
+	}
+
+	/* write the new t_cold value */
+	reg_val = thresh_val&  ~tsr->threshold_tcold_mask;
+	reg_val |= (t_cold<<  __ffs(tsr->threshold_tcold_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
+		return -EIO;
+	}
+
+	return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
+}
+
+static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr,
+					   int id, int tshut_hot)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 reg_val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->tshut_threshold,&reg_val);
+	reg_val&= ~tsr->tshut_hot_mask;
+	reg_val |= tshut_hot<<  __ffs(tsr->tshut_hot_mask);
+	err |= omap_control_writel(cdev, reg_val, tsr->tshut_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tshut thot\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
+					    int id, int tshut_cold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 reg_val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->tshut_threshold,&reg_val);
+	reg_val&= ~tsr->tshut_cold_mask;
+	reg_val |= tshut_cold<<  __ffs(tsr->tshut_cold_mask);
+	err |= omap_control_writel(cdev, reg_val, tsr->tshut_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
+					 u32 counter)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->bgap_counter,&val);
+	val&= ~tsr->counter_mask;
+	val |= counter<<  __ffs(tsr->counter_mask);
+	err |= omap_control_writel(cdev, val, tsr->bgap_counter);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Exposed APIs */
+/**
+ * omap_bandgap_read_thot() - reads sensor current thot
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @thot - resulting current thot value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
+			      int *thot)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->bgap_threshold,&temp);
+	temp = (temp&  tsr->threshold_thot_mask)>>
+		__ffs(tsr->threshold_thot_mask);
+	ret |= adc_to_temp_conversion(bg_ptr, id, temp,&temp);
+	if (ret) {
+		dev_err(bg_ptr->dev, "failed to read thot\n");
+		return -EIO;
+	}
+
+	*thot = temp;
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_write_thot() - sets sensor current thot
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @val - desired thot value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct temp_sensor_registers *tsr;
+	u32 t_hot;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+
+	if (val<  ts_data->min_temp + ts_data->hyst_val)
+		return -EINVAL;
+	ret = temp_to_adc_conversion(val, bg_ptr, id,&t_hot);
+	if (ret<  0)
+		return ret;
+
+	mutex_lock(&bg_ptr->bg_mutex);
+	temp_sensor_configure_thot(bg_ptr, id, t_hot);
+	mutex_unlock(&bg_ptr->bg_mutex);
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_read_tcold() - reads sensor current tcold
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @tcold - resulting current tcold value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
+			       int *tcold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->bgap_threshold,&temp);
+	temp = (temp&  tsr->threshold_tcold_mask)
+	>>  __ffs(tsr->threshold_tcold_mask);
+	ret |= adc_to_temp_conversion(bg_ptr, id, temp,&temp);
+	if (ret)
+		return -EIO;
+
+	*tcold = temp;
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_write_tcold() - sets the sensor tcold
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @val - desired tcold value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct temp_sensor_registers *tsr;
+	u32 t_cold;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	if (val>  ts_data->max_temp + ts_data->hyst_val)
+		return -EINVAL;
+
+	ret = temp_to_adc_conversion(val, bg_ptr, id,&t_cold);
+	if (ret<  0)
+		return ret;
+
+	mutex_lock(&bg_ptr->bg_mutex);
+	temp_sensor_configure_tcold(bg_ptr, id, t_cold);
+	mutex_unlock(&bg_ptr->bg_mutex);
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_read_update_interval() - read the sensor update interval
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @interval - resulting update interval in miliseconds
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+					 int *interval)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 time;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->bgap_counter,&time);
+	if (ret)
+		return ret;
+	time = (time&  tsr->counter_mask)>>  __ffs(tsr->counter_mask);
+	time = time * 1000 / bg_ptr->clk_rate;
+
+	*interval = time;
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_write_update_interval() - set the update interval
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @interval - desired update interval in miliseconds
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
+					  int id, u32 interval)
+{
+	interval = interval * bg_ptr->clk_rate / 1000;
+	mutex_lock(&bg_ptr->bg_mutex);
+	configure_temp_sensor_counter(bg_ptr, id, interval);
+	mutex_unlock(&bg_ptr->bg_mutex);
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_read_temperature() - report current temperature
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @temperature - resulting temperature
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+				     int *temperature)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= tsr->bgap_dtemp_mask;
+
+	ret |= adc_to_temp_conversion(bg_ptr, id, temp,&temp);
+	if (ret)
+		return -EIO;
+
+	*temperature = temp;
+
+	return 0;
+}
+
+/**
+ * enable_continuous_mode() - One time enabling of continuous conversion mode
+ * @bg_ptr - pointer to scm instance
+ */
+static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	int i, r;
+	u32 val;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		r = omap_control_readl(cdev, tsr->bgap_mode_ctrl,&val);
+		val |= 1<<  __ffs(tsr->mode_ctrl_mask);
+		r |= omap_control_writel(cdev, val, tsr->bgap_mode_ctrl);
+		if (r)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return r ? -EIO : 0;
+}
+
+static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
+				      struct platform_device *pdev)
+{
+	int gpio_nr = bg_ptr->tshut_gpio;
+	int status;
+
+	/* Request for gpio_86 line */
+	status = gpio_request(gpio_nr, "tshut");
+	if (status<  0) {
+		dev_err(bg_ptr->dev,
+			"Could not request for TSHUT GPIO:%i\n", 86);
+		return status;
+	}
+	status = gpio_direction_input(gpio_nr);
+	if (status) {
+		dev_err(bg_ptr->dev,
+			"Cannot set input TSHUT GPIO %d\n", gpio_nr);
+		return status;
+	}
+
+	status = request_irq(gpio_to_irq(gpio_nr),
+			     omap_bandgap_tshut_irq_handler,
+			     IRQF_TRIGGER_RISING, "tshut",
+			     NULL);
+	if (status) {
+		gpio_free(gpio_nr);
+		dev_err(bg_ptr->dev, "request irq failed for TSHUT");
+	}
+
+	return 0;
+}
+
+static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
+				       struct platform_device *pdev)
+{
+	int ret;
+
+	bg_ptr->irq = platform_get_irq(pdev, 0);
+	if (bg_ptr->irq<  0) {
+		dev_err(&pdev->dev, "get_irq failed\n");
+		return bg_ptr->irq;
+	}
+	ret = request_threaded_irq(bg_ptr->irq, NULL,
+				   talert_irq_handler,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   "talert", bg_ptr);
+	if (ret) {
+		dev_err(&pdev->dev, "Request threaded irq failed.\n");
+		return ret;

drivers/thermal/omap-bandgap.c line 1193

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	}
+
+	return 0;
+}
+
+static const struct omap_bandgap_data omap4460_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "bandgap_ts_fclk",
+	.div_ck_name = "div_ts_ck",

None of these clock data should be there ideally. You should ensure that the proper device alias will be there using clkdev entries.

Except that with DT, it will not work without the clock DT binding :-(

I think Rob posted a latest update based on CCF... but for the moment we are stuck :-(

Quoted 25 lines
drivers/thermal/omap-bandgap.c new file +25 -0
+	.conv_table = omap4460_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap4460_mpu_temp_sensor_registers,
+			.ts_data =&omap4460_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+	},
+	.sensor_count = 1,
+};
+
+static const struct omap_bandgap_data omap5430_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "ts_clk_div_ck",
+	.div_ck_name = "ts_clk_div_ck",
+	.conv_table = omap5430_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap5430_mpu_temp_sensor_registers,
+			.ts_data =&omap5430_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+		{
+			.registers =&omap5430_gpu_temp_sensor_registers,

drivers/thermal/omap-bandgap.c line 1228

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+			.ts_data =&omap5430_gpu_temp_sensor_data,
+			.domain = "gpu",
+		},
+		{
+			.registers =&omap5430_core_temp_sensor_registers,
+			.ts_data =&omap5430_core_temp_sensor_data,
+			.domain = "core",
+		},
+	},
+	.sensor_count = 3,

It can probably be replaced by a sizeof.

drivers/thermal/omap-bandgap.c line 1238

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+};
+
+static const struct of_device_id of_omap_bandgap_match[] = {
+	/*
+	 * TODO: Add support to 4430
+	 * { .compatible = "ti,omap4430-bandgap", .data = , },
+	 */
+	{
+		.compatible = "ti,omap4460-bandgap",
+		.data = (void *)&omap4460_data,

No need to cast toward a void *.

Quoted 4 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+	},
+	{
+		.compatible = "ti,omap5430-bandgap",
+		.data = (void *)&omap5430_data,

drivers/thermal/omap-bandgap.c line 1252

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	},
+	/* Sentinel */
+	{ },
+};
+
+static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct omap_bandgap *bg_ptr;

bg_ptr is not a super name.

drivers/thermal/omap-bandgap.c line 1259

Quoted 7 lines
drivers/thermal/omap-bandgap.c new file +7 -0
+	u32 prop;
+
+	/* just for the sake */
+	if (!node) {
+		dev_err(&pdev->dev, "no platform information available\n");
+		return ERR_PTR(-EINVAL);
+	}

Not needed, just do the of_match_device here directly.

drivers/thermal/omap-bandgap.c line 1270

Quoted 11 lines
drivers/thermal/omap-bandgap.c new file +11 -0
+
+	bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
+				    GFP_KERNEL);
+	if (!bg_ptr) {
+		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	of_id = of_match_device(of_omap_bandgap_match,&pdev->dev);
+	if (of_id)
+		bg_ptr->pdata = of_id->data;

Nit: This is not really pdata anymore, so you should maybe remove the "p" to avoid confusion.

Quoted 26 lines
drivers/thermal/omap-bandgap.c new file +26 -0
+
+	if (bg_ptr->pdata->has_tshut) {
+		if (of_property_read_u32(node, "ti,tshut-gpio",&prop)<  0) {
+			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
+			return ERR_PTR(-EINVAL);
+		}
+		bg_ptr->tshut_gpio = prop;
+		if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
+			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
+				bg_ptr->tshut_gpio);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return bg_ptr;
+}
+
+static
+int __devinit omap_bandgap_probe(struct platform_device *pdev)
+{
+	struct device *cdev = pdev->dev.parent;
+	struct omap_bandgap *bg_ptr;
+	int clk_rate, ret = 0, i;
+
+	if (!cdev) {
+		dev_err(&pdev->dev, "no omap control ref in our parent\n");

drivers/thermal/omap-bandgap.c line 1306

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+		return -EINVAL;
+	}
+
+	bg_ptr = omap_bandgap_build(pdev);
+	if (IS_ERR_OR_NULL(bg_ptr)) {
+		dev_err(&pdev->dev, "failed to fetch platform data\n");
+		return PTR_ERR(bg_ptr);
+	}
+
+	if (bg_ptr->pdata->has_talert) {

Nit2: Yeah, in fact instead of pdata, "conf" or "settings" seems to be more representative of what this structure really contain.

Quoted 7 lines
drivers/thermal/omap-bandgap.c new file +7 -0
+		ret = omap_bandgap_talert_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
+			return ret;
+		}
+	}
+

drivers/thermal/omap-bandgap.c line 1323

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	if (bg_ptr->pdata->has_tshut) {
+		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to initialize system tshut IRQ\n");
+			goto free_talert;
+		}
+	}
+
+	bg_ptr->fclock = clk_get(NULL, bg_ptr->pdata->fclock_name);

That's not good to get a clock without using the local dev alias. But because of lack of clock DT binding yet, I'm not sure we have the choice.

Quoted 43 lines
drivers/thermal/omap-bandgap.c new file +43 -0
+	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request fclock reference\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->pdata->div_ck_name);
+	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to request div_ts_ck clock ref\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->conv_table = bg_ptr->pdata->conv_table;
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		u32 val;
+
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		/*
+		 * check if the efuse has a non-zero value if not
+		 * it is an untrimmed sample and the temperatures
+		 * may not be accurate
+		 */
+		ret = omap_control_readl(cdev, tsr->bgap_efuse,&val);
+		if (ret || !val)
+			dev_info(&pdev->dev,
+				 "Non-trimmed BGAP, Temp not accurate\n");
+	}
+
+	clk_rate = clk_round_rate(bg_ptr->div_clk,
+				  bg_ptr->pdata->sensors[0].ts_data->max_freq);
+	if (clk_rate<  bg_ptr->pdata->sensors[0].ts_data->min_freq ||
+	    clk_rate == 0xffffffff) {
+		ret = -ENODEV;
+		goto put_clks;
+	}
+
+	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot set clock rate\n");
+		goto put_clks;

drivers/thermal/omap-bandgap.c line 1376

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	}
+
+	bg_ptr->clk_rate = clk_rate;
+	clk_enable(bg_ptr->fclock);
+
+	mutex_init(&bg_ptr->bg_mutex);
+	bg_ptr->dev =&pdev->dev;
+	platform_set_drvdata(pdev, bg_ptr);
+
+	/* 1 clk cycle */

What does that mean exactly?

Regards,
Benoit

Quoted 294 lines
drivers/thermal/omap-bandgap.c new file +225 -0
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i, 1);
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_data *ts_data;
+
+		ts_data = bg_ptr->pdata->sensors[i].ts_data;
+
+		temp_sensor_init_talert_thresholds(bg_ptr, i,
+						   ts_data->t_hot,
+						   ts_data->t_cold);
+		temp_sensor_configure_tshut_hot(bg_ptr, i,
+						ts_data->tshut_hot);
+		temp_sensor_configure_tshut_cold(bg_ptr, i,
+						 ts_data->tshut_cold);
+	}
+
+	enable_continuous_mode(bg_ptr);
+
+	/* Set .250 seconds time as default counter */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i,
+					      bg_ptr->clk_rate / 4);
+
+	/* Every thing is good? Then expose the sensors */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		char *domain;
+
+		domain = bg_ptr->pdata->sensors[i].domain;
+		if (bg_ptr->pdata->expose_sensor)
+			bg_ptr->pdata->expose_sensor(bg_ptr, i, domain);
+	}
+
+	return 0;
+
+put_clks:
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+free_irqs:
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+free_talert:
+	free_irq(bg_ptr->irq, bg_ptr);
+
+	return ret;
+}
+
+static
+int __devexit omap_bandgap_remove(struct platform_device *pdev)
+{
+	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
+
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+	free_irq(bg_ptr->irq, bg_ptr);
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int err = 0;
+	int i;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,
+					&rval->bg_mode_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_mask_ctrl,
+					&rval->bg_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_counter,
+					&rval->bg_counter);
+		err |= omap_control_readl(cdev, tsr->bgap_threshold,
+					&rval->bg_threshold);
+		err |= omap_control_readl(cdev, tsr->tshut_threshold,
+					&rval->tshut_threshold);
+
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int
+omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp = 0, counter = 1000;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	/* Select single conversion mode */
+	err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,&temp);
+	temp&= ~(1<<  __ffs(tsr->mode_ctrl_mask));
+	omap_control_writel(cdev, temp, tsr->bgap_mode_ctrl);
+
+	/* Start of Conversion = 1 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp |= 1<<  __ffs(tsr->bgap_soc_mask);
+	omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+	/* Wait until DTEMP is updated */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= (tsr->bgap_dtemp_mask);
+	while ((temp == 0)&&  --counter) {
+		err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+		temp&= (tsr->bgap_dtemp_mask);
+	}
+	/* Start of Conversion = 0 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= ~(1<<  __ffs(tsr->bgap_soc_mask));
+	err |= omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int i, err = 0;
+	u32 temp = 0;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+		u32 val;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_counter,&val);
+		if (val == 0) {
+			err |= omap_control_writel(cdev, rval->bg_threshold,
+						   tsr->bgap_threshold);
+			err |= omap_control_writel(cdev, rval->tshut_threshold,
+						   tsr->tshut_threshold);
+			/* Force immediate temperature measurement and update
+			 * of the DTEMP field
+			 */
+			omap_bandgap_force_single_read(bg_ptr, i);
+			err |= omap_control_writel(cdev, rval->bg_counter,
+						   tsr->bgap_counter);
+			err |= omap_control_writel(cdev, rval->bg_mode_ctrl,
+						   tsr->bgap_mode_ctrl);
+			err |= omap_control_writel(cdev, rval->bg_ctrl,
+						   tsr->bgap_mask_ctrl);
+		} else {
+			err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,
+						&temp);
+			temp&= (tsr->bgap_dtemp_mask);
+			if (temp == 0) {
+				omap_bandgap_force_single_read(bg_ptr, i);
+				err |= omap_control_readl(cdev,
+							  tsr->bgap_mask_ctrl,
+							&temp);
+				temp |= 1<<  __ffs(tsr->mode_ctrl_mask);
+				err |= omap_control_writel(cdev, temp,
+							   tsr->bgap_mask_ctrl);
+			}
+		}
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_suspend(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+	int err;
+
+	err = omap_bandgap_save_ctxt(bg_ptr);
+	clk_disable(bg_ptr->fclock);
+
+	return err;
+}
+
+static int omap_bandgap_resume(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+
+	clk_enable(bg_ptr->fclock);
+
+	return omap_bandgap_restore_ctxt(bg_ptr);
+}
+static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
+				omap_bandgap_resume)
+};
+
+#define DEV_PM_OPS	(&omap_bandgap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver omap_bandgap_sensor_driver = {
+	.probe = omap_bandgap_probe,
+	.remove = omap_bandgap_remove,
+	.driver = {
+			.name = "omap-bandgap",
+			.pm = DEV_PM_OPS,
+			.of_match_table	= of_omap_bandgap_match,
+	},
+};
+
+module_platform_driver(omap_bandgap_sensor_driver);
+early_platform_init("early_omap_temperature",&omap_bandgap_sensor_driver);
+
+MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-bandgap");
+MODULE_AUTHOR("Texas Instrument Inc.");
drivers/thermal/omap-bandgap.h new file +63 -0
new file mode 100644
index 0000000..12e0d6b
@@ -0,0 +1,63 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin<[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __OMAP_BANDGAP_H
+#define __OMAP_BANDGAP_H
+
+struct omap_bandgap_data;
+
+/**
+ * struct omap_bandgap - bandgap device structure
+ * @dev: device pointer
+ * @pdata: platform data with sensor data
+ * @fclock: pointer to functional clock of temperature sensor
+ * @div_clk: pointer to parent clock of temperature sensor fclk
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @bg_mutex: Mutex for sysfs, irq and PM
+ * @irq: MPU Irq number for thermal alert
+ * @tshut_gpio: GPIO where Tshut signal is routed
+ * @clk_rate: Holds current clock rate
+ */
+struct omap_bandgap {
+	struct device			*dev;
+	const struct omap_bandgap_data	*pdata;
+	struct clk			*fclock;
+	struct clk			*div_clk;
+	const int			*conv_table;
+	struct mutex			bg_mutex; /* Mutex for irq and PM */
+	int				irq;
+	int				tshut_gpio;
+	u32				clk_rate;
+};
+
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+				      int *interval);
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
+				       u32 interval);
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+				  int *temperature);
+
+#endif
#53 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

Quoted 687 lines · Cousson Benoit
Quoted 366 lines · Eduardo Valentin

In the System Control Module, OMAP supplies a voltage reference and a temperature sensor feature that are gathered in the band gap voltage and temperature sensor (VBGAPTS) module. The band gap provides current and voltage reference for its internal circuits and other analog IP blocks. The analog-to-digital converter (ADC) produces an output value that is proportional to the silicon temperature.

This patch provides a platform driver which expose this feature. It is moduled as a MFD child of the System Control Module core MFD driver.

This driver provides only APIs to access the device properties, like temperature, thresholds and update rate.

---
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 drivers/thermal/Kconfig                            |   13 +
 drivers/thermal/Makefile                           |    4 +-
 drivers/thermal/omap-bandgap.c                     | 1601 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   63 +
 5 files changed, 1707 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h
Documentation/devicetree/bindings/thermal/omap_bandgap.txt new file +27 -0
new file mode 100644
index 0000000..430bcf8
@@ -0,0 +1,27 @@
+* Texas Instrument OMAP SCM bandgap bindings
+
+In the System Control Module, OMAP supplies a voltage reference
+and a temperature sensor feature that are gathered in the band
+gap voltage and temperature sensor (VBGAPTS) module. The band
+gap provides current and voltage reference for its internal
+circuits and other analog IP blocks. The analog-to-digital
+converter (ADC) produces an output value that is proportional
+to the silicon temperature.
+
+Required properties:
+- compatible : Should be:
+  - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap
+  - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap
+- interrupts : this entry should indicate which interrupt line
+the talert signal is routed to;
+Specific:
+- ti,tshut-gpio : this entry should be used to inform which GPIO
+line the tshut signal is routed to;
+
+Example:
+
+bandgap {
+	compatible = "ti,omap4460-control-bandgap";
+	interrupts =<0 126 4>; /* talert */
+	ti,tshut-gpio =<86>;
+};
drivers/thermal/Kconfig +13 -0
index 514a691..ffdd240 100644
@@ -26,3 +26,16 @@ config SPEAR_THERMAL
 	help
 	  Enable this to plug the SPEAr thermal sensor driver into the Linux
 	  thermal framework
+
+config OMAP_BANDGAP
+	tristate "Texas Instruments OMAP4+ temperature sensor driver"
+	depends on THERMAL
+	depends on MFD_OMAP_CONTROL
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  OMAP4460+ on die bandgap temperature sensor support. The register
+	  set is part of system control module.
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
+
drivers/thermal/Makefile +3 -1
index a9fff0b..5ff1af1 100644
@@ -3,4 +3,6 @@
 #
 
 obj-$(CONFIG_THERMAL)		+= thermal_sys.o
-obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
\ No newline at end of file
+obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
+obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal.o
+omap-thermal-y			:= omap-bandgap.o
drivers/thermal/omap-bandgap.c new file +265 -0
new file mode 100644
index 0000000..3d5a12b
@@ -0,0 +1,1601 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy<[email protected]>
+ * Author: Moiz Sonasath<[email protected]>
+ * Couple of fixes, DT and MFD adaptation:
+ *   Eduardo Valentin<[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include<linux/module.h>
+#include<linux/export.h>
+#include<linux/init.h>
+#include<linux/kernel.h>
+#include<linux/interrupt.h>
+#include<linux/clk.h>
+#include<linux/gpio.h>
+#include<linux/platform_device.h>
+#include<linux/err.h>
+#include<linux/types.h>
+#include<linux/mutex.h>
+#include<linux/reboot.h>
+#include<linux/of_platform.h>
+#include<linux/of_irq.h>
+#include<linux/mfd/omap_control.h>
+
+#include<mach/control.h>
+
+#include "omap-bandgap.h"
+
+/* Offsets from the base of temperature sensor registers */
+
+#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x32C
+#define OMAP4460_BGAP_CTRL_OFFSET		0x378
+#define OMAP4460_BGAP_COUNTER_OFFSET		0x37C
+#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x380
+#define OMAP4460_BGAP_TSHUT_OFFSET		0x384
+#define OMAP4460_BGAP_STATUS_OFFSET		0x388
+#define OMAP4460_FUSE_OPP_BGAP			0x260
+
+#define OMAP5430_TEMP_SENSOR_MPU_OFFSET		0x32C
+#define OMAP5430_BGAP_CTRL_OFFSET		0x380
+#define OMAP5430_BGAP_COUNTER_MPU_OFFSET	0x39C
+#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET	0x384
+#define OMAP5430_BGAP_TSHUT_MPU_OFFSET		0x390
+#define OMAP5430_BGAP_STATUS_OFFSET		0x3A8
+#define OMAP5430_FUSE_OPP_BGAP_MPU		0x1E4
+
+#define OMAP5430_TEMP_SENSOR_GPU_OFFSET		0x330
+#define OMAP5430_BGAP_COUNTER_GPU_OFFSET	0x3A0
+#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET	0x388
+#define OMAP5430_BGAP_TSHUT_GPU_OFFSET		0x394
+#define OMAP5430_FUSE_OPP_BGAP_GPU		0x1E0
+
+#define OMAP5430_TEMP_SENSOR_CORE_OFFSET	0x334
+#define OMAP5430_BGAP_COUNTER_CORE_OFFSET	0x3A4
+#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET	0x38C
+#define OMAP5430_BGAP_TSHUT_CORE_OFFSET		0x398
+#define OMAP5430_FUSE_OPP_BGAP_CORE		0x1E8
+
+#define OMAP4460_TSHUT_HOT		900	/* 122 deg C */
+#define OMAP4460_TSHUT_COLD		895	/* 100 deg C */
+#define OMAP4460_T_HOT			800	/* 73 deg C */
+#define OMAP4460_T_COLD			795	/* 71 deg C */
+#define OMAP4460_MAX_FREQ		1500000
+#define OMAP4460_MIN_FREQ		1000000
+#define OMAP4460_MIN_TEMP		-40000
+#define OMAP4460_MAX_TEMP		123000
+#define OMAP4460_HYST_VAL		5000
+#define OMAP4460_ADC_START_VALUE	530
+#define OMAP4460_ADC_END_VALUE		932
+
+#define OMAP5430_MPU_TSHUT_HOT		915
+#define OMAP5430_MPU_TSHUT_COLD		900
+#define OMAP5430_MPU_T_HOT		800
+#define OMAP5430_MPU_T_COLD		795
+#define OMAP5430_MPU_MAX_FREQ		1500000
+#define OMAP5430_MPU_MIN_FREQ		1000000
+#define OMAP5430_MPU_MIN_TEMP		-40000
+#define OMAP5430_MPU_MAX_TEMP		125000
+#define OMAP5430_MPU_HYST_VAL		5000
+#define OMAP5430_ADC_START_VALUE	532
+#define OMAP5430_ADC_END_VALUE		934
+
+#define OMAP5430_GPU_TSHUT_HOT		915
+#define OMAP5430_GPU_TSHUT_COLD		900
+#define OMAP5430_GPU_T_HOT		800
+#define OMAP5430_GPU_T_COLD		795
+#define OMAP5430_GPU_MAX_FREQ		1500000
+#define OMAP5430_GPU_MIN_FREQ		1000000
+#define OMAP5430_GPU_MIN_TEMP		-40000
+#define OMAP5430_GPU_MAX_TEMP		125000
+#define OMAP5430_GPU_HYST_VAL		5000
+
+#define OMAP5430_CORE_TSHUT_HOT		915
+#define OMAP5430_CORE_TSHUT_COLD	900
+#define OMAP5430_CORE_T_HOT		800
+#define OMAP5430_CORE_T_COLD		795
+#define OMAP5430_CORE_MAX_FREQ		1500000
+#define OMAP5430_CORE_MIN_FREQ		1000000
+#define OMAP5430_CORE_MIN_TEMP		-40000
+#define OMAP5430_CORE_MAX_TEMP		125000
+#define OMAP5430_CORE_HYST_VAL		5000
+
+/**
+ * The register offsets and bit fields might change across
+ * OMAP versions hence populating them in this structure.
+ */
+
+struct temp_sensor_registers {
+	u32	temp_sensor_ctrl;
+	u32	bgap_tempsoff_mask;
+	u32	bgap_soc_mask;
+	u32	bgap_eocz_mask;
+	u32	bgap_dtemp_mask;
+
+	u32	bgap_mask_ctrl;
+	u32	mask_hot_mask;
+	u32	mask_cold_mask;
+
+	u32	bgap_mode_ctrl;
+	u32	mode_ctrl_mask;
+
+	u32	bgap_counter;
+	u32	counter_mask;
+
+	u32	bgap_threshold;
+	u32	threshold_thot_mask;
+	u32	threshold_tcold_mask;
+
+	u32	tshut_threshold;
+	u32	tshut_hot_mask;
+	u32	tshut_cold_mask;
+
+	u32	bgap_status;
+	u32	status_clean_stop_mask;
+	u32	status_bgap_alert_mask;
+	u32	status_hot_mask;
+	u32	status_cold_mask;
+
+	u32	bgap_efuse;
+};
+
+/**
+ * The thresholds and limits for temperature sensors.
+ */
+struct temp_sensor_data {
+	u32	tshut_hot;
+	u32	tshut_cold;
+	u32	t_hot;
+	u32	t_cold;
+	u32	min_freq;
+	u32	max_freq;
+	int	max_temp;
+	int	min_temp;
+	int	hyst_val;
+	u32	adc_start_val;
+	u32	adc_end_val;
+	u32	update_int1;
+	u32	update_int2;
+};
+
+/**
+ * struct temp_sensor_regval - temperature sensor register values
+ * @bg_mode_ctrl: temp sensor control register value
+ * @bg_ctrl: bandgap ctrl register value
+ * @bg_counter: bandgap counter value
+ * @bg_threshold: bandgap threshold register value
+ * @tshut_threshold: bandgap tshut register value
+ */
+struct temp_sensor_regval {
+	u32			bg_mode_ctrl;
+	u32			bg_ctrl;
+	u32			bg_counter;
+	u32			bg_threshold;
+	u32			tshut_threshold;
+};
+
+/**
+ * struct omap_temp_sensor - bandgap temperature sensor platform data
+ * @ts_data: pointer to struct with thresholds, limits of temperature sensor
+ * @registers: pointer to the list of register offsets and bitfields
+ * @regval: temperature sensor register values
+ * @domain: the name of the domain where the sensor is located
+ */
+struct omap_temp_sensor {
+	struct temp_sensor_data		*ts_data;
+	struct temp_sensor_registers	*registers;
+	struct temp_sensor_regval	*regval;
+	char				*domain;
+};
+
+/**
+ * struct omap_bandgap_data - bandgap platform data structure
+ * @has_talert: indicates if the chip has talert output line
+ * @has_tshut: indicates if the chip has tshut output line
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @fclock_name: clock name of the functional clock
+ * @div_ck_nme: clock name of the clock divisor
+ * @sensor_count: count of temperature sensor device in scm
+ * @sensors: array of sensors present in this bandgap instance
+ * @expose_sensor: callback to export sensor to thermal API
+ */
+struct omap_bandgap_data {
+	bool				has_talert;
+	bool				has_tshut;
+	const int			*conv_table;
+	char				*fclock_name;
+	char				*div_ck_name;
+	int				sensor_count;
+	int (*report_temperature)(struct omap_bandgap *bg_ptr, int id);
+	int (*expose_sensor)(struct omap_bandgap *bg_ptr, int id, char *domain);
+
+	/* this needs to be at the end */
+	struct omap_temp_sensor		sensors[];
+};
+
+/* TODO: provide data structures for 4430 */
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap4460_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
+	.bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP4460_MASK_HOT_MASK,
+	.mask_cold_mask = OMAP4460_MASK_COLD_MASK,
+
+	.bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+	.mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
+
+	.bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
+	.counter_mask = OMAP4460_COUNTER_MASK,
+
+	.bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
+	.threshold_thot_mask = OMAP4460_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP4460_T_COLD_MASK,
+
+	.tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
+	.tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP4460_BGAP_STATUS_OFFSET,

drivers/thermal/omap-bandgap.c line 275

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	.status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
+	.status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP4460_HOT_FLAG_MASK,
+	.status_cold_mask = OMAP4460_COLD_FLAG_MASK,
+
+	.bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU

Bad copy paste.

Quoted 31 lines
drivers/thermal/omap-bandgap.c new file +31 -0
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap5430_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
+
+	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
+	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,

drivers/thermal/omap-bandgap.c line 316

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	.status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */

Ditto

Quoted 29 lines
drivers/thermal/omap-bandgap.c new file +29 -0
+static struct temp_sensor_registers
+omap5430_gpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_MM_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_MM_MASK,
+
+	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
+	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,

drivers/thermal/omap-bandgap.c line 355

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	.status_hot_mask = OMAP5430_HOT_MM_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_MM_FLAG_MASK,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */

Ditto

Quoted 221 lines
drivers/thermal/omap-bandgap.c new file +221 -0
+static struct temp_sensor_registers
+omap5430_core_temp_sensor_registers = {
+	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
+	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+	.mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
+	.mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
+
+	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
+	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+	.bgap_counter = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
+	.counter_mask = OMAP5430_COUNTER_MASK,
+
+	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
+	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
+	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+	.tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
+	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+	.status_clean_stop_mask = 0x0,
+	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+	.status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
+	.status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
+
+	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
+};
+
+/* Thresholds and limits for OMAP4460 MPU temperature sensor */
+static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
+	.tshut_hot = OMAP4460_TSHUT_HOT,
+	.tshut_cold = OMAP4460_TSHUT_COLD,
+	.t_hot = OMAP4460_T_HOT,
+	.t_cold = OMAP4460_T_COLD,
+	.min_freq = OMAP4460_MIN_FREQ,
+	.max_freq = OMAP4460_MAX_FREQ,
+	.max_temp = OMAP4460_MAX_TEMP,
+	.min_temp = OMAP4460_MIN_TEMP,
+	.hyst_val = OMAP4460_HYST_VAL,
+	.adc_start_val = OMAP4460_ADC_START_VALUE,
+	.adc_end_val = OMAP4460_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 MPU temperature sensor */
+static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
+	.tshut_hot = OMAP5430_MPU_TSHUT_HOT,
+	.tshut_cold = OMAP5430_MPU_TSHUT_COLD,
+	.t_hot = OMAP5430_MPU_T_HOT,
+	.t_cold = OMAP5430_MPU_T_COLD,
+	.min_freq = OMAP5430_MPU_MIN_FREQ,
+	.max_freq = OMAP5430_MPU_MAX_FREQ,
+	.max_temp = OMAP5430_MPU_MAX_TEMP,
+	.min_temp = OMAP5430_MPU_MIN_TEMP,
+	.hyst_val = OMAP5430_MPU_HYST_VAL,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 GPU temperature sensor */
+static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
+	.tshut_hot = OMAP5430_GPU_TSHUT_HOT,
+	.tshut_cold = OMAP5430_GPU_TSHUT_COLD,
+	.t_hot = OMAP5430_GPU_T_HOT,
+	.t_cold = OMAP5430_GPU_T_COLD,
+	.min_freq = OMAP5430_GPU_MIN_FREQ,
+	.max_freq = OMAP5430_GPU_MAX_FREQ,
+	.max_temp = OMAP5430_GPU_MAX_TEMP,
+	.min_temp = OMAP5430_GPU_MIN_TEMP,
+	.hyst_val = OMAP5430_GPU_HYST_VAL,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 CORE temperature sensor */
+static struct temp_sensor_data omap5430_core_temp_sensor_data = {
+	.tshut_hot = OMAP5430_CORE_TSHUT_HOT,
+	.tshut_cold = OMAP5430_CORE_TSHUT_COLD,
+	.t_hot = OMAP5430_CORE_T_HOT,
+	.t_cold = OMAP5430_CORE_T_COLD,
+	.min_freq = OMAP5430_CORE_MIN_FREQ,
+	.max_freq = OMAP5430_CORE_MAX_FREQ,
+	.max_temp = OMAP5430_CORE_MAX_TEMP,
+	.min_temp = OMAP5430_CORE_MIN_TEMP,
+	.hyst_val = OMAP5430_CORE_HYST_VAL,
+	.adc_start_val = OMAP5430_ADC_START_VALUE,
+	.adc_end_val = OMAP5430_ADC_END_VALUE,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static const int
+omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
+	-37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
+	-34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
+	-30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
+	-27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
+	-24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+	-20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
+	-17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
+	-13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
+	-10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
+	-6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
+	-2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
+	2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
+	6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
+	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
+	15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
+	19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
+	23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
+	26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
+	30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+	34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
+	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
+	42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
+	45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
+	49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
+	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
+	57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
+	60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
+	64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
+	68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
+	72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+	75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
+	79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
+	83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
+	86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
+	90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
+	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
+	98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
+	101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
+	104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
+	108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
+	111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
+	114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
+	117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+	124600, 124900, 125000, 125000, 125000, 125000
+};
+
+static const int
+omap5430_adc_to_temp[OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600,
+	-38200, -37800, -37300, -36800,
+	-36400, -36000, -35600, -35200, -34800, -34300, -33800, -33400, -33000,
+	-32600,
+	-32200, -31800, -31300, -30800, -30400, -30000, -29600, -29200, -28700,
+	-28200, -27800, -27400, -27000, -26600, -26200, -25700, -25200, -24800,
+	-24400, -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+	-20600, -20200, -19700, -19200, -9300, -18400, -18000, -17600, -17200,
+	-16700, -16200, -15800, -15400, -15000, -14600, -14200, -13700, -13200,
+	-12800, -12400, -12000, -11600, -11200, -10700, -10200, -9800, -9400,
+	-9000,
+	-8600, -8200, -7700, -7200, -6800, -6400, -6000, -5600, -5200, -4800,
+	-4300,
+	-3800, -3400, -3000, -2600, -2200, -1800, -1300, -800, -400, 0, 400,
+	800,
+	1200, 1600, 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000,
+	6400, 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10800,
+	11100,
+	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, 15300,
+	15800,
+	16200, 16600, 17000, 17400, 17800, 18200, 18700, 19200, 19600, 20000,
+	20400,
+	20800, 21200, 21600, 22100, 22600, 23000, 23400, 23800, 24200, 24600,
+	25000,
+	25400, 25900, 26400, 26800, 27200, 27600, 28000, 28400, 28800, 29300,
+	29800,
+	30200, 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+	34400,
+	34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, 38200, 38600,
+	39000,
+	39400, 39800, 40200, 40600, 41100, 41600, 42000, 42400, 42800, 43200,
+	43600,
+	44000, 44400, 44800, 45300, 45800, 46200, 46600, 47000, 47400, 47800,
+	48200,
+	48600, 49000, 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400,
+	52800,
+	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, 57000,
+	57400,
+	57800, 58200, 58700, 59200, 59600, 60000, 60400, 60800, 61200, 61600,
+	62000,
+	62400, 62800, 63300, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
+	66600,
+	67000, 67400, 67800, 68200, 68700, 69200, 69600, 70000, 70400, 70800,
+	71200,
+	71600, 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+	75800,
+	76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, 79400, 79800,
+	80300,
+	80800, 81200, 81600, 82000, 82400, 82800, 83200, 83600, 84000, 84400,
+	84800,
+	85200, 85600, 86000, 86400, 86800, 87300, 87800, 88200, 88600, 89000,
+	89400,
+	89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400,
+	93800,
+	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, 98000,
+	98400,
+	98800, 99200, 99600, 100000, 100400, 100800, 101200, 101600, 102000,
+	102400,
+	102800, 103200, 103600, 104000, 104400, 104800, 105200, 105600, 106100,
+	106600, 107000, 107400, 107800, 108200, 108600, 109000, 109400, 109800,
+	110200, 110600, 111000, 111400, 111800, 112200, 112600, 113000, 113400,
+	113800, 114200, 114600, 115000, 115400, 115800, 116200, 116600, 117000,
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 580

Quoted 4 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+	117400, 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+	124600, 124900, 125000, 125000, 125000, 125000,
+};

It might be good to store the per SoC data in dedicated files or at least put some #ifdef around to avoid wasting memory for a non-multi OMAP boot.

Indeed, I was rewriting this stuff with that in mind when I saw your comment :-)

Idea is to move all this arch dependent data structures to specific files. Here at omap-bandgap.c we would have essentially the pdriver and the local functions and APIs. The omapX-thermal.c would contain the specific data structures and the functions related to the thermal zones, and possibly the policy specifics for each case. Something like:

drivers/thermal/

 |- omap-bandgap.c: Bandgap platform driver specific functions and APIs (CONFIG_OMAP_BANDGAP)
 |- omap-bandgap.h: Common data structure definition and defines
 |- omap4-thermal.c: OMAP4xx data structures needed by the bandgap driver and the thermal zone definitions (CONFIG_OMAP4_THERMAL)
 |- omap5-thermal.c: OMAP54xx data structures needed by the bandgap driver and the thermal zone definitions (CONFIG_OMAP5_THERMAL)
 |- omap-thermal.ko: Module binary. It would contain the support depending on what has been selected at compile time
Quoted 1 line

filename: omap-thermal.ko

author:         Texas Instrument Inc.
alias:          platform:omap-bandgap
license:        GPL v2
description:    OMAP4+ bandgap temperature sensor driver
srcversion:     937A9F9230A5025A0E9A268
alias:          of:N*T*Cti,omap4460-bandgap*
alias:          of:N*T*Cti,omap5430-bandgap*
depends:        
intree:         Y
vermagic:       3.4.0-rc6-12199-g3e31a0c-dirty SMP preempt mod_unload modversions ARMv7 p2v8 

There is gonna happen some ifdefery in omap-bandgap.[c,h] in order to compose the match_id table based on what has been selected for compilation, but I at least don't see any other way around.

Quoted 1,131 lines
Quoted 603 lines
drivers/thermal/omap-bandgap.c new file +603 -0
+
+static irqreturn_t talert_irq_handler(int irq, void *data)
+{
+	struct omap_bandgap *bg_ptr = data;
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 t_hot = 0, t_cold = 0, temp, ctrl;
+	int i, r;
+
+	bg_ptr = data;
+	/* Read the status of t_hot */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		r = omap_control_readl(cdev, tsr->bgap_status,&t_hot);
+		t_hot&= tsr->status_hot_mask;
+
+		/* Read the status of t_cold */
+		r |= omap_control_readl(cdev, tsr->bgap_status,&t_cold);
+		t_cold&= tsr->status_cold_mask;
+
+		if (!t_cold&&  !t_hot)
+			continue;
+
+		r |= omap_control_readl(cdev, tsr->bgap_mask_ctrl,&ctrl);
+		/*
+		 * One TALERT interrupt: Two sources
+		 * If the interrupt is due to t_hot then mask t_hot and
+		 * and unmask t_cold else mask t_cold and unmask t_hot
+		 */
+		if (t_hot) {
+			ctrl&= ~tsr->mask_hot_mask;
+			ctrl |= tsr->mask_cold_mask;
+		} else if (t_cold) {
+			ctrl&= ~tsr->mask_cold_mask;
+			ctrl |= tsr->mask_hot_mask;
+		}
+
+		r |= omap_control_writel(cdev, ctrl, tsr->bgap_mask_ctrl);
+
+		if (r) {
+			dev_err(bg_ptr->dev, "failed to ack talert interrupt\n");
+			return IRQ_NONE;
+		}
+
+		/* read temperature */
+		r = omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+		temp&= tsr->bgap_dtemp_mask;
+
+		/* report temperature to whom may concern */
+		if (bg_ptr->pdata->report_temperature)
+			bg_ptr->pdata->report_temperature(bg_ptr, i);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
+{
+	orderly_poweroff(true);
+
+	return IRQ_HANDLED;
+}
+
+static
+int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
+			   int *t)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+
+	/* look up for temperature in the table and return the temperature */
+	if (adc_val<  ts_data->adc_start_val || adc_val>  ts_data->adc_end_val)
+		return -ERANGE;
+
+	*t = bg_ptr->conv_table[adc_val - ts_data->adc_start_val];
+
+	return 0;
+}
+
+static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
+				  int *adc)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[i].ts_data;
+	int high, low, mid;
+
+	low = 0;
+	high = ts_data->adc_end_val - ts_data->adc_start_val;
+	mid = (high + low) / 2;
+
+	if (temp<  bg_ptr->conv_table[high] || temp>  bg_ptr->conv_table[high])
+		return -EINVAL;
+
+	while (low<  high) {
+		if (temp<  bg_ptr->conv_table[mid])
+			high = mid - 1;
+		else
+			low = mid + 1;
+		mid = (low + high) / 2;
+	}
+
+	*adc = ts_data->adc_start_val + low;
+
+	return 0;
+}
+
+static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
+					 u32 t_hot, u32 t_cold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp, reg_val;
+	int err;
+
+	/* Read the current on die temperature */
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= tsr->bgap_dtemp_mask;
+
+	err |= omap_control_readl(cdev, tsr->bgap_mask_ctrl,&reg_val);
+	if (temp<  t_hot)
+		reg_val |= tsr->mask_hot_mask;
+	else
+		reg_val&= ~tsr->mask_hot_mask;
+
+	if (t_cold<  temp)
+		reg_val |= tsr->mask_cold_mask;
+	else
+		reg_val&= ~tsr->mask_cold_mask;
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_mask_ctrl);
+
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to unmask interrupts\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static
+int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
+	     u32 *sum)
+{
+	int temp, ret;
+
+	ret = adc_to_temp_conversion(bg_ptr, i, adc_val,&temp);
+	if (ret<  0)
+		return ret;
+
+	temp += hyst_val;
+
+	return temp_to_adc_conversion(temp, bg_ptr, i, sum);
+}
+
+static
+int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 thresh_val, reg_val;
+	int cold, err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+
+	/* obtain the T cold value */
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+	cold = (thresh_val&  tsr->threshold_tcold_mask)>>
+	    __ffs(tsr->threshold_tcold_mask);
+	if (t_hot<= cold) {
+		/* change the t_cold to t_hot - 5000 millidegrees */
+		err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id,&cold);
+		/* write the new t_cold value */
+		reg_val = thresh_val&  (~tsr->threshold_tcold_mask);
+		reg_val |= cold<<  __ffs(tsr->threshold_tcold_mask);
+		err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+		thresh_val = reg_val;
+	}
+
+	/* write the new t_hot value */
+	reg_val = thresh_val&  ~tsr->threshold_thot_mask;
+	reg_val |= (t_hot<<  __ffs(tsr->threshold_thot_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+		return -EIO;
+	}
+
+	return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
+}
+
+static
+int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
+				       int t_hot, int t_cold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 reg_val, thresh_val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+
+	/* write the new t_cold value */
+	reg_val = thresh_val&  ~tsr->threshold_tcold_mask;
+	reg_val |= (t_cold<<  __ffs(tsr->threshold_tcold_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
+		return -EIO;
+	}
+
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+
+	/* write the new t_hot value */
+	reg_val = thresh_val&  ~tsr->threshold_thot_mask;
+	reg_val |= (t_hot<<  __ffs(tsr->threshold_thot_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+		return -EIO;
+	}
+
+	err = omap_control_readl(cdev, tsr->bgap_mask_ctrl,&reg_val);
+	reg_val |= tsr->mask_hot_mask;
+	reg_val |= tsr->mask_cold_mask;
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_mask_ctrl);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+		return -EIO;
+	}
+
+	return err;
+}
+
+static
+int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
+				int t_cold)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 thresh_val, reg_val;
+	int hot, err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	/* obtain the T cold value */
+	err = omap_control_readl(cdev, tsr->bgap_threshold,&thresh_val);
+	hot = (thresh_val&  tsr->threshold_thot_mask)>>
+	    __ffs(tsr->threshold_thot_mask);
+
+	if (t_cold>= hot) {
+		/* change the t_hot to t_cold + 5000 millidegrees */
+		err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id,&hot);
+		/* write the new t_hot value */
+		reg_val = thresh_val&  (~tsr->threshold_thot_mask);
+		reg_val |= hot<<  __ffs(tsr->threshold_thot_mask);
+		err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+		thresh_val = reg_val;
+	}
+
+	/* write the new t_cold value */
+	reg_val = thresh_val&  ~tsr->threshold_tcold_mask;
+	reg_val |= (t_cold<<  __ffs(tsr->threshold_tcold_mask));
+	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
+		return -EIO;
+	}
+
+	return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
+}
+
+static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr,
+					   int id, int tshut_hot)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 reg_val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->tshut_threshold,&reg_val);
+	reg_val&= ~tsr->tshut_hot_mask;
+	reg_val |= tshut_hot<<  __ffs(tsr->tshut_hot_mask);
+	err |= omap_control_writel(cdev, reg_val, tsr->tshut_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tshut thot\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
+					    int id, int tshut_cold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 reg_val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->tshut_threshold,&reg_val);
+	reg_val&= ~tsr->tshut_cold_mask;
+	reg_val |= tshut_cold<<  __ffs(tsr->tshut_cold_mask);
+	err |= omap_control_writel(cdev, reg_val, tsr->tshut_threshold);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
+					 u32 counter)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 val;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	err = omap_control_readl(cdev, tsr->bgap_counter,&val);
+	val&= ~tsr->counter_mask;
+	val |= counter<<  __ffs(tsr->counter_mask);
+	err |= omap_control_writel(cdev, val, tsr->bgap_counter);
+	if (err) {
+		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Exposed APIs */
+/**
+ * omap_bandgap_read_thot() - reads sensor current thot
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @thot - resulting current thot value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
+			      int *thot)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->bgap_threshold,&temp);
+	temp = (temp&  tsr->threshold_thot_mask)>>
+		__ffs(tsr->threshold_thot_mask);
+	ret |= adc_to_temp_conversion(bg_ptr, id, temp,&temp);
+	if (ret) {
+		dev_err(bg_ptr->dev, "failed to read thot\n");
+		return -EIO;
+	}
+
+	*thot = temp;
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_write_thot() - sets sensor current thot
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @val - desired thot value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct temp_sensor_registers *tsr;
+	u32 t_hot;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+
+	if (val<  ts_data->min_temp + ts_data->hyst_val)
+		return -EINVAL;
+	ret = temp_to_adc_conversion(val, bg_ptr, id,&t_hot);
+	if (ret<  0)
+		return ret;
+
+	mutex_lock(&bg_ptr->bg_mutex);
+	temp_sensor_configure_thot(bg_ptr, id, t_hot);
+	mutex_unlock(&bg_ptr->bg_mutex);
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_read_tcold() - reads sensor current tcold
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @tcold - resulting current tcold value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
+			       int *tcold)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->bgap_threshold,&temp);
+	temp = (temp&  tsr->threshold_tcold_mask)
+	>>  __ffs(tsr->threshold_tcold_mask);
+	ret |= adc_to_temp_conversion(bg_ptr, id, temp,&temp);
+	if (ret)
+		return -EIO;
+
+	*tcold = temp;
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_write_tcold() - sets the sensor tcold
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @val - desired tcold value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
+{
+	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+	struct temp_sensor_registers *tsr;
+	u32 t_cold;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	if (val>  ts_data->max_temp + ts_data->hyst_val)
+		return -EINVAL;
+
+	ret = temp_to_adc_conversion(val, bg_ptr, id,&t_cold);
+	if (ret<  0)
+		return ret;
+
+	mutex_lock(&bg_ptr->bg_mutex);
+	temp_sensor_configure_tcold(bg_ptr, id, t_cold);
+	mutex_unlock(&bg_ptr->bg_mutex);
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_read_update_interval() - read the sensor update interval
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @interval - resulting update interval in miliseconds
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+					 int *interval)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 time;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->bgap_counter,&time);
+	if (ret)
+		return ret;
+	time = (time&  tsr->counter_mask)>>  __ffs(tsr->counter_mask);
+	time = time * 1000 / bg_ptr->clk_rate;
+
+	*interval = time;
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_write_update_interval() - set the update interval
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @interval - desired update interval in miliseconds
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
+					  int id, u32 interval)
+{
+	interval = interval * bg_ptr->clk_rate / 1000;
+	mutex_lock(&bg_ptr->bg_mutex);
+	configure_temp_sensor_counter(bg_ptr, id, interval);
+	mutex_unlock(&bg_ptr->bg_mutex);
+
+	return 0;
+}
+
+/**
+ * omap_bandgap_read_temperature() - report current temperature
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @temperature - resulting temperature
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+				     int *temperature)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp;
+	int ret;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	ret = omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= tsr->bgap_dtemp_mask;
+
+	ret |= adc_to_temp_conversion(bg_ptr, id, temp,&temp);
+	if (ret)
+		return -EIO;
+
+	*temperature = temp;
+
+	return 0;
+}
+
+/**
+ * enable_continuous_mode() - One time enabling of continuous conversion mode
+ * @bg_ptr - pointer to scm instance
+ */
+static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	int i, r;
+	u32 val;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		r = omap_control_readl(cdev, tsr->bgap_mode_ctrl,&val);
+		val |= 1<<  __ffs(tsr->mode_ctrl_mask);
+		r |= omap_control_writel(cdev, val, tsr->bgap_mode_ctrl);
+		if (r)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return r ? -EIO : 0;
+}
+
+static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
+				      struct platform_device *pdev)
+{
+	int gpio_nr = bg_ptr->tshut_gpio;
+	int status;
+
+	/* Request for gpio_86 line */
+	status = gpio_request(gpio_nr, "tshut");
+	if (status<  0) {
+		dev_err(bg_ptr->dev,
+			"Could not request for TSHUT GPIO:%i\n", 86);
+		return status;
+	}
+	status = gpio_direction_input(gpio_nr);
+	if (status) {
+		dev_err(bg_ptr->dev,
+			"Cannot set input TSHUT GPIO %d\n", gpio_nr);
+		return status;
+	}
+
+	status = request_irq(gpio_to_irq(gpio_nr),
+			     omap_bandgap_tshut_irq_handler,
+			     IRQF_TRIGGER_RISING, "tshut",
+			     NULL);
+	if (status) {
+		gpio_free(gpio_nr);
+		dev_err(bg_ptr->dev, "request irq failed for TSHUT");
+	}
+
+	return 0;
+}
+
+static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
+				       struct platform_device *pdev)
+{
+	int ret;
+
+	bg_ptr->irq = platform_get_irq(pdev, 0);
+	if (bg_ptr->irq<  0) {
+		dev_err(&pdev->dev, "get_irq failed\n");
+		return bg_ptr->irq;
+	}
+	ret = request_threaded_irq(bg_ptr->irq, NULL,
+				   talert_irq_handler,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   "talert", bg_ptr);
+	if (ret) {
+		dev_err(&pdev->dev, "Request threaded irq failed.\n");
+		return ret;

drivers/thermal/omap-bandgap.c line 1193

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	}
+
+	return 0;
+}
+
+static const struct omap_bandgap_data omap4460_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "bandgap_ts_fclk",
+	.div_ck_name = "div_ts_ck",

None of these clock data should be there ideally. You should ensure that the proper device alias will be there using clkdev entries.

Except that with DT, it will not work without the clock DT binding :-(

I think Rob posted a latest update based on CCF... but for the moment we are stuck :-(

Quoted 25 lines
drivers/thermal/omap-bandgap.c new file +25 -0
+	.conv_table = omap4460_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap4460_mpu_temp_sensor_registers,
+			.ts_data =&omap4460_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+	},
+	.sensor_count = 1,
+};
+
+static const struct omap_bandgap_data omap5430_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "ts_clk_div_ck",
+	.div_ck_name = "ts_clk_div_ck",
+	.conv_table = omap5430_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap5430_mpu_temp_sensor_registers,
+			.ts_data =&omap5430_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+		{
+			.registers =&omap5430_gpu_temp_sensor_registers,

drivers/thermal/omap-bandgap.c line 1228

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+			.ts_data =&omap5430_gpu_temp_sensor_data,
+			.domain = "gpu",
+		},
+		{
+			.registers =&omap5430_core_temp_sensor_registers,
+			.ts_data =&omap5430_core_temp_sensor_data,
+			.domain = "core",
+		},
+	},
+	.sensor_count = 3,

It can probably be replaced by a sizeof.

drivers/thermal/omap-bandgap.c line 1238

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+};
+
+static const struct of_device_id of_omap_bandgap_match[] = {
+	/*
+	 * TODO: Add support to 4430
+	 * { .compatible = "ti,omap4430-bandgap", .data = , },
+	 */
+	{
+		.compatible = "ti,omap4460-bandgap",
+		.data = (void *)&omap4460_data,

No need to cast toward a void *.

Quoted 4 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+	},
+	{
+		.compatible = "ti,omap5430-bandgap",
+		.data = (void *)&omap5430_data,

drivers/thermal/omap-bandgap.c line 1252

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	},
+	/* Sentinel */
+	{ },
+};
+
+static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct omap_bandgap *bg_ptr;

bg_ptr is not a super name.

drivers/thermal/omap-bandgap.c line 1259

Quoted 7 lines
drivers/thermal/omap-bandgap.c new file +7 -0
+	u32 prop;
+
+	/* just for the sake */
+	if (!node) {
+		dev_err(&pdev->dev, "no platform information available\n");
+		return ERR_PTR(-EINVAL);
+	}

Not needed, just do the of_match_device here directly.

drivers/thermal/omap-bandgap.c line 1270

Quoted 11 lines
drivers/thermal/omap-bandgap.c new file +11 -0
+
+	bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
+				    GFP_KERNEL);
+	if (!bg_ptr) {
+		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	of_id = of_match_device(of_omap_bandgap_match,&pdev->dev);
+	if (of_id)
+		bg_ptr->pdata = of_id->data;

Nit: This is not really pdata anymore, so you should maybe remove the "p" to avoid confusion.

Quoted 26 lines
drivers/thermal/omap-bandgap.c new file +26 -0
+
+	if (bg_ptr->pdata->has_tshut) {
+		if (of_property_read_u32(node, "ti,tshut-gpio",&prop)<  0) {
+			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
+			return ERR_PTR(-EINVAL);
+		}
+		bg_ptr->tshut_gpio = prop;
+		if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
+			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
+				bg_ptr->tshut_gpio);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return bg_ptr;
+}
+
+static
+int __devinit omap_bandgap_probe(struct platform_device *pdev)
+{
+	struct device *cdev = pdev->dev.parent;
+	struct omap_bandgap *bg_ptr;
+	int clk_rate, ret = 0, i;
+
+	if (!cdev) {
+		dev_err(&pdev->dev, "no omap control ref in our parent\n");

drivers/thermal/omap-bandgap.c line 1306

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+		return -EINVAL;
+	}
+
+	bg_ptr = omap_bandgap_build(pdev);
+	if (IS_ERR_OR_NULL(bg_ptr)) {
+		dev_err(&pdev->dev, "failed to fetch platform data\n");
+		return PTR_ERR(bg_ptr);
+	}
+
+	if (bg_ptr->pdata->has_talert) {

Nit2: Yeah, in fact instead of pdata, "conf" or "settings" seems to be more representative of what this structure really contain.

Quoted 7 lines
drivers/thermal/omap-bandgap.c new file +7 -0
+		ret = omap_bandgap_talert_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
+			return ret;
+		}
+	}
+

drivers/thermal/omap-bandgap.c line 1323

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	if (bg_ptr->pdata->has_tshut) {
+		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to initialize system tshut IRQ\n");
+			goto free_talert;
+		}
+	}
+
+	bg_ptr->fclock = clk_get(NULL, bg_ptr->pdata->fclock_name);

That's not good to get a clock without using the local dev alias. But because of lack of clock DT binding yet, I'm not sure we have the choice.

Quoted 43 lines
drivers/thermal/omap-bandgap.c new file +43 -0
+	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request fclock reference\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->pdata->div_ck_name);
+	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to request div_ts_ck clock ref\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->conv_table = bg_ptr->pdata->conv_table;
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		u32 val;
+
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		/*
+		 * check if the efuse has a non-zero value if not
+		 * it is an untrimmed sample and the temperatures
+		 * may not be accurate
+		 */
+		ret = omap_control_readl(cdev, tsr->bgap_efuse,&val);
+		if (ret || !val)
+			dev_info(&pdev->dev,
+				 "Non-trimmed BGAP, Temp not accurate\n");
+	}
+
+	clk_rate = clk_round_rate(bg_ptr->div_clk,
+				  bg_ptr->pdata->sensors[0].ts_data->max_freq);
+	if (clk_rate<  bg_ptr->pdata->sensors[0].ts_data->min_freq ||
+	    clk_rate == 0xffffffff) {
+		ret = -ENODEV;
+		goto put_clks;
+	}
+
+	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot set clock rate\n");
+		goto put_clks;

drivers/thermal/omap-bandgap.c line 1376

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	}
+
+	bg_ptr->clk_rate = clk_rate;
+	clk_enable(bg_ptr->fclock);
+
+	mutex_init(&bg_ptr->bg_mutex);
+	bg_ptr->dev =&pdev->dev;
+	platform_set_drvdata(pdev, bg_ptr);
+
+	/* 1 clk cycle */

What does that mean exactly?

Regards,
Benoit

Quoted 294 lines
drivers/thermal/omap-bandgap.c new file +225 -0
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i, 1);
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_data *ts_data;
+
+		ts_data = bg_ptr->pdata->sensors[i].ts_data;
+
+		temp_sensor_init_talert_thresholds(bg_ptr, i,
+						   ts_data->t_hot,
+						   ts_data->t_cold);
+		temp_sensor_configure_tshut_hot(bg_ptr, i,
+						ts_data->tshut_hot);
+		temp_sensor_configure_tshut_cold(bg_ptr, i,
+						 ts_data->tshut_cold);
+	}
+
+	enable_continuous_mode(bg_ptr);
+
+	/* Set .250 seconds time as default counter */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i,
+					      bg_ptr->clk_rate / 4);
+
+	/* Every thing is good? Then expose the sensors */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		char *domain;
+
+		domain = bg_ptr->pdata->sensors[i].domain;
+		if (bg_ptr->pdata->expose_sensor)
+			bg_ptr->pdata->expose_sensor(bg_ptr, i, domain);
+	}
+
+	return 0;
+
+put_clks:
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+free_irqs:
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+free_talert:
+	free_irq(bg_ptr->irq, bg_ptr);
+
+	return ret;
+}
+
+static
+int __devexit omap_bandgap_remove(struct platform_device *pdev)
+{
+	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
+
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+	free_irq(bg_ptr->irq, bg_ptr);
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int err = 0;
+	int i;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,
+					&rval->bg_mode_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_mask_ctrl,
+					&rval->bg_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_counter,
+					&rval->bg_counter);
+		err |= omap_control_readl(cdev, tsr->bgap_threshold,
+					&rval->bg_threshold);
+		err |= omap_control_readl(cdev, tsr->tshut_threshold,
+					&rval->tshut_threshold);
+
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int
+omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp = 0, counter = 1000;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	/* Select single conversion mode */
+	err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,&temp);
+	temp&= ~(1<<  __ffs(tsr->mode_ctrl_mask));
+	omap_control_writel(cdev, temp, tsr->bgap_mode_ctrl);
+
+	/* Start of Conversion = 1 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp |= 1<<  __ffs(tsr->bgap_soc_mask);
+	omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+	/* Wait until DTEMP is updated */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= (tsr->bgap_dtemp_mask);
+	while ((temp == 0)&&  --counter) {
+		err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+		temp&= (tsr->bgap_dtemp_mask);
+	}
+	/* Start of Conversion = 0 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= ~(1<<  __ffs(tsr->bgap_soc_mask));
+	err |= omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int i, err = 0;
+	u32 temp = 0;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+		u32 val;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_counter,&val);
+		if (val == 0) {
+			err |= omap_control_writel(cdev, rval->bg_threshold,
+						   tsr->bgap_threshold);
+			err |= omap_control_writel(cdev, rval->tshut_threshold,
+						   tsr->tshut_threshold);
+			/* Force immediate temperature measurement and update
+			 * of the DTEMP field
+			 */
+			omap_bandgap_force_single_read(bg_ptr, i);
+			err |= omap_control_writel(cdev, rval->bg_counter,
+						   tsr->bgap_counter);
+			err |= omap_control_writel(cdev, rval->bg_mode_ctrl,
+						   tsr->bgap_mode_ctrl);
+			err |= omap_control_writel(cdev, rval->bg_ctrl,
+						   tsr->bgap_mask_ctrl);
+		} else {
+			err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,
+						&temp);
+			temp&= (tsr->bgap_dtemp_mask);
+			if (temp == 0) {
+				omap_bandgap_force_single_read(bg_ptr, i);
+				err |= omap_control_readl(cdev,
+							  tsr->bgap_mask_ctrl,
+							&temp);
+				temp |= 1<<  __ffs(tsr->mode_ctrl_mask);
+				err |= omap_control_writel(cdev, temp,
+							   tsr->bgap_mask_ctrl);
+			}
+		}
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_suspend(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+	int err;
+
+	err = omap_bandgap_save_ctxt(bg_ptr);
+	clk_disable(bg_ptr->fclock);
+
+	return err;
+}
+
+static int omap_bandgap_resume(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+
+	clk_enable(bg_ptr->fclock);
+
+	return omap_bandgap_restore_ctxt(bg_ptr);
+}
+static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
+				omap_bandgap_resume)
+};
+
+#define DEV_PM_OPS	(&omap_bandgap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver omap_bandgap_sensor_driver = {
+	.probe = omap_bandgap_probe,
+	.remove = omap_bandgap_remove,
+	.driver = {
+			.name = "omap-bandgap",
+			.pm = DEV_PM_OPS,
+			.of_match_table	= of_omap_bandgap_match,
+	},
+};
+
+module_platform_driver(omap_bandgap_sensor_driver);
+early_platform_init("early_omap_temperature",&omap_bandgap_sensor_driver);
+
+MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-bandgap");
+MODULE_AUTHOR("Texas Instrument Inc.");
drivers/thermal/omap-bandgap.h new file +63 -0
new file mode 100644
index 0000000..12e0d6b
@@ -0,0 +1,63 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin<[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __OMAP_BANDGAP_H
+#define __OMAP_BANDGAP_H
+
+struct omap_bandgap_data;
+
+/**
+ * struct omap_bandgap - bandgap device structure
+ * @dev: device pointer
+ * @pdata: platform data with sensor data
+ * @fclock: pointer to functional clock of temperature sensor
+ * @div_clk: pointer to parent clock of temperature sensor fclk
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @bg_mutex: Mutex for sysfs, irq and PM
+ * @irq: MPU Irq number for thermal alert
+ * @tshut_gpio: GPIO where Tshut signal is routed
+ * @clk_rate: Holds current clock rate
+ */
+struct omap_bandgap {
+	struct device			*dev;
+	const struct omap_bandgap_data	*pdata;
+	struct clk			*fclock;
+	struct clk			*div_clk;
+	const int			*conv_table;
+	struct mutex			bg_mutex; /* Mutex for irq and PM */
+	int				irq;
+	int				tshut_gpio;
+	u32				clk_rate;
+};
+
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+				      int *interval);
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
+				       u32 interval);
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+				  int *temperature);
+
+#endif
#54 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

In reply to Cousson, Benoit

Hello again,

Quoted 1 line · Cousson Benoit

On 5/25/2012 10:25 AM, Eduardo Valentin wrote:

<big cut>

Quoted 9 lines

drivers/thermal/omap-bandgap.c line 1193

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+
+static const struct omap_bandgap_data omap4460_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "bandgap_ts_fclk",
+	.div_ck_name = "div_ts_ck",

None of these clock data should be there ideally. You should ensure that the proper device alias will be there using clkdev entries.

In fact, it is a shame that it would be needed to have this entries there :-(

Quoted 5 lines

Except that with DT, it will not work without the clock DT binding :-(

I think Rob posted a latest update based on CCF... but for the moment we are stuck :-(

OK. But would it work for BG as well as it seams to be a special case?

Quoted 30 lines
Quoted 30 lines
drivers/thermal/omap-bandgap.c new file +29 -0
+	.conv_table = omap4460_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap4460_mpu_temp_sensor_registers,
+			.ts_data =&omap4460_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+	},
+	.sensor_count = 1,
+};
+
+static const struct omap_bandgap_data omap5430_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "ts_clk_div_ck",
+	.div_ck_name = "ts_clk_div_ck",
+	.conv_table = omap5430_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap5430_mpu_temp_sensor_registers,
+			.ts_data =&omap5430_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+		{
+			.registers =&omap5430_gpu_temp_sensor_registers,
+			.ts_data =&omap5430_gpu_temp_sensor_data,
+			.domain = "gpu",
+		},
+		{
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1228

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+			.registers =&omap5430_core_temp_sensor_registers,
+			.ts_data =&omap5430_core_temp_sensor_data,
+			.domain = "core",
+		},
+	},
+	.sensor_count = 3,

It can probably be replaced by a sizeof.

ARRAY_SIZE prob, will check.

Quoted 13 lines

drivers/thermal/omap-bandgap.c line 1238

Quoted 11 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+};
+
+static const struct of_device_id of_omap_bandgap_match[] = {
+	/*
+	 * TODO: Add support to 4430
+	 * { .compatible = "ti,omap4430-bandgap", .data = , },
+	 */
+	{
+		.compatible = "ti,omap4460-bandgap",
+		.data = (void *)&omap4460_data,

No need to cast toward a void *.

In this case, there is a need, because the omap4460_data is const but the .data field isn't. So I need to force it.

Quoted 17 lines
Quoted 5 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+	},
+	{
+		.compatible = "ti,omap5430-bandgap",
+		.data = (void *)&omap5430_data,

drivers/thermal/omap-bandgap.c line 1252

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	},
+	/* Sentinel */
+	{ },
+};
+
+static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct omap_bandgap *bg_ptr;

bg_ptr is not a super name.

Got a better name? Just don't want a long one to avoid code bending at 80th column...

Quoted 10 lines

drivers/thermal/omap-bandgap.c line 1259

Quoted 8 lines
drivers/thermal/omap-bandgap.c new file +7 -0
+	u32 prop;
+
+	/* just for the sake */
+	if (!node) {
+		dev_err(&pdev->dev, "no platform information available\n");
+		return ERR_PTR(-EINVAL);
+	}

Not needed, just do the of_match_device here directly.

Indeed...

Quoted 15 lines

drivers/thermal/omap-bandgap.c line 1270

Quoted 12 lines
drivers/thermal/omap-bandgap.c new file +11 -0
+
+	bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
+				    GFP_KERNEL);
+	if (!bg_ptr) {
+		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	of_id = of_match_device(of_omap_bandgap_match,&pdev->dev);
+	if (of_id)
+		bg_ptr->pdata = of_id->data;

Nit: This is not really pdata anymore, so you should maybe remove the "p" to avoid confusion.

OK...

Quoted 32 lines
Quoted 32 lines
drivers/thermal/omap-bandgap.c new file +31 -0
+
+	if (bg_ptr->pdata->has_tshut) {
+		if (of_property_read_u32(node, "ti,tshut-gpio",&prop)<  0) {
+			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
+			return ERR_PTR(-EINVAL);
+		}
+		bg_ptr->tshut_gpio = prop;
+		if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
+			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
+				bg_ptr->tshut_gpio);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return bg_ptr;
+}
+
+static
+int __devinit omap_bandgap_probe(struct platform_device *pdev)
+{
+	struct device *cdev = pdev->dev.parent;
+	struct omap_bandgap *bg_ptr;
+	int clk_rate, ret = 0, i;
+
+	if (!cdev) {
+		dev_err(&pdev->dev, "no omap control ref in our parent\n");
+		return -EINVAL;
+	}
+
+	bg_ptr = omap_bandgap_build(pdev);
+	if (IS_ERR_OR_NULL(bg_ptr)) {
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1306

Quoted 5 lines
drivers/thermal/omap-bandgap.c new file +5 -0
+		dev_err(&pdev->dev, "failed to fetch platform data\n");
+		return PTR_ERR(bg_ptr);
+	}
+
+	if (bg_ptr->pdata->has_talert) {

Nit2: Yeah, in fact instead of pdata, "conf" or "settings" seems to be more representative of what this structure really contain.

conf looks good to me.

Quoted 14 lines
Quoted 14 lines
drivers/thermal/omap-bandgap.c new file +13 -0
+		ret = omap_bandgap_talert_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
+			return ret;
+		}
+	}
+
+	if (bg_ptr->pdata->has_tshut) {
+		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to initialize system tshut IRQ\n");
+			goto free_talert;
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1323

Quoted 4 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+		}
+	}
+
+	bg_ptr->fclock = clk_get(NULL, bg_ptr->pdata->fclock_name);

That's not good to get a clock without using the local dev alias. But because of lack of clock DT binding yet, I'm not sure we have the choice.

In fact I didn't touch the clk data on purpose and left the clock handling as is. On my side I didn't know how the clock struct would look like with DT, so, I didn't mess with it.

Do you have a reference to check the work in progress for clock DT ?

Quoted 48 lines
Quoted 48 lines
drivers/thermal/omap-bandgap.c new file +47 -0
+	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request fclock reference\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->pdata->div_ck_name);
+	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to request div_ts_ck clock ref\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->conv_table = bg_ptr->pdata->conv_table;
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		u32 val;
+
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		/*
+		 * check if the efuse has a non-zero value if not
+		 * it is an untrimmed sample and the temperatures
+		 * may not be accurate
+		 */
+		ret = omap_control_readl(cdev, tsr->bgap_efuse,&val);
+		if (ret || !val)
+			dev_info(&pdev->dev,
+				 "Non-trimmed BGAP, Temp not accurate\n");
+	}
+
+	clk_rate = clk_round_rate(bg_ptr->div_clk,
+				  bg_ptr->pdata->sensors[0].ts_data->max_freq);
+	if (clk_rate<  bg_ptr->pdata->sensors[0].ts_data->min_freq ||
+	    clk_rate == 0xffffffff) {
+		ret = -ENODEV;
+		goto put_clks;
+	}
+
+	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot set clock rate\n");
+		goto put_clks;
+	}
+
+	bg_ptr->clk_rate = clk_rate;
+	clk_enable(bg_ptr->fclock);
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1376

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+
+	mutex_init(&bg_ptr->bg_mutex);
+	bg_ptr->dev =&pdev->dev;
+	platform_set_drvdata(pdev, bg_ptr);
+
+	/* 1 clk cycle */

What does that mean exactly?

That's indeed a good question. I guess by default we configure the bandgap to wait only 1 cycle before it goes to the next read round, if in continuous mode.

That should get overwritten when we have, for instance, some policy initialized and changing the update rate based on the temperature level that the sensor is.

These decisions would go under omapXX-thermal.c, BTW. Check my reply on your suggestion for data structure split.

Quoted 290 lines

Regards,
Benoit

Quoted 286 lines
drivers/thermal/omap-bandgap.c new file +225 -0
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i, 1);
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_data *ts_data;
+
+		ts_data = bg_ptr->pdata->sensors[i].ts_data;
+
+		temp_sensor_init_talert_thresholds(bg_ptr, i,
+						   ts_data->t_hot,
+						   ts_data->t_cold);
+		temp_sensor_configure_tshut_hot(bg_ptr, i,
+						ts_data->tshut_hot);
+		temp_sensor_configure_tshut_cold(bg_ptr, i,
+						 ts_data->tshut_cold);
+	}
+
+	enable_continuous_mode(bg_ptr);
+
+	/* Set .250 seconds time as default counter */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i,
+					      bg_ptr->clk_rate / 4);
+
+	/* Every thing is good? Then expose the sensors */
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		char *domain;
+
+		domain = bg_ptr->pdata->sensors[i].domain;
+		if (bg_ptr->pdata->expose_sensor)
+			bg_ptr->pdata->expose_sensor(bg_ptr, i, domain);
+	}
+
+	return 0;
+
+put_clks:
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+free_irqs:
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+free_talert:
+	free_irq(bg_ptr->irq, bg_ptr);
+
+	return ret;
+}
+
+static
+int __devexit omap_bandgap_remove(struct platform_device *pdev)
+{
+	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
+
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+	free_irq(bg_ptr->irq, bg_ptr);
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int err = 0;
+	int i;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,
+					&rval->bg_mode_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_mask_ctrl,
+					&rval->bg_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_counter,
+					&rval->bg_counter);
+		err |= omap_control_readl(cdev, tsr->bgap_threshold,
+					&rval->bg_threshold);
+		err |= omap_control_readl(cdev, tsr->tshut_threshold,
+					&rval->tshut_threshold);
+
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int
+omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp = 0, counter = 1000;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	/* Select single conversion mode */
+	err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,&temp);
+	temp&= ~(1<<  __ffs(tsr->mode_ctrl_mask));
+	omap_control_writel(cdev, temp, tsr->bgap_mode_ctrl);
+
+	/* Start of Conversion = 1 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp |= 1<<  __ffs(tsr->bgap_soc_mask);
+	omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+	/* Wait until DTEMP is updated */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= (tsr->bgap_dtemp_mask);
+	while ((temp == 0)&&  --counter) {
+		err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+		temp&= (tsr->bgap_dtemp_mask);
+	}
+	/* Start of Conversion = 0 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= ~(1<<  __ffs(tsr->bgap_soc_mask));
+	err |= omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int i, err = 0;
+	u32 temp = 0;
+
+	for (i = 0; i<  bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+		u32 val;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_counter,&val);
+		if (val == 0) {
+			err |= omap_control_writel(cdev, rval->bg_threshold,
+						   tsr->bgap_threshold);
+			err |= omap_control_writel(cdev, rval->tshut_threshold,
+						   tsr->tshut_threshold);
+			/* Force immediate temperature measurement and update
+			 * of the DTEMP field
+			 */
+			omap_bandgap_force_single_read(bg_ptr, i);
+			err |= omap_control_writel(cdev, rval->bg_counter,
+						   tsr->bgap_counter);
+			err |= omap_control_writel(cdev, rval->bg_mode_ctrl,
+						   tsr->bgap_mode_ctrl);
+			err |= omap_control_writel(cdev, rval->bg_ctrl,
+						   tsr->bgap_mask_ctrl);
+		} else {
+			err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,
+						&temp);
+			temp&= (tsr->bgap_dtemp_mask);
+			if (temp == 0) {
+				omap_bandgap_force_single_read(bg_ptr, i);
+				err |= omap_control_readl(cdev,
+							  tsr->bgap_mask_ctrl,
+							&temp);
+				temp |= 1<<  __ffs(tsr->mode_ctrl_mask);
+				err |= omap_control_writel(cdev, temp,
+							   tsr->bgap_mask_ctrl);
+			}
+		}
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_suspend(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+	int err;
+
+	err = omap_bandgap_save_ctxt(bg_ptr);
+	clk_disable(bg_ptr->fclock);
+
+	return err;
+}
+
+static int omap_bandgap_resume(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+
+	clk_enable(bg_ptr->fclock);
+
+	return omap_bandgap_restore_ctxt(bg_ptr);
+}
+static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
+				omap_bandgap_resume)
+};
+
+#define DEV_PM_OPS	(&omap_bandgap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver omap_bandgap_sensor_driver = {
+	.probe = omap_bandgap_probe,
+	.remove = omap_bandgap_remove,
+	.driver = {
+			.name = "omap-bandgap",
+			.pm = DEV_PM_OPS,
+			.of_match_table	= of_omap_bandgap_match,
+	},
+};
+
+module_platform_driver(omap_bandgap_sensor_driver);
+early_platform_init("early_omap_temperature",&omap_bandgap_sensor_driver);
+
+MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-bandgap");
+MODULE_AUTHOR("Texas Instrument Inc.");
drivers/thermal/omap-bandgap.h new file +55 -0
new file mode 100644
index 0000000..12e0d6b
@@ -0,0 +1,63 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin<[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __OMAP_BANDGAP_H
+#define __OMAP_BANDGAP_H
+
+struct omap_bandgap_data;
+
+/**
+ * struct omap_bandgap - bandgap device structure
+ * @dev: device pointer
+ * @pdata: platform data with sensor data
+ * @fclock: pointer to functional clock of temperature sensor
+ * @div_clk: pointer to parent clock of temperature sensor fclk
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @bg_mutex: Mutex for sysfs, irq and PM
+ * @irq: MPU Irq number for thermal alert
+ * @tshut_gpio: GPIO where Tshut signal is routed
+ * @clk_rate: Holds current clock rate
+ */
+struct omap_bandgap {
+	struct device			*dev;
+	const struct omap_bandgap_data	*pdata;
+	struct clk			*fclock;
+	struct clk			*div_clk;
+	const int			*conv_table;
+	struct mutex			bg_mutex; /* Mutex for irq and PM */
+	int				irq;
+	int				tshut_gpio;
+	u32				clk_rate;
+};
+
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
Quoted 9 lines

drivers/thermal/omap-bandgap.h line 63

Quoted 8 lines
drivers/thermal/omap-bandgap.h new file +8 -0
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+				      int *interval);
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
+				       u32 interval);
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+				  int *temperature);
+
+#endif

---
Eduardo

#55 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

Quoted 66 lines · Eduardo Valentin

Hello again,

Quoted 1 line · Cousson Benoit

On 5/25/2012 10:25 AM, Eduardo Valentin wrote:

<big cut>

Quoted 9 lines

drivers/thermal/omap-bandgap.c line 1193

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+
+static const struct omap_bandgap_data omap4460_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "bandgap_ts_fclk",
+	.div_ck_name = "div_ts_ck",

None of these clock data should be there ideally. You should ensure that the proper device alias will be there using clkdev entries.

In fact, it is a shame that it would be needed to have this entries there :-(

Quoted 5 lines

Except that with DT, it will not work without the clock DT binding :-(

I think Rob posted a latest update based on CCF... but for the moment we are stuck :-(

OK. But would it work for BG as well as it seams to be a special case?

Quoted 30 lines
Quoted 30 lines
drivers/thermal/omap-bandgap.c new file +29 -0
+	.conv_table = omap4460_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap4460_mpu_temp_sensor_registers,
+			.ts_data =&omap4460_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+	},
+	.sensor_count = 1,
+};
+
+static const struct omap_bandgap_data omap5430_data = {
+	.has_talert = true,
+	.has_tshut = true,
+	.fclock_name = "ts_clk_div_ck",
+	.div_ck_name = "ts_clk_div_ck",
+	.conv_table = omap5430_adc_to_temp,
+	.sensors = {
+		{
+			.registers =&omap5430_mpu_temp_sensor_registers,
+			.ts_data =&omap5430_mpu_temp_sensor_data,
+			.domain = "cpu",
+		},
+		{
+			.registers =&omap5430_gpu_temp_sensor_registers,
+			.ts_data =&omap5430_gpu_temp_sensor_data,
+			.domain = "gpu",
+		},
+		{
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1228

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+			.registers =&omap5430_core_temp_sensor_registers,
+			.ts_data =&omap5430_core_temp_sensor_data,
+			.domain = "core",
+		},
+	},
+	.sensor_count = 3,

It can probably be replaced by a sizeof.

Quoted 1 line

ARRAY_SIZE prob, will check.

Ah, yes, that's one... I was looking for it for forgot the name :-)

Quoted 33 lines
Quoted 4 lines
Quoted 4 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+};
+
+static const struct of_device_id of_omap_bandgap_match[] = {
+	/*
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1238

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+	 * TODO: Add support to 4430
+	 * { .compatible = "ti,omap4430-bandgap", .data = , },
+	 */
+	{
+		.compatible = "ti,omap4460-bandgap",
+		.data = (void *)&omap4460_data,

No need to cast toward a void *.

In this case, there is a need, because the omap4460_data is const but the .data field isn't. So I need to force it.

Quoted 17 lines
Quoted 5 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+	},
+	{
+		.compatible = "ti,omap5430-bandgap",
+		.data = (void *)&omap5430_data,

drivers/thermal/omap-bandgap.c line 1252

Quoted 10 lines
drivers/thermal/omap-bandgap.c new file +10 -0
+	},
+	/* Sentinel */
+	{ },
+};
+
+static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct omap_bandgap *bg_ptr;

bg_ptr is not a super name.

Quoted 1 line

Got a better name? Just don't want a long one to avoid code bending at 80th column...

My concern was mainly with the _ptr, it looks like a Hungarian notation. :-)...

Maybe bg only? Or omap_bg?

Quoted 98 lines
Quoted 11 lines

drivers/thermal/omap-bandgap.c line 1259

Quoted 9 lines
drivers/thermal/omap-bandgap.c new file +7 -0
+	u32 prop;
+
+	/* just for the sake */
+	if (!node) {
+		dev_err(&pdev->dev, "no platform information available\n");
+		return ERR_PTR(-EINVAL);
+	}

Not needed, just do the of_match_device here directly.

Indeed...

Quoted 15 lines

drivers/thermal/omap-bandgap.c line 1270

Quoted 12 lines
drivers/thermal/omap-bandgap.c new file +11 -0
+
+	bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
+				    GFP_KERNEL);
+	if (!bg_ptr) {
+		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	of_id = of_match_device(of_omap_bandgap_match,&pdev->dev);
+	if (of_id)
+		bg_ptr->pdata = of_id->data;

Nit: This is not really pdata anymore, so you should maybe remove the "p" to avoid confusion.

OK...

Quoted 32 lines
Quoted 32 lines
drivers/thermal/omap-bandgap.c new file +31 -0
+
+	if (bg_ptr->pdata->has_tshut) {
+		if (of_property_read_u32(node, "ti,tshut-gpio",&prop)<   0) {
+			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
+			return ERR_PTR(-EINVAL);
+		}
+		bg_ptr->tshut_gpio = prop;
+		if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
+			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
+				bg_ptr->tshut_gpio);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return bg_ptr;
+}
+
+static
+int __devinit omap_bandgap_probe(struct platform_device *pdev)
+{
+	struct device *cdev = pdev->dev.parent;
+	struct omap_bandgap *bg_ptr;
+	int clk_rate, ret = 0, i;
+
+	if (!cdev) {
+		dev_err(&pdev->dev, "no omap control ref in our parent\n");
+		return -EINVAL;
+	}
+
+	bg_ptr = omap_bandgap_build(pdev);
+	if (IS_ERR_OR_NULL(bg_ptr)) {
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1306

Quoted 5 lines
drivers/thermal/omap-bandgap.c new file +5 -0
+		dev_err(&pdev->dev, "failed to fetch platform data\n");
+		return PTR_ERR(bg_ptr);
+	}
+
+	if (bg_ptr->pdata->has_talert) {

Nit2: Yeah, in fact instead of pdata, "conf" or "settings" seems to be more representative of what this structure really contain.

conf looks good to me.

Quoted 14 lines
Quoted 14 lines
drivers/thermal/omap-bandgap.c new file +13 -0
+		ret = omap_bandgap_talert_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
+			return ret;
+		}
+	}
+
+	if (bg_ptr->pdata->has_tshut) {
+		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to initialize system tshut IRQ\n");
+			goto free_talert;
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1323

Quoted 4 lines
drivers/thermal/omap-bandgap.c new file +4 -0
+		}
+	}
+
+	bg_ptr->fclock = clk_get(NULL, bg_ptr->pdata->fclock_name);

That's not good to get a clock without using the local dev alias. But because of lack of clock DT binding yet, I'm not sure we have the choice.

Quoted 5 lines

In fact I didn't touch the clk data on purpose and left the clock handling as is. On my side I didn't know how the clock struct would look like with DT, so, I didn't mess with it.

Do you have a reference to check the work in progress for clock DT ?

Rob sent a pull request, it seems that now it is up to Mike T. :-)

http://lists-archives.com/linux-kernel/27640907-dt-clk-binding-support.html

Quoted 58 lines
Quoted 49 lines
Quoted 49 lines
drivers/thermal/omap-bandgap.c new file +47 -0
+	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request fclock reference\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->pdata->div_ck_name);
+	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to request div_ts_ck clock ref\n");
+		goto free_irqs;
+	}
+
+	bg_ptr->conv_table = bg_ptr->pdata->conv_table;
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		u32 val;
+
+		tsr = bg_ptr->pdata->sensors[i].registers;
+		/*
+		 * check if the efuse has a non-zero value if not
+		 * it is an untrimmed sample and the temperatures
+		 * may not be accurate
+		 */
+		ret = omap_control_readl(cdev, tsr->bgap_efuse,&val);
+		if (ret || !val)
+			dev_info(&pdev->dev,
+				 "Non-trimmed BGAP, Temp not accurate\n");
+	}
+
+	clk_rate = clk_round_rate(bg_ptr->div_clk,
+				  bg_ptr->pdata->sensors[0].ts_data->max_freq);
+	if (clk_rate<   bg_ptr->pdata->sensors[0].ts_data->min_freq ||
+	    clk_rate == 0xffffffff) {
+		ret = -ENODEV;
+		goto put_clks;
+	}
+
+	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot set clock rate\n");
+		goto put_clks;
+	}
+
+	bg_ptr->clk_rate = clk_rate;
+	clk_enable(bg_ptr->fclock);
Quoted 8 lines

drivers/thermal/omap-bandgap.c line 1376

Quoted 6 lines
drivers/thermal/omap-bandgap.c new file +6 -0
+
+	mutex_init(&bg_ptr->bg_mutex);
+	bg_ptr->dev =&pdev->dev;
+	platform_set_drvdata(pdev, bg_ptr);
+
+	/* 1 clk cycle */

What does that mean exactly?

Quoted 2 lines

That's indeed a good question. I guess by default we configure the bandgap to wait only 1 cycle before it goes to the next read round, if in continuous mode.

OK, so some more explanation in that comment are maybe required.

Thanks,
Benoit

Quoted 309 lines

That should get overwritten when we have, for instance, some policy initialized and changing the update rate based on the temperature level that the sensor is.

These decisions would go under omapXX-thermal.c, BTW. Check my reply on your suggestion for data structure split.

Quoted 290 lines

Regards,
Benoit

Quoted 286 lines
drivers/thermal/omap-bandgap.c new file +225 -0
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i, 1);
+
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_data *ts_data;
+
+		ts_data = bg_ptr->pdata->sensors[i].ts_data;
+
+		temp_sensor_init_talert_thresholds(bg_ptr, i,
+						   ts_data->t_hot,
+						   ts_data->t_cold);
+		temp_sensor_configure_tshut_hot(bg_ptr, i,
+						ts_data->tshut_hot);
+		temp_sensor_configure_tshut_cold(bg_ptr, i,
+						 ts_data->tshut_cold);
+	}
+
+	enable_continuous_mode(bg_ptr);
+
+	/* Set .250 seconds time as default counter */
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++)
+		configure_temp_sensor_counter(bg_ptr, i,
+					      bg_ptr->clk_rate / 4);
+
+	/* Every thing is good? Then expose the sensors */
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++) {
+		char *domain;
+
+		domain = bg_ptr->pdata->sensors[i].domain;
+		if (bg_ptr->pdata->expose_sensor)
+			bg_ptr->pdata->expose_sensor(bg_ptr, i, domain);
+	}
+
+	return 0;
+
+put_clks:
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+free_irqs:
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+free_talert:
+	free_irq(bg_ptr->irq, bg_ptr);
+
+	return ret;
+}
+
+static
+int __devexit omap_bandgap_remove(struct platform_device *pdev)
+{
+	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
+
+	clk_disable(bg_ptr->fclock);
+	clk_put(bg_ptr->fclock);
+	clk_put(bg_ptr->div_clk);
+	free_irq(bg_ptr->irq, bg_ptr);
+	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+	gpio_free(bg_ptr->tshut_gpio);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int err = 0;
+	int i;
+
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,
+					&rval->bg_mode_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_mask_ctrl,
+					&rval->bg_ctrl);
+		err |= omap_control_readl(cdev,	tsr->bgap_counter,
+					&rval->bg_counter);
+		err |= omap_control_readl(cdev, tsr->bgap_threshold,
+					&rval->bg_threshold);
+		err |= omap_control_readl(cdev, tsr->tshut_threshold,
+					&rval->tshut_threshold);
+
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int
+omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	struct temp_sensor_registers *tsr;
+	u32 temp = 0, counter = 1000;
+	int err;
+
+	tsr = bg_ptr->pdata->sensors[id].registers;
+	/* Select single conversion mode */
+	err = omap_control_readl(cdev, tsr->bgap_mode_ctrl,&temp);
+	temp&= ~(1<<   __ffs(tsr->mode_ctrl_mask));
+	omap_control_writel(cdev, temp, tsr->bgap_mode_ctrl);
+
+	/* Start of Conversion = 1 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp |= 1<<   __ffs(tsr->bgap_soc_mask);
+	omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+	/* Wait until DTEMP is updated */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= (tsr->bgap_dtemp_mask);
+	while ((temp == 0)&&   --counter) {
+		err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+		temp&= (tsr->bgap_dtemp_mask);
+	}
+	/* Start of Conversion = 0 */
+	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,&temp);
+	temp&= ~(1<<   __ffs(tsr->bgap_soc_mask));
+	err |= omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+{
+	struct device *cdev = bg_ptr->dev->parent;
+	int i, err = 0;
+	u32 temp = 0;
+
+	for (i = 0; i<   bg_ptr->pdata->sensor_count; i++) {
+		struct temp_sensor_registers *tsr;
+		struct temp_sensor_regval *rval;
+		u32 val;
+
+		rval = bg_ptr->pdata->sensors[i].regval;
+		tsr = bg_ptr->pdata->sensors[i].registers;
+
+		err = omap_control_readl(cdev, tsr->bgap_counter,&val);
+		if (val == 0) {
+			err |= omap_control_writel(cdev, rval->bg_threshold,
+						   tsr->bgap_threshold);
+			err |= omap_control_writel(cdev, rval->tshut_threshold,
+						   tsr->tshut_threshold);
+			/* Force immediate temperature measurement and update
+			 * of the DTEMP field
+			 */
+			omap_bandgap_force_single_read(bg_ptr, i);
+			err |= omap_control_writel(cdev, rval->bg_counter,
+						   tsr->bgap_counter);
+			err |= omap_control_writel(cdev, rval->bg_mode_ctrl,
+						   tsr->bgap_mode_ctrl);
+			err |= omap_control_writel(cdev, rval->bg_ctrl,
+						   tsr->bgap_mask_ctrl);
+		} else {
+			err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,
+						&temp);
+			temp&= (tsr->bgap_dtemp_mask);
+			if (temp == 0) {
+				omap_bandgap_force_single_read(bg_ptr, i);
+				err |= omap_control_readl(cdev,
+							  tsr->bgap_mask_ctrl,
+							&temp);
+				temp |= 1<<   __ffs(tsr->mode_ctrl_mask);
+				err |= omap_control_writel(cdev, temp,
+							   tsr->bgap_mask_ctrl);
+			}
+		}
+		if (err)
+			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+	}
+
+	return err ? -EIO : 0;
+}
+
+static int omap_bandgap_suspend(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+	int err;
+
+	err = omap_bandgap_save_ctxt(bg_ptr);
+	clk_disable(bg_ptr->fclock);
+
+	return err;
+}
+
+static int omap_bandgap_resume(struct device *dev)
+{
+	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+
+	clk_enable(bg_ptr->fclock);
+
+	return omap_bandgap_restore_ctxt(bg_ptr);
+}
+static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
+				omap_bandgap_resume)
+};
+
+#define DEV_PM_OPS	(&omap_bandgap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver omap_bandgap_sensor_driver = {
+	.probe = omap_bandgap_probe,
+	.remove = omap_bandgap_remove,
+	.driver = {
+			.name = "omap-bandgap",
+			.pm = DEV_PM_OPS,
+			.of_match_table	= of_omap_bandgap_match,
+	},
+};
+
+module_platform_driver(omap_bandgap_sensor_driver);
+early_platform_init("early_omap_temperature",&omap_bandgap_sensor_driver);
+
+MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-bandgap");
+MODULE_AUTHOR("Texas Instrument Inc.");
drivers/thermal/omap-bandgap.h new file +55 -0
new file mode 100644
index 0000000..12e0d6b
@@ -0,0 +1,63 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin<[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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __OMAP_BANDGAP_H
+#define __OMAP_BANDGAP_H
+
+struct omap_bandgap_data;
+
+/**
+ * struct omap_bandgap - bandgap device structure
+ * @dev: device pointer
+ * @pdata: platform data with sensor data
+ * @fclock: pointer to functional clock of temperature sensor
+ * @div_clk: pointer to parent clock of temperature sensor fclk
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @bg_mutex: Mutex for sysfs, irq and PM
+ * @irq: MPU Irq number for thermal alert
+ * @tshut_gpio: GPIO where Tshut signal is routed
+ * @clk_rate: Holds current clock rate
+ */
+struct omap_bandgap {
+	struct device			*dev;
+	const struct omap_bandgap_data	*pdata;
+	struct clk			*fclock;
+	struct clk			*div_clk;
+	const int			*conv_table;
+	struct mutex			bg_mutex; /* Mutex for irq and PM */
+	int				irq;
+	int				tshut_gpio;
+	u32				clk_rate;
+};
+
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
Quoted 9 lines

drivers/thermal/omap-bandgap.h line 63

Quoted 8 lines
drivers/thermal/omap-bandgap.h new file +8 -0
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+				      int *interval);
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
+				       u32 interval);
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+				  int *temperature);
+
+#endif

---
Eduardo

#56 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

Quoted 11 lines · Benoit
Quoted 5 lines · Eduardo Valentin

In fact I didn't touch the clk data on purpose and left the clock handling as is. On my side I didn't know how the clock struct would look like with DT, so, I didn't mess with it.

Do you have a reference to check the work in progress for clock DT ?

Rob sent a pull request, it seems that now it is up to Mike T. :-)

http://lists-archives.com/linux-kernel/27640907-dt-clk-binding-support.html

Due to the on-going discussion around those patches I haven't pulled yet. If everyone agrees once the dust settles then I'll take them in.

Regards,
Mike

#57 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

In reply to Eduardo Valentin

Hi.

Quoted 17 lines · Eduardo Valentin

In the System Control Module, OMAP supplies a voltage reference and a temperature sensor feature that are gathered in the band gap voltage and temperature sensor (VBGAPTS) module. The band gap provides current and voltage reference for its internal circuits and other analog IP blocks. The analog-to-digital converter (ADC) produces an output value that is proportional to the silicon temperature.

This patch provides a platform driver which expose this feature. It is moduled as a MFD child of the System Control Module core MFD driver.

This driver provides only APIs to access the device properties, like temperature, thresholds and update rate.

Quoted 12 lines
---
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 drivers/thermal/Kconfig                            |   13 +
 drivers/thermal/Makefile                           |    4 +-
 drivers/thermal/omap-bandgap.c                     | 1601 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   63 +
 5 files changed, 1707 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h

Add private spin lock in omap-bandgap driver to prevent blocking of control module general registers access.
I wasn't able to test - I have panda 4430 board.

TODO:
Prevent over-usage of spin_lock/spin_unlock for sequential calls of bg_writel().

drivers/mfd/omap-control-core.c +17 -1
Index: omap-thermal/drivers/mfd/omap-control-core.c
===================================================================
@@ -67,6 +67,19 @@ EXPORT_SYMBOL_GPL(omap_control_readl);
 int omap_control_writel(struct device *dev, u32 val, u32 reg)
 {
 	struct omap_control *omap_control = dev_get_drvdata(dev);
+
+	if (!omap_control)
+		return -EINVAL;
+
+	writel(val, omap_control->base + reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+int omap_control_lock_writel(struct device *dev, u32 val, u32 reg)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
 	unsigned long flags;
 
 	if (!omap_control)
@@ -78,7 +91,7 @@ int omap_control_writel(struct device *d
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(omap_control_writel);
+EXPORT_SYMBOL_GPL(omap_control_lock_writel);
 
 /**
  * omap_control_get: returns the control module device pinter
@@ -136,6 +149,9 @@ static int __devinit omap_control_probe(
 	struct device_node *np = dev->of_node;
 	struct omap_control *omap_control;
 
+	printk("\n\t\t **** omap_control_probe(): enter ");
+	dump_stack();
+
 	omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
 	if (!omap_control) {
 		dev_err(dev, "not enough memory for omap_control\n");
drivers/thermal/omap-bandgap.c +43 -28

199 lines not on this page · raw message

drivers/usb/otg/omap4-usb-phy.c +3 -3
Index: omap-thermal/drivers/usb/otg/omap4-usb-phy.c
===================================================================
@@ -46,13 +46,13 @@ int omap4_usb_phy_power(struct device *d
 	if (on) {
 		ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
 		if (!ret && (val & PHY_PD)) {
-			ret = omap_control_writel(dev, ~PHY_PD,
+			ret = omap_control_lock_writel(dev, ~PHY_PD,
 						  CONTROL_DEV_CONF);
 			/* XXX: add proper documentation for this delay */
 			mdelay(200);
 		}
 	} else {
-		ret = omap_control_writel(dev, PHY_PD, CONTROL_DEV_CONF);
+		ret = omap_control_lock_writel(dev, PHY_PD, CONTROL_DEV_CONF);
 	}
 
 	return ret;
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(omap4_usb_phy_power);
  */
 int omap4_usb_phy_mailbox(struct device *dev, u32 val)
 {
-	return omap_control_writel(dev, val, CONTROL_USBOTGHS_CONTROL);
+	return omap_control_lock_writel(dev, val, CONTROL_USBOTGHS_CONTROL);
 }
 EXPORT_SYMBOL_GPL(omap4_usb_phy_mailbox);
 
include/linux/mfd/omap_control.h +6 -0
Index: omap-thermal/include/linux/mfd/omap_control.h
===================================================================
@@ -43,6 +43,7 @@ struct omap_control {
 #ifdef CONFIG_MFD_OMAP_CONTROL
 extern int omap_control_readl(struct device *dev, u32 reg, u32 *val);
 extern int omap_control_writel(struct device *dev, u32 val, u32 reg);
+extern int omap_control_lock_writel(struct device *dev, u32 val, u32 reg);
 extern struct device *omap_control_get(void);
 extern void omap_control_put(struct device *dev);
 #else
@@ -55,6 +56,11 @@ static inline int omap_control_writel(st
 {
 	return 0;
 }
+
+static inline int omap_control_lock_writel(struct device *dev, u32 val, u32 reg)
+{
+	return 0;
+}
 
 static inline struct device *omap_control_get(void)
 {
#58 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

Hello Konstantin,

Quoted 31 lines · Konstantin Baydarov

Hi.

Quoted 17 lines · Eduardo Valentin

In the System Control Module, OMAP supplies a voltage reference and a temperature sensor feature that are gathered in the band gap voltage and temperature sensor (VBGAPTS) module. The band gap provides current and voltage reference for its internal circuits and other analog IP blocks. The analog-to-digital converter (ADC) produces an output value that is proportional to the silicon temperature.

This patch provides a platform driver which expose this feature. It is moduled as a MFD child of the System Control Module core MFD driver.

This driver provides only APIs to access the device properties, like temperature, thresholds and update rate.

Quoted 12 lines
---
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 drivers/thermal/Kconfig                            |   13 +
 drivers/thermal/Makefile                           |    4 +-
 drivers/thermal/omap-bandgap.c                     | 1601 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   63 +
 5 files changed, 1707 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h
Quoted 2 lines

Add private spin lock in omap-bandgap driver to prevent blocking of control module general registers access.

Thanks for sending this out. I will rethink these drivers wrt to locking and will your proposal.

Quoted 1 line

I wasn't able to test - I have panda 4430 board.

Right, we definetly need to have it probing on 4430, I will check how we can close on that.

Quoted 4 lines

TODO:
Prevent over-usage of spin_lock/spin_unlock for sequential calls of bg_writel().

OK...

Quoted 51 lines

Index: omap-thermal/drivers/mfd/omap-control-core.c
===================================================================

drivers/mfd/omap-control-core.c +17 -1
@@ -67,6 +67,19 @@ EXPORT_SYMBOL_GPL(omap_control_readl);
 int omap_control_writel(struct device *dev, u32 val, u32 reg)
 {
 	struct omap_control *omap_control = dev_get_drvdata(dev);
+
+	if (!omap_control)
+		return -EINVAL;
+
+	writel(val, omap_control->base + reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_control_writel);
+
+int omap_control_lock_writel(struct device *dev, u32 val, u32 reg)
+{
+	struct omap_control *omap_control = dev_get_drvdata(dev);
 	unsigned long flags;
 
 	if (!omap_control)
@@ -78,7 +91,7 @@ int omap_control_writel(struct device *d
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(omap_control_writel);
+EXPORT_SYMBOL_GPL(omap_control_lock_writel);
 
 /**
  * omap_control_get: returns the control module device pinter
@@ -136,6 +149,9 @@ static int __devinit omap_control_probe(
 	struct device_node *np = dev->of_node;
 	struct omap_control *omap_control;
 
+	printk("\n\t\t **** omap_control_probe(): enter ");
+	dump_stack();
+
 	omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
 	if (!omap_control) {
 		dev_err(dev, "not enough memory for omap_control\n");

Index: omap-thermal/drivers/thermal/omap-bandgap.c
===================================================================

drivers/thermal/omap-bandgap.c struct temp_sensor_registers { · line 157

Quoted 4 lines
drivers/thermal/omap-bandgap.c +1 -0
@@ -154,6 +154,7 @@ struct temp_sensor_registers {
 	u32	status_cold_mask;
 
 	u32	bgap_efuse;
+	spinlock_t	bg_reg_lock;

Indeed. I agree we should have this per sensor. Need to revisit the existing mutex as well though.

Quoted 5 lines
drivers/thermal/omap-bandgap.c +0 -0
 };
 
 /**
@@ -579,6 +580,17 @@ omap5430_adc_to_temp[OMAP5430_ADC_END_VA
 	124600, 124900, 125000, 125000, 125000, 125000,

drivers/thermal/omap-bandgap.c omap5430_adc_to_temp[OMAP5430_ADC_END_VA · line 590

Quoted 10 lines
drivers/thermal/omap-bandgap.c +8 -0
 };
 
+static int bg_writel(struct device *dev, u32 val, u32 reg, spinlock_t *lock)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(lock, flags);
+	ret = omap_control_writel(dev, val, reg);
+	spin_unlock_irqrestore(lock, flags);

In fact this doesn't help much in the bulk writes case. As you have already mentioned, ideally we should lock, perform the operation, then unlock, instead of several lock/write/unlock sequences.

Quoted 252 lines
drivers/thermal/omap-bandgap.c +34 -28
+	return ret;
+}
+
 static irqreturn_t talert_irq_handler(int irq, void *data)
 {
 	struct omap_bandgap *bg_ptr = data;
@@ -615,7 +627,7 @@ static irqreturn_t talert_irq_handler(in
 			ctrl |= tsr->mask_hot_mask;
 		}
 
-		r |= omap_control_writel(cdev, ctrl, tsr->bgap_mask_ctrl);
+		r |= bg_writel(cdev, ctrl, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
 
 		if (r) {
 			dev_err(bg_ptr->dev, "failed to ack talert interrupt\n");
@@ -705,7 +717,7 @@ static int temp_sensor_unmask_interrupts
 		reg_val |= tsr->mask_cold_mask;
 	else
 		reg_val &= ~tsr->mask_cold_mask;
-	err |= omap_control_writel(cdev, reg_val, tsr->bgap_mask_ctrl);
+	err |= bg_writel(cdev, reg_val, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
 
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to unmask interrupts\n");
@@ -751,14 +763,14 @@ int temp_sensor_configure_thot(struct om
 		/* write the new t_cold value */
 		reg_val = thresh_val & (~tsr->threshold_tcold_mask);
 		reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
-		err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+		err |= bg_writel(cdev, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
 		thresh_val = reg_val;
 	}
 
 	/* write the new t_hot value */
 	reg_val = thresh_val & ~tsr->threshold_thot_mask;
 	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
-	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	err |= bg_writel(cdev, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
 		return -EIO;
@@ -782,7 +794,7 @@ int temp_sensor_init_talert_thresholds(s
 	/* write the new t_cold value */
 	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
 	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
-	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	err |= bg_writel(cdev, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
 		return -EIO;
@@ -793,7 +805,7 @@ int temp_sensor_init_talert_thresholds(s
 	/* write the new t_hot value */
 	reg_val = thresh_val & ~tsr->threshold_thot_mask;
 	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
-	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	err |= bg_writel(cdev, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
 		return -EIO;
@@ -802,7 +814,7 @@ int temp_sensor_init_talert_thresholds(s
 	err = omap_control_readl(cdev, tsr->bgap_mask_ctrl, &reg_val);
 	reg_val |= tsr->mask_hot_mask;
 	reg_val |= tsr->mask_cold_mask;
-	err |= omap_control_writel(cdev, reg_val, tsr->bgap_mask_ctrl);
+	err |= bg_writel(cdev, reg_val, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
 		return -EIO;
@@ -833,14 +845,14 @@ int temp_sensor_configure_tcold(struct o
 		/* write the new t_hot value */
 		reg_val = thresh_val & (~tsr->threshold_thot_mask);
 		reg_val |= hot << __ffs(tsr->threshold_thot_mask);
-		err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+		err |= bg_writel(cdev, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
 		thresh_val = reg_val;
 	}
 
 	/* write the new t_cold value */
 	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
 	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
-	err |= omap_control_writel(cdev, reg_val, tsr->bgap_threshold);
+	err |= bg_writel(cdev, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
 		return -EIO;
@@ -861,7 +873,7 @@ static int temp_sensor_configure_tshut_h
 	err = omap_control_readl(cdev, tsr->tshut_threshold, &reg_val);
 	reg_val &= ~tsr->tshut_hot_mask;
 	reg_val |= tshut_hot << __ffs(tsr->tshut_hot_mask);
-	err |= omap_control_writel(cdev, reg_val, tsr->tshut_threshold);
+	err |= bg_writel(cdev, reg_val, tsr->tshut_threshold, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram tshut thot\n");
 		return -EIO;
@@ -882,7 +894,7 @@ static int temp_sensor_configure_tshut_c
 	err = omap_control_readl(cdev, tsr->tshut_threshold, &reg_val);
 	reg_val &= ~tsr->tshut_cold_mask;
 	reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask);
-	err |= omap_control_writel(cdev, reg_val, tsr->tshut_threshold);
+	err |= bg_writel(cdev, reg_val, tsr->tshut_threshold, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
 		return -EIO;
@@ -903,7 +915,7 @@ static int configure_temp_sensor_counter
 	err = omap_control_readl(cdev, tsr->bgap_counter, &val);
 	val &= ~tsr->counter_mask;
 	val |= counter << __ffs(tsr->counter_mask);
-	err |= omap_control_writel(cdev, val, tsr->bgap_counter);
+	err |= bg_writel(cdev, val, tsr->bgap_counter, &tsr->bg_reg_lock);
 	if (err) {
 		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
 		return -EIO;
@@ -1124,7 +1136,7 @@ static int enable_continuous_mode(struct
 		tsr = bg_ptr->pdata->sensors[i].registers;
 		r = omap_control_readl(cdev, tsr->bgap_mode_ctrl, &val);
 		val |= 1 << __ffs(tsr->mode_ctrl_mask);
-		r |= omap_control_writel(cdev, val, tsr->bgap_mode_ctrl);
+		r |= bg_writel(cdev, val, tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
 		if (r)
 			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
 	}
@@ -1342,6 +1354,9 @@ int __devinit omap_bandgap_probe(struct
 		u32 val;
 
 		tsr = bg_ptr->pdata->sensors[i].registers;
+		/* Initialize register lock */
+		spin_lock_init(&tsr->bg_reg_lock);
+
 		/*
 		 * check if the efuse has a non-zero value if not
 		 * it is an untrimmed sample and the temperatures
@@ -1482,12 +1497,12 @@ omap_bandgap_force_single_read(struct om
 	/* Select single conversion mode */
 	err = omap_control_readl(cdev, tsr->bgap_mode_ctrl, &temp);
 	temp &= ~(1 << __ffs(tsr->mode_ctrl_mask));
-	omap_control_writel(cdev, temp, tsr->bgap_mode_ctrl);
+	bg_writel(cdev, temp, tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
 
 	/* Start of Conversion = 1 */
 	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl, &temp);
 	temp |= 1 << __ffs(tsr->bgap_soc_mask);
-	omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+	bg_writel(cdev, temp, tsr->temp_sensor_ctrl, &tsr->bg_reg_lock);
 	/* Wait until DTEMP is updated */
 	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl, &temp);
 	temp &= (tsr->bgap_dtemp_mask);
@@ -1498,7 +1513,7 @@ omap_bandgap_force_single_read(struct om
 	/* Start of Conversion = 0 */
 	err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl, &temp);
 	temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
-	err |= omap_control_writel(cdev, temp, tsr->temp_sensor_ctrl);
+	err |= bg_writel(cdev, temp, tsr->temp_sensor_ctrl, &tsr->bg_reg_lock);
 
 	return err ? -EIO : 0;
 }
@@ -1519,20 +1534,20 @@ static int omap_bandgap_restore_ctxt(str
 
 		err = omap_control_readl(cdev, tsr->bgap_counter, &val);
 		if (val == 0) {
-			err |= omap_control_writel(cdev, rval->bg_threshold,
-						   tsr->bgap_threshold);
-			err |= omap_control_writel(cdev, rval->tshut_threshold,
-						   tsr->tshut_threshold);
+			err |= bg_writel(cdev, rval->bg_threshold,
+						   tsr->bgap_threshold, &tsr->bg_reg_lock);
+			err |= bg_writel(cdev, rval->tshut_threshold,
+						   tsr->tshut_threshold, &tsr->bg_reg_lock);
 			/* Force immediate temperature measurement and update
 			 * of the DTEMP field
 			 */
 			omap_bandgap_force_single_read(bg_ptr, i);
-			err |= omap_control_writel(cdev, rval->bg_counter,
-						   tsr->bgap_counter);
-			err |= omap_control_writel(cdev, rval->bg_mode_ctrl,
-						   tsr->bgap_mode_ctrl);
-			err |= omap_control_writel(cdev, rval->bg_ctrl,
-						   tsr->bgap_mask_ctrl);
+			err |= bg_writel(cdev, rval->bg_counter,
+						   tsr->bgap_counter, &tsr->bg_reg_lock);
+			err |= bg_writel(cdev, rval->bg_mode_ctrl,
+						   tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
+			err |= bg_writel(cdev, rval->bg_ctrl,
+						   tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
 		} else {
 			err |= omap_control_readl(cdev, tsr->temp_sensor_ctrl,
 						 &temp);
@@ -1543,8 +1558,8 @@ static int omap_bandgap_restore_ctxt(str
 							  tsr->bgap_mask_ctrl,
 							  &temp);
 				temp |= 1 << __ffs(tsr->mode_ctrl_mask);
-				err |= omap_control_writel(cdev, temp,
-							   tsr->bgap_mask_ctrl);
+				err |= bg_writel(cdev, temp,
+							   tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
 			}
 		}
 		if (err)

Index: omap-thermal/drivers/usb/otg/omap4-usb-phy.c
===================================================================

drivers/usb/otg/omap4-usb-phy.c +3 -3
@@ -46,13 +46,13 @@ int omap4_usb_phy_power(struct device *d
 	if (on) {
 		ret = omap_control_readl(dev, CONTROL_DEV_CONF, &val);
 		if (!ret && (val & PHY_PD)) {
-			ret = omap_control_writel(dev, ~PHY_PD,
+			ret = omap_control_lock_writel(dev, ~PHY_PD,
 						  CONTROL_DEV_CONF);
 			/* XXX: add proper documentation for this delay */
 			mdelay(200);
 		}
 	} else {
-		ret = omap_control_writel(dev, PHY_PD, CONTROL_DEV_CONF);
+		ret = omap_control_lock_writel(dev, PHY_PD, CONTROL_DEV_CONF);
 	}
 
 	return ret;
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(omap4_usb_phy_power);
  */
 int omap4_usb_phy_mailbox(struct device *dev, u32 val)
 {
-	return omap_control_writel(dev, val, CONTROL_USBOTGHS_CONTROL);
+	return omap_control_lock_writel(dev, val, CONTROL_USBOTGHS_CONTROL);
 }
 EXPORT_SYMBOL_GPL(omap4_usb_phy_mailbox);
 

Index: omap-thermal/include/linux/mfd/omap_control.h
===================================================================

include/linux/mfd/omap_control.h +6 -0
@@ -43,6 +43,7 @@ struct omap_control {
 #ifdef CONFIG_MFD_OMAP_CONTROL
 extern int omap_control_readl(struct device *dev, u32 reg, u32 *val);
 extern int omap_control_writel(struct device *dev, u32 val, u32 reg);
+extern int omap_control_lock_writel(struct device *dev, u32 val, u32 reg);
 extern struct device *omap_control_get(void);
 extern void omap_control_put(struct device *dev);
 #else
@@ -55,6 +56,11 @@ static inline int omap_control_writel(st
 {
 	return 0;
 }
+
+static inline int omap_control_lock_writel(struct device *dev, u32 val, u32 reg)
+{
+	return 0;
+}
 
 static inline struct device *omap_control_get(void)
 {
maintainer
#59 lore raw

RFC PATCH 9/11 ARM: OMAP4+: thermal: introduce bandgap temperature sensor

In reply to Eduardo Valentin
Quoted 8 lines · Eduardo Valentin

In the System Control Module, OMAP supplies a voltage reference and a temperature sensor feature that are gathered in the band gap voltage and temperature sensor (VBGAPTS) module. The band gap provides current and voltage reference for its internal circuits and other analog IP blocks. The analog-to-digital converter (ADC) produces an output value that is proportional to the silicon temperature.

Quoted 6 lines

This patch provides a platform driver which expose this feature. It is moduled as a MFD child of the System Control Module core MFD driver.

This driver provides only APIs to access the device properties, like temperature, thresholds and update rate.

Here too you a better long term solution is probably to ioremap the temp sensor registers for the driver. That way alloc_mem_region() provides some checks so the driver won't stomp over other registers.

If you need to use omap_ctrl_read/write here, then we should at least clearly understand and document why it needs to be done that way instead of following standard ioremap + readl/writel.

Regards,

Tony

#60 lore raw

RFC PATCH 10/11 omap4: thermal: add basic CPU thermal zone

In reply to Eduardo Valentin

This patch exposes OMAP4 thermal sensor as a thermal zone named "cpu". Only thermal creation is done here.

TODO:

- Add cooling bindings
- Add extrapolation rules

---
 drivers/thermal/Kconfig         |   12 ++++++
 drivers/thermal/Makefile        |    1 +
 drivers/thermal/omap-bandgap.c  |    1 +
 drivers/thermal/omap-bandgap.h  |   12 ++++++
 drivers/thermal/omap4-thermal.c |   72 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 98 insertions(+), 0 deletions(-)
 create mode 100644 drivers/thermal/omap4-thermal.c
drivers/thermal/Kconfig +12 -0
index ffdd240..2e82797 100644
@@ -39,3 +39,15 @@ config OMAP_BANDGAP
 	  This includes alert interrupts generation and also the TSHUT
 	  support.
 
+config OMAP4_THERMAL
+	bool "Texas Instruments OMAP4 thermal support"
+	depends on OMAP_BANDGAP
+	depends on ARCH_OMAP4
+	help
+	  If you say yes here you get thermal support for the Texas Instruments
+	  OMAP4 SoC family. The current chip supported are:
+	   - OMAP4460
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
+
drivers/thermal/Makefile +1 -0
index 5ff1af1..6397678 100644
@@ -6,3 +6,4 @@ obj-$(CONFIG_THERMAL)		+= thermal_sys.o
 obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
 obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal.o
 omap-thermal-y			:= omap-bandgap.o
+omap-thermal-$(CONFIG_OMAP4_THERMAL)	+= omap4-thermal.o
drivers/thermal/omap-bandgap.c +1 -0
index 3d5a12b..d53ffcf 100644
@@ -1192,6 +1192,7 @@ static const struct omap_bandgap_data omap4460_data = {
 	.fclock_name = "bandgap_ts_fclk",
 	.div_ck_name = "div_ts_ck",
 	.conv_table = omap4460_adc_to_temp,
+	.expose_sensor = omap4_thermal_expose_sensor,
 	.sensors = {
 		{
 			.registers = &omap4460_mpu_temp_sensor_registers,
drivers/thermal/omap-bandgap.h +12 -0
index 12e0d6b..0f5b3e6 100644
@@ -60,4 +60,16 @@ int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
 int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
 				  int *temperature);
 
+#ifdef CONFIG_OMAP4_THERMAL
+int omap4_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
+				char *domain);
+#else
+static inline int omap4_thermal_expose_sensor(struct omap_bandgap *bg_ptr,
+					      int id, char *domain)
+{
+	return 0;
+}
+
+#endif
+
 #endif
drivers/thermal/omap4-thermal.c new file +72 -0

72 lines not on this page · raw message

Signature · 1 line
1.7.7.1.488.ge8e1c
#61 lore raw

RFC PATCH 10/11 omap4: thermal: add basic CPU thermal zone

Quoted 26 lines · Eduardo Valentin

This patch exposes OMAP4 thermal sensor as a thermal zone named "cpu". Only thermal creation is done here.

TODO:

?- Add cooling bindings
?- Add extrapolation rules

---

?drivers/thermal/Kconfig ? ? ? ? | ? 12 ++++++
?drivers/thermal/Makefile ? ? ? ?| ? ?1 +
?drivers/thermal/omap-bandgap.c ?| ? ?1 +
?drivers/thermal/omap-bandgap.h ?| ? 12 ++++++
?drivers/thermal/omap4-thermal.c | ? 72 +++++++++++++++++++++++++++++++++++++++

?5 files changed, 98 insertions(+), 0 deletions(-) ?create mode 100644 drivers/thermal/omap4-thermal.c

drivers/thermal/Kconfig +0 -0
index ffdd240..2e82797 100644
@@ -39,3 +39,15 @@ config OMAP_BANDGAP

? ? ? ? ?This includes alert interrupts generation and also the TSHUT ? ? ? ? ?support.

drivers/thermal/Kconfig

Quoted 9 lines
drivers/thermal/Kconfig +9 -0
+config OMAP4_THERMAL
+ ? ? ? bool "Texas Instruments OMAP4 thermal support"
+ ? ? ? depends on OMAP_BANDGAP
+ ? ? ? depends on ARCH_OMAP4
+ ? ? ? help
+ ? ? ? ? If you say yes here you get thermal support for the Texas Instruments
+ ? ? ? ? OMAP4 SoC family. The current chip supported are:
+ ? ? ? ? ?- OMAP4460
+

It's more of IP feature than OMAP specific, so something like

config HAVE_BANDGAP_THERMAL_SUPPORT

and then let processor's which support enable it. That OMAP varients in AMXX etc if needed can make use of it.

If you agree, then rest of the driver also can be cleaned to avoid omap_* in file names and variables.

Apart from this minor comment, rest of the patch looks fine to me.

Regards
Santosh

#62 lore raw

RFC PATCH 10/11 omap4: thermal: add basic CPU thermal zone

Hi,

Quoted 39 lines · Santosh
Quoted 26 lines · Eduardo Valentin

This patch exposes OMAP4 thermal sensor as a thermal zone named "cpu". Only thermal creation is done here.

TODO:

?- Add cooling bindings
?- Add extrapolation rules

---

?drivers/thermal/Kconfig ? ? ? ? | ? 12 ++++++
?drivers/thermal/Makefile ? ? ? ?| ? ?1 +
?drivers/thermal/omap-bandgap.c ?| ? ?1 +
?drivers/thermal/omap-bandgap.h ?| ? 12 ++++++
?drivers/thermal/omap4-thermal.c | ? 72 +++++++++++++++++++++++++++++++++++++++

?5 files changed, 98 insertions(+), 0 deletions(-) ?create mode 100644 drivers/thermal/omap4-thermal.c

drivers/thermal/Kconfig +0 -0
index ffdd240..2e82797 100644
@@ -39,3 +39,15 @@ config OMAP_BANDGAP

? ? ? ? ?This includes alert interrupts generation and also the TSHUT ? ? ? ? ?support.

drivers/thermal/Kconfig

Quoted 9 lines
drivers/thermal/Kconfig +9 -0
+config OMAP4_THERMAL
+ ? ? ? bool "Texas Instruments OMAP4 thermal support"
+ ? ? ? depends on OMAP_BANDGAP
+ ? ? ? depends on ARCH_OMAP4
+ ? ? ? help
+ ? ? ? ? If you say yes here you get thermal support for the Texas Instruments
+ ? ? ? ? OMAP4 SoC family. The current chip supported are:
+ ? ? ? ? ?- OMAP4460
+

It's more of IP feature than OMAP specific, so something like

Quoted 4 lines

config HAVE_BANDGAP_THERMAL_SUPPORT

and then let processor's which support enable it. That OMAP varients in AMXX etc if needed can make use of it.

Those are just an OMAP in disguise.

Quoted 4 lines

If you agree, then rest of the driver also can be cleaned to avoid omap_* in file names and variables.

Apart from this minor comment, rest of the patch looks fine to me.

Then it will appear as a fully generic bandgap driver, which is not the case. This is really a TI thing, right ?

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/20120528/077cf771/attachment-0001.sig>
#63 lore raw

RFC PATCH 10/11 omap4: thermal: add basic CPU thermal zone

Hello Santosh,

Quoted 49 lines · Felipe Balbi

Hi,

Quoted 39 lines · Santosh
Quoted 26 lines · Eduardo Valentin

This patch exposes OMAP4 thermal sensor as a thermal zone named "cpu". Only thermal creation is done here.

TODO:

?- Add cooling bindings
?- Add extrapolation rules

---

?drivers/thermal/Kconfig ? ? ? ? | ? 12 ++++++
?drivers/thermal/Makefile ? ? ? ?| ? ?1 +
?drivers/thermal/omap-bandgap.c ?| ? ?1 +
?drivers/thermal/omap-bandgap.h ?| ? 12 ++++++
?drivers/thermal/omap4-thermal.c | ? 72 +++++++++++++++++++++++++++++++++++++++

?5 files changed, 98 insertions(+), 0 deletions(-) ?create mode 100644 drivers/thermal/omap4-thermal.c

drivers/thermal/Kconfig +0 -0
index ffdd240..2e82797 100644
@@ -39,3 +39,15 @@ config OMAP_BANDGAP

? ? ? ? ?This includes alert interrupts generation and also the TSHUT ? ? ? ? ?support.

drivers/thermal/Kconfig

Quoted 9 lines
drivers/thermal/Kconfig +9 -0
+config OMAP4_THERMAL
+ ? ? ? bool "Texas Instruments OMAP4 thermal support"
+ ? ? ? depends on OMAP_BANDGAP
+ ? ? ? depends on ARCH_OMAP4
+ ? ? ? help
+ ? ? ? ? If you say yes here you get thermal support for the Texas Instruments
+ ? ? ? ? OMAP4 SoC family. The current chip supported are:
+ ? ? ? ? ?- OMAP4460
+

It's more of IP feature than OMAP specific, so something like

Quoted 4 lines

config ?HAVE_BANDGAP_THERMAL_SUPPORT

and then let processor's which support enable it. That OMAP varients in AMXX etc if needed can make use of it.

Those are just an OMAP in disguise.

Quoted 7 lines
Quoted 4 lines

If you agree, then rest of the driver also can be cleaned to avoid omap_* in file names and variables.

Apart from this minor comment, rest of the patch looks fine to me.

Then it will appear as a fully generic bandgap driver, which is not the case. This is really a TI thing, right ?

I have to agree with Felipe here. I do see your point to have a name which is applicable to AMxx, but having such generic naming is not helping either :-( as this bandgap driver is not supposed to be generic.

I though of "ti_bandgap.*", but still seams to be misleading..

I guess same applies to usb_phy and scm.

Again, if you have a name that fits better I won't hesitate to use it :-)

Quoted 3 lines

--
balbi

Signature · 1 line
Eduardo Valentin
#64 lore raw

RFC PATCH 10/11 omap4: thermal: add basic CPU thermal zone

Quoted 60 lines · Eduardo

Hello Santosh,

Quoted 49 lines · Felipe Balbi

Hi,

Quoted 39 lines · Santosh
Quoted 25 lines · Eduardo Valentin

This patch exposes OMAP4 thermal sensor as a thermal zone named "cpu". Only thermal creation is done here.

TODO:

- Add cooling bindings
- Add extrapolation rules

---
  drivers/thermal/Kconfig         |   12 ++++++
  drivers/thermal/Makefile        |    1 +
  drivers/thermal/omap-bandgap.c  |    1 +
  drivers/thermal/omap-bandgap.h  |   12 ++++++
  drivers/thermal/omap4-thermal.c |   72 +++++++++++++++++++++++++++++++++++++++
  5 files changed, 98 insertions(+), 0 deletions(-)

create mode 100644 drivers/thermal/omap4-thermal.c

drivers/thermal/Kconfig +0 -0
index ffdd240..2e82797 100644
@@ -39,3 +39,15 @@ config OMAP_BANDGAP
          This includes alert interrupts generation and also the TSHUT
          support.

drivers/thermal/Kconfig config OMAP_BANDGAP · line 50

Quoted 10 lines
drivers/thermal/Kconfig +9 -0
 
+config OMAP4_THERMAL
+       bool "Texas Instruments OMAP4 thermal support"
+       depends on OMAP_BANDGAP
+       depends on ARCH_OMAP4
+       help
+         If you say yes here you get thermal support for the Texas Instruments
+         OMAP4 SoC family. The current chip supported are:
+          - OMAP4460
+

It's more of IP feature than OMAP specific, so something like

Quoted 4 lines

config HAVE_BANDGAP_THERMAL_SUPPORT

and then let processor's which support enable it. That OMAP varients in AMXX etc if needed can make use of it.

Those are just an OMAP in disguise.

Quoted 7 lines
Quoted 4 lines

If you agree, then rest of the driver also can be cleaned to avoid omap_* in file names and variables.

Apart from this minor comment, rest of the patch looks fine to me.

Then it will appear as a fully generic bandgap driver, which is not the case. This is really a TI thing, right ?

Quoted 6 lines

I have to agree with Felipe here. I do see your point to have a name which is applicable to AMxx, but having such generic naming is not helping either :-( as this bandgap driver is not supposed to be generic.

I though of "ti_bandgap.*", but still seams to be misleading..

Yeah, I guess omap_bandgap is good enough. This issues is mainly due to the version in OMAP4 for my point of view.

Benoit

#65 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

In reply to Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

---
 arch/arm/boot/dts/omap4.dtsi |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/boot/dts/omap4.dtsi +13 -0
index 359c497..d2cb392 100644
@@ -272,5 +272,18 @@
 			ti,hwmods = "mmc5";
 			ti,needs-special-reset;
 		};
+
+		ctrl_module_core: ctrl_module_core at 4a002000 {
+			compatible = "ti,omap4-control";
+			ti,hwmods = "ctrl_module_core";
+			bandgap {
+				compatible = "ti,omap4460-bandgap";
+				interrupts = <0 126 4>; /* talert */
+				ti,tshut-gpio = <86>; /* tshut */
+			};
+			usb {
+				compatible = "ti,omap4-usb-phy";
+			};
+		};
 	};
 };
Signature · 1 line
1.7.7.1.488.ge8e1c
#66 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Hi, Eduardo.

Quoted 15 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

---
 arch/arm/boot/dts/omap4.dtsi |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/boot/dts/omap4.dtsi +0 -0
index 359c497..d2cb392 100644
@@ -272,5 +272,18 @@
 			ti,hwmods = "mmc5";
 			ti,needs-special-reset;

arch/arm/boot/dts/omap4.dtsi line 283

Quoted 10 lines
arch/arm/boot/dts/omap4.dtsi +9 -0
 		};
+
+		ctrl_module_core: ctrl_module_core at 4a002000 {
+			compatible = "ti,omap4-control";
+			ti,hwmods = "ctrl_module_core";
+			bandgap {
+				compatible = "ti,omap4460-bandgap";
+				interrupts = <0 126 4>; /* talert */
+				ti,tshut-gpio = <86>; /* tshut */
+			};

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

BR,
Konstantin Baydarov.

Quoted 6 lines
arch/arm/boot/dts/omap4.dtsi +4 -0
+			usb {
+				compatible = "ti,omap4-usb-phy";
+			};
+		};
 	};
 };
#67 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Quoted 21 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 18 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

---
  arch/arm/boot/dts/omap4.dtsi |   13 +++++++++++++
  1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/boot/dts/omap4.dtsi +2 -0
index 359c497..d2cb392 100644
@@ -272,5 +272,18 @@
  			ti,hwmods = "mmc5";
  			ti,needs-special-reset;
  		};
+
+		ctrl_module_core: ctrl_module_core at 4a002000 {
Quoted 8 lines

arch/arm/boot/dts/omap4.dtsi line 283

Quoted 7 lines
arch/arm/boot/dts/omap4.dtsi +7 -0
+			compatible = "ti,omap4-control";
+			ti,hwmods = "ctrl_module_core";
+			bandgap {
+				compatible = "ti,omap4460-bandgap";
+				interrupts =<0 126 4>; /* talert */
+				ti,tshut-gpio =<86>; /* tshut */
+			};

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Regards,
Benoit

#68 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Quoted 31 lines · Benoit
Quoted 21 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 18 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

---
  arch/arm/boot/dts/omap4.dtsi |   13 +++++++++++++
  1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/boot/dts/omap4.dtsi +2 -0
index 359c497..d2cb392 100644
@@ -272,5 +272,18 @@
              ti,hwmods = "mmc5";
              ti,needs-special-reset;
          };
+
+        ctrl_module_core: ctrl_module_core at 4a002000 {
Quoted 8 lines

arch/arm/boot/dts/omap4.dtsi line 283

Quoted 7 lines
arch/arm/boot/dts/omap4.dtsi +7 -0
+            compatible = "ti,omap4-control";
+            ti,hwmods = "ctrl_module_core";
+            bandgap {
+                compatible = "ti,omap4460-bandgap";
+                interrupts =<0 126 4>; /* talert */
+                ti,tshut-gpio =<86>; /* tshut */
+            };

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Quoted 1 line

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file. Another solution is to determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

BR,
Konstantin Baydarov.

Quoted 2 lines

Regards,
Benoit

#69 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

Regards,
Benoit

#70 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Hi.

Quoted 31 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

Quoted 7 lines

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

Probably, cpu_is_omap443x() and cpu_is_omap446x() can be used in bandgap driver probe function. Actually many drivers use cpu_is_omap*():
drivers/mfd/omap-usb-host.c
drivers/mfd/twl-core.c

BR,
Konstantin Baydarov.

Quoted 3 lines

Regards,
Benoit

#71 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Quoted 33 lines · Konstantin Baydarov
   Hi.
Quoted 31 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

Quoted 8 lines
Quoted 7 lines

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

Probably, cpu_is_omap443x() and cpu_is_omap446x() can be used in bandgap driver probe function. Actually many drivers use cpu_is_omap*():

No, we cannot, we are in the process of getting rid of that. A driver should only focus on the IP version in theory. The CPU version is not the proper way of getting that. It will make the driver not scalable at all for future OMAP revision.

Quoted 2 lines

drivers/mfd/omap-usb-host.c
drivers/mfd/twl-core.c

Yeah, these are the ones that still need to be fixed...

Regards,
Benoit

#72 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Hello,

Quoted 34 lines · Cousson Benoit
Quoted 33 lines · Konstantin Baydarov

Hi.

Quoted 31 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

I have the weird deja vu feeling...
The DT entry I sent, I already knew it would cause troubles :-) Having it per board it would be really a PITA. Image that every body doing a 4430 board needs to define a BG entry... That would work, but still do we want this?

Benoit, I guess you should know my option by now.
Ideally we should rely on revision register to decide what to do in the driver. And as we discussed, looks like for BG this is somewhat non-existing.

If we go with the SCM revision register, what do we do if the BG goes away from SCM?

If we go with "ti,omap4-bandgap", we still need a way to say if it is 4430, 4460 or 4470. There are configuration / settings specific for each. Not only on bandgap, but also wrt to sensor location and hotspot extrapolation rules.

Because we lack a revision register for bandgap, one way to go is to have still the revisioning on the same way: "ti,omapXXXX-bandgap", but having a omapXXXX.dtsi per omap revision. But do we want to this only due to bandgap?
BTW, is it only BG which is suffering of this issue?

Quoted 1 line
Quoted 1 line

Probably, cpu_is_omap443x() and cpu_is_omap446x() can be used in bandgap driver probe function. Actually many drivers use cpu_is_omap*():

No please! Let's not use that stuff...

Quoted 10 lines

No, we cannot, we are in the process of getting rid of that. A driver should only focus on the IP version in theory. The CPU version is not the proper way of getting that. It will make the driver not scalable at all for future OMAP revision.

Quoted 2 lines

drivers/mfd/omap-usb-host.c
drivers/mfd/twl-core.c

Yeah, these are the ones that still need to be fixed...

agreed with Benoit here.

Quoted 3 lines

Regards,
Benoit

#73 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Quoted 39 lines · Eduardo Valentin

Hello,

Quoted 36 lines · Cousson Benoit
Quoted 35 lines · Konstantin Baydarov
   Hi.
Quoted 33 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

Quoted 7 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

The bitfield layout in that register is:

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

I have the weird deja vu feeling...

I know :-)

Quoted 4 lines

The DT entry I sent, I already knew it would cause troubles :-) Having it per board it would be really a PITA. Image that every body doing a 4430 board needs to define a BG entry... That would work, but still do we want this?

No, in fact I do not want to do that if we can avoid it.

Quoted 3 lines

Benoit, I guess you should know my option by now.
Ideally we should rely on revision register to decide what to do in the driver. And as we discussed, looks like for BG this is somewhat non-existing.

Oops, sorry I was thinking about the SCM revision :-(

The register seems to be there with the layout detailed before. I just do not have a clue about the value we should expect. That's why we have to read it on both 4430 and 4460 to check if some bits are different.

Quoted 1 line

If we go with the SCM revision register, what do we do if the BG goes away from SCM?

Yeah, good point.
But, if at some point the BG becomes a real IP with an OCP port, then we will have a TI wrapper on top of it with the proper revision register... at least in theory :-)

Quoted 1 line

If we go with "ti,omap4-bandgap", we still need a way to say if it is 4430, 4460 or 4470.

Yeah, so we should check if at least that SCM revision field is meaningful.

Quoted 2 lines

There are configuration / settings specific for each. Not only on bandgap, but also wrt to sensor location and hotspot extrapolation rules.

Assuming the SCM version is usable we can extract from that some SW revision for each sub IP.
But it is still not clear how the children will be aware of the parent revision :-(
Exported a get_scm_revision is doable potentially.

Quoted 4 lines

Because we lack a revision register for bandgap, one way to go is to have still the revisioning on the same way: "ti,omapXXXX-bandgap", but having a omapXXXX.dtsi per omap revision. But do we want to this only due to bandgap?
BTW, is it only BG which is suffering of this issue?

Mmm, probably not, that being said, SCM is probably the worst IP we have on OMAP :-)

Regards,
Benoit

Quoted 21 lines
Quoted 1 line
Quoted 1 line

Probably, cpu_is_omap443x() and cpu_is_omap446x() can be used in bandgap driver probe function. Actually many drivers use cpu_is_omap*():

No please! Let's not use that stuff...

Quoted 10 lines

No, we cannot, we are in the process of getting rid of that. A driver should only focus on the IP version in theory. The CPU version is not the proper way of getting that. It will make the driver not scalable at all for future OMAP revision.

Quoted 2 lines

drivers/mfd/omap-usb-host.c
drivers/mfd/twl-core.c

Yeah, these are the ones that still need to be fixed...

agreed with Benoit here.

Quoted 3 lines

Regards,
Benoit

#74 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

In reply to Cousson, Benoit

Hi.

Quoted 31 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

Quoted 7 lines

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

The value of CONTROL_GEN_CORE_REVISION register on my panda board(4430) is:
CONTROL_GEN_CORE_REVISION: 0x40000900
CONTROL_GEN_CORE_HWINFO: 0x0

Eduardo, could you check CONTROL_GEN_CORE_REVISION on your 4460 board.

BR,
Konstantin Baydarov.

Quoted 3 lines

Regards,
Benoit

#75 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Hello,

Quoted 38 lines · Konstantin Baydarov

Hi.

Quoted 35 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

Quoted 8 lines
Quoted 3 lines

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

The value of CONTROL_GEN_CORE_REVISION register on my panda board(4430) is:
CONTROL_GEN_CORE_REVISION: 0x40000900
CONTROL_GEN_CORE_HWINFO: 0x0

Eduardo, could you check CONTROL_GEN_CORE_REVISION on your 4460 board.

4460:
[root@(none) ~]# omapconf read 0x4A002000
40000A00
[root@(none) ~]# omapconf read 0x4A002004
00000000

4470:
[root@(none) ~]# omapconf read 0x4A002000
40000B00
[root@(none) ~]# omapconf read 0x4A002004
00000000

Quoted 8 lines

BR,
Konstantin Baydarov.

Quoted 3 lines

Regards,
Benoit

#76 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Quoted 56 lines · Eduardo Valentin

Hello,

Quoted 38 lines · Konstantin Baydarov
   Hi.
Quoted 35 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

Quoted 8 lines
Quoted 3 lines

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

The value of CONTROL_GEN_CORE_REVISION register on my panda board(4430) is:
CONTROL_GEN_CORE_REVISION: 0x40000900
CONTROL_GEN_CORE_HWINFO: 0x0

Eduardo, could you check CONTROL_GEN_CORE_REVISION on your 4460 board.

4460:
[root@(none) ~]# omapconf read 0x4A002000
40000A00
[root@(none) ~]# omapconf read 0x4A002004
00000000

Quoted 5 lines

4470:
[root@(none) ~]# omapconf read 0x4A002000
40000B00
[root@(none) ~]# omapconf read 0x4A002004
00000000

Nice! We do have a cool progression 1 -> 2 -> 3 for each revision. Well at least for the SCM.

Benoit

#77 lore raw

RFC PATCH 11/11 ARM: DT: Add support to system control module for OMAP4

Hi.

Quoted 63 lines · Benoit
Quoted 56 lines · Eduardo Valentin

Hello,

Quoted 38 lines · Konstantin Baydarov
   Hi.
Quoted 35 lines · Benoit
Quoted 7 lines · Konstantin Baydarov
Quoted 6 lines · Benoit
Quoted 5 lines · Konstantin Baydarov

Hi, Eduardo.

Quoted 2 lines · Eduardo Valentin

This patch add device tree entries on OMAP4 based boards for System Control Module (SCM).

...

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

I believe that CPU-specific bandgap definition should be moved to bard specific dts.

Mmm, why, since it is CPU specific and not board specific. I has to be in the SoC file.

Speaking about omap4430 - omap4430 bandgap differs from omap4460, so if omap4430 bandgap support will be added to omap-bandgap driver the version of bandgap should specified in dts file. omap4.dtsi is a common for omap4 boards, that is why I'm suggesting to move bandgap description to probably board specific file.

OK, I got your point, but in that case we could potentially define a omap4460.dtsi file.

Quoted 4 lines

Another solution is to
determine bandgap type in driver probe function, but in that case "ti,omap4460-bandgap" in omap4.dtsi should be replaced to "ti,omap4-bandgap".

Yes, this is the best solution, but that assume that we can identify the control module version from the HW, which is not necessarily true :-(

The IP_REVISION (offset = 0) value are unfortunately not documented, so we should read it to check if they are different from omap4430 and 4460.

The bitfield layout in that register is:

Quoted 8 lines
Quoted 3 lines

IP_REV_MAJOR: 8..10
IP_REV_CUSTOM: 6..7
IP_REV_MINOR: 0..5

The value of CONTROL_GEN_CORE_REVISION register on my panda board(4430) is:
CONTROL_GEN_CORE_REVISION: 0x40000900
CONTROL_GEN_CORE_HWINFO: 0x0

Eduardo, could you check CONTROL_GEN_CORE_REVISION on your 4460 board.

4460:
[root@(none) ~]# omapconf read 0x4A002000
40000A00
[root@(none) ~]# omapconf read 0x4A002004
00000000

Quoted 5 lines

4470:
[root@(none) ~]# omapconf read 0x4A002000
40000B00
[root@(none) ~]# omapconf read 0x4A002004
00000000

Quoted 4 lines

Nice! We do have a cool progression 1 -> 2 -> 3 for each revision. Well at least for the SCM.

Benoit

This patch allows checking of bandgap type dynamically in bandgap driver probe function by reading omap core control module revision register CONTROL_GEN_CORE_REVISION. It lets bandgap module to be defined in common omap4.dtsi, because all cpu specific attributes(irq and tshut number) were moved to driver.

Patch wasn't tested because I have panda 4430 board.

arch/arm/boot/dts/omap4.dtsi +1 -3
Index: omap-thermal/arch/arm/boot/dts/omap4.dtsi
===================================================================
@@ -277,9 +277,7 @@
 			compatible = "ti,omap4-control";
 			ti,hwmods = "ctrl_module_core";
 			bandgap {
-				compatible = "ti,omap4460-bandgap";
-				interrupts = <0 126 4>; /* talert */
-				ti,tshut-gpio = <86>; /* tshut */
+				compatible = "ti,omap4-bandgap";
 			};
 			usb {
 				compatible = "ti,omap4-usb-phy";
drivers/thermal/omap-bandgap.c +36 -16

104 lines not on this page · raw message

#78 lore raw

cover OMAP System Control Module

In reply to Eduardo Valentin

Hello again,

Quoted 1 line · Eduardo Valentin

Hello Paul and Tony,

FYI, Forgot to mention that these patches are available here:
git://gitorious.org/omap-thermal/omap-thermal.git omap_scm_dev

Quoted 148 lines

This is a series of patches adding a basic support for system control module, on OMAP4+ context. It is a working in progress, but I wanted to share already to get your feedback.

I've modeled the driver as an MFD. You will see in this series:
. A rework of the system control module header (patch from Santosh, picked from the list) . Device creation for control module core
. Early device creation for control module core
. The MFD core driver for system control module
. The MFD child for usb-phy pin control
. The MFD child for bandgap sensor
. Very early exposure of OMAP4 thermal zone
. All added drivers are only supporting DT probing
. The series is based on linux-omap master, as it has the hwmod entries for SCM.

The overall idea of this series is to put in place the infrastructure. It is not touching nor removing the existing APIs under mach-omap2/control.c for now. But the target is to have these APIs moved to the MFD core driver.

For early access, like ID checking, I have written the platform driver as an early platform driver and you will see also early device addition and probing under device.c for this case. This is of course a proposal. I see that there are people that thing this is a bit of an overkill. Konstantin (CCd) was proposing a simpler solution by having APIs with early_* prefixes, and solve the IO address mapping with a DT entry, for instance. But feel free to propose better ways.

This code has been ripped off from the Android 3.1 branch. I have rewritten a couple of things, but the major driver functions and API's entries are kept.

So, based on this series, I see as a TODO list, for system control core driver:
- Start to move all the existing APIs under mach-omap2/control.c to the mfd core.
- Rewrite the users of the existing APIs, mentioned on previous item Once we decide the API and agree on how to deal with early calls.
- Add remaining children (from top of my head, the CAM is one of them, but I also think we should prob have one for HWOBS for instance)
- Test on boards that use the existing APIs.

TODO list for bandgap driver:
- Improve thermal zone definition for OMAP4
- Introduce the thermal zones for OMAP5

Amit, due to hwmod dep, I didn't include any cooling binding in this series, based on the generic CPU cooling device.

Overall series has been tested only with panda board OMAP4460.

Your comments are welcome.

All best,

Eduardo Valentin (9):
ARM: OMAP: expose control.h to mach area
OMAP: Add early device for system control module
mfd: omap: control: core system control driver
OMAP2+: use control module mfd driver in omap_type
mfd: omap: control: usb-phy: introduce the ctrl-module usb driver
ARM: OMAP4+: Adding the temperature sensor register set bit fields
ARM: OMAP4+: thermal: introduce bandgap temperature sensor
omap4: thermal: add basic CPU thermal zone
ARM: DT: Add support to system control module for OMAP4

Kishon Vijay Abraham I (1):
arm: omap: device: create a device for system control module

Santosh Shilimkar (1):
ARM: OMAP4: Remove un-used control module headers and defines.

 .../devicetree/bindings/mfd/omap_control.txt       |   44 +
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 arch/arm/boot/dts/omap4.dtsi                       |   13 +
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/mach-omap2/am35xx-emac.c                  |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c                |    2 +-
 arch/arm/mach-omap2/board-4430sdp.c                |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c            |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c              |    2 +-
 arch/arm/mach-omap2/board-apollon.c                |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |    2 +-
 arch/arm/mach-omap2/board-h4.c                     |    2 +-
 arch/arm/mach-omap2/board-igep0020.c               |    2 +-
 arch/arm/mach-omap2/board-ldp.c                    |    2 +-
 arch/arm/mach-omap2/board-omap3logic.c             |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c             |    2 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |    2 +-
 arch/arm/mach-omap2/clock2420_data.c               |    2 +-
 arch/arm/mach-omap2/clock2430_data.c               |    2 +-
 arch/arm/mach-omap2/clock3xxx_data.c               |    2 +-
 arch/arm/mach-omap2/clock44xx_data.c               |    2 +-
 arch/arm/mach-omap2/common.c                       |    2 +-
 arch/arm/mach-omap2/control.c                      |    2 +-
 arch/arm/mach-omap2/cpuidle34xx.c                  |    2 +-
 arch/arm/mach-omap2/devices.c                      |   57 +-
 arch/arm/mach-omap2/display.c                      |    2 +-
 arch/arm/mach-omap2/hsmmc.c                        |    2 +-
 arch/arm/mach-omap2/id.c                           |   18 +-
 arch/arm/mach-omap2/{ => include/mach}/control.h   |  163 ++-
 .../include/mach/ctrl_module_core_44xx.h           |  391 -----
 .../include/mach/ctrl_module_pad_core_44xx.h       | 1409 -----------------
 .../include/mach/ctrl_module_pad_wkup_44xx.h       |  236 ---
 .../include/mach/ctrl_module_wkup_44xx.h           |   92 --
 arch/arm/mach-omap2/mcbsp.c                        |    2 +-
 arch/arm/mach-omap2/mux.c                          |    2 +-
 arch/arm/mach-omap2/omap_phy_internal.c            |    2 +-
 arch/arm/mach-omap2/opp3xxx_data.c                 |    2 +-
 arch/arm/mach-omap2/opp4xxx_data.c                 |    2 +-
 arch/arm/mach-omap2/pm24xx.c                       |    2 +-
 arch/arm/mach-omap2/pm34xx.c                       |    2 +-
 arch/arm/mach-omap2/prcm.c                         |    2 +-
 arch/arm/mach-omap2/serial.c                       |    2 +-
 arch/arm/mach-omap2/sleep34xx.S                    |    2 +-
 arch/arm/mach-omap2/sr_device.c                    |    2 +-
 arch/arm/mach-omap2/usb-fs.c                       |    2 +-
 arch/arm/mach-omap2/voltage.c                      |    2 +-
 arch/arm/plat-omap/Kconfig                         |    3 +
 drivers/mfd/Kconfig                                |    9 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  211 +++
 drivers/thermal/Kconfig                            |   25 +
 drivers/thermal/Makefile                           |    5 +-
 drivers/thermal/omap-bandgap.c                     | 1602 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   75 +
 drivers/thermal/omap4-thermal.c                    |   72 +
 drivers/usb/otg/Kconfig                            |   13 +
 drivers/usb/otg/Makefile                           |    1 +
 drivers/usb/otg/omap4-usb-phy.c                    |  130 ++
 include/linux/mfd/omap_control.h                   |   69 +
 include/linux/usb/omap4_usb_phy.h                  |   53 +
 60 files changed, 2617 insertions(+), 2173 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/omap_control.txt
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 rename arch/arm/mach-omap2/{ => include/mach}/control.h (75%)
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
 create mode 100644 drivers/mfd/omap-control-core.c
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h
 create mode 100644 drivers/thermal/omap4-thermal.c
 create mode 100644 drivers/usb/otg/omap4-usb-phy.c
 create mode 100644 include/linux/mfd/omap_control.h
 create mode 100644 include/linux/usb/omap4_usb_phy.h
Signature · 1 line
1.7.7.1.488.ge8e1c
#79 lore raw

cover OMAP System Control Module

In reply to Eduardo Valentin

Hi.

Quoted 21 lines · Eduardo Valentin

Hello Paul and Tony,

This is a series of patches adding a basic support for system control module, on OMAP4+ context. It is a working in progress, but I wanted to share already to get your feedback.

I've modeled the driver as an MFD. You will see in this series:
. A rework of the system control module header (patch from Santosh, picked from the list) . Device creation for control module core
. Early device creation for control module core
. The MFD core driver for system control module
. The MFD child for usb-phy pin control
. The MFD child for bandgap sensor
. Very early exposure of OMAP4 thermal zone
. All added drivers are only supporting DT probing
. The series is based on linux-omap master, as it has the hwmod entries for SCM.

The overall idea of this series is to put in place the infrastructure. It is not touching nor removing the existing APIs under mach-omap2/control.c for now. But the target is to have these APIs moved to the MFD core driver.

Quoted 7 lines

For early access, like ID checking, I have written the platform driver as an early platform driver and you will see also early device addition and probing under device.c for this case. This is of course a proposal. I see that there are people that thing this is a bit of an overkill. Konstantin (CCd) was proposing a simpler solution by having APIs with early_* prefixes, and solve the IO address mapping with a DT entry, for instance. But feel free to propose better ways.

In my latest version I got rid from early API set, check out patch for V3 patch set. I'll attach patch for current version later.

BR,
Konstantin Baydarov.

Quoted 118 lines

This code has been ripped off from the Android 3.1 branch. I have rewritten a couple of things, but the major driver functions and API's entries are kept.

So, based on this series, I see as a TODO list, for system control core driver:
- Start to move all the existing APIs under mach-omap2/control.c to the mfd core.
- Rewrite the users of the existing APIs, mentioned on previous item Once we decide the API and agree on how to deal with early calls.
- Add remaining children (from top of my head, the CAM is one of them, but I also think we should prob have one for HWOBS for instance)
- Test on boards that use the existing APIs.

TODO list for bandgap driver:
- Improve thermal zone definition for OMAP4
- Introduce the thermal zones for OMAP5

Amit, due to hwmod dep, I didn't include any cooling binding in this series, based on the generic CPU cooling device.

Overall series has been tested only with panda board OMAP4460.

Your comments are welcome.

All best,

Eduardo Valentin (9):
ARM: OMAP: expose control.h to mach area
OMAP: Add early device for system control module
mfd: omap: control: core system control driver
OMAP2+: use control module mfd driver in omap_type
mfd: omap: control: usb-phy: introduce the ctrl-module usb driver
ARM: OMAP4+: Adding the temperature sensor register set bit fields
ARM: OMAP4+: thermal: introduce bandgap temperature sensor
omap4: thermal: add basic CPU thermal zone
ARM: DT: Add support to system control module for OMAP4

Kishon Vijay Abraham I (1):
arm: omap: device: create a device for system control module

Santosh Shilimkar (1):
ARM: OMAP4: Remove un-used control module headers and defines.

 .../devicetree/bindings/mfd/omap_control.txt       |   44 +
 .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
 arch/arm/boot/dts/omap4.dtsi                       |   13 +
 arch/arm/mach-omap2/Kconfig                        |    1 +
 arch/arm/mach-omap2/am35xx-emac.c                  |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c                |    2 +-
 arch/arm/mach-omap2/board-4430sdp.c                |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c            |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c              |    2 +-
 arch/arm/mach-omap2/board-apollon.c                |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |    2 +-
 arch/arm/mach-omap2/board-h4.c                     |    2 +-
 arch/arm/mach-omap2/board-igep0020.c               |    2 +-
 arch/arm/mach-omap2/board-ldp.c                    |    2 +-
 arch/arm/mach-omap2/board-omap3logic.c             |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c             |    2 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |    2 +-
 arch/arm/mach-omap2/clock2420_data.c               |    2 +-
 arch/arm/mach-omap2/clock2430_data.c               |    2 +-
 arch/arm/mach-omap2/clock3xxx_data.c               |    2 +-
 arch/arm/mach-omap2/clock44xx_data.c               |    2 +-
 arch/arm/mach-omap2/common.c                       |    2 +-
 arch/arm/mach-omap2/control.c                      |    2 +-
 arch/arm/mach-omap2/cpuidle34xx.c                  |    2 +-
 arch/arm/mach-omap2/devices.c                      |   57 +-
 arch/arm/mach-omap2/display.c                      |    2 +-
 arch/arm/mach-omap2/hsmmc.c                        |    2 +-
 arch/arm/mach-omap2/id.c                           |   18 +-
 arch/arm/mach-omap2/{ => include/mach}/control.h   |  163 ++-
 .../include/mach/ctrl_module_core_44xx.h           |  391 -----
 .../include/mach/ctrl_module_pad_core_44xx.h       | 1409 -----------------
 .../include/mach/ctrl_module_pad_wkup_44xx.h       |  236 ---
 .../include/mach/ctrl_module_wkup_44xx.h           |   92 --
 arch/arm/mach-omap2/mcbsp.c                        |    2 +-
 arch/arm/mach-omap2/mux.c                          |    2 +-
 arch/arm/mach-omap2/omap_phy_internal.c            |    2 +-
 arch/arm/mach-omap2/opp3xxx_data.c                 |    2 +-
 arch/arm/mach-omap2/opp4xxx_data.c                 |    2 +-
 arch/arm/mach-omap2/pm24xx.c                       |    2 +-
 arch/arm/mach-omap2/pm34xx.c                       |    2 +-
 arch/arm/mach-omap2/prcm.c                         |    2 +-
 arch/arm/mach-omap2/serial.c                       |    2 +-
 arch/arm/mach-omap2/sleep34xx.S                    |    2 +-
 arch/arm/mach-omap2/sr_device.c                    |    2 +-
 arch/arm/mach-omap2/usb-fs.c                       |    2 +-
 arch/arm/mach-omap2/voltage.c                      |    2 +-
 arch/arm/plat-omap/Kconfig                         |    3 +
 drivers/mfd/Kconfig                                |    9 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/omap-control-core.c                    |  211 +++
 drivers/thermal/Kconfig                            |   25 +
 drivers/thermal/Makefile                           |    5 +-
 drivers/thermal/omap-bandgap.c                     | 1602 ++++++++++++++++++++
 drivers/thermal/omap-bandgap.h                     |   75 +
 drivers/thermal/omap4-thermal.c                    |   72 +
 drivers/usb/otg/Kconfig                            |   13 +
 drivers/usb/otg/Makefile                           |    1 +
 drivers/usb/otg/omap4-usb-phy.c                    |  130 ++
 include/linux/mfd/omap_control.h                   |   69 +
 include/linux/usb/omap4_usb_phy.h                  |   53 +
 60 files changed, 2617 insertions(+), 2173 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/omap_control.txt
 create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
 rename arch/arm/mach-omap2/{ => include/mach}/control.h (75%)
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
 create mode 100644 drivers/mfd/omap-control-core.c
 create mode 100644 drivers/thermal/omap-bandgap.c
 create mode 100644 drivers/thermal/omap-bandgap.h
 create mode 100644 drivers/thermal/omap4-thermal.c
 create mode 100644 drivers/usb/otg/omap4-usb-phy.c
 create mode 100644 include/linux/mfd/omap_control.h
 create mode 100644 include/linux/usb/omap4_usb_phy.h
#80 lore raw

cover OMAP System Control Module

Konstantin,

Quoted 31 lines · Konstantin Baydarov

?Hi.

Quoted 21 lines · Eduardo Valentin

Hello Paul and Tony,

This is a series of patches adding a basic support for system control module, on OMAP4+ context. It is a working in progress, but I wanted to share already to get your feedback.

I've modeled the driver as an MFD. You will see in this series:
. A rework of the system control module header (patch from Santosh, picked from the list) . Device creation for control module core
. Early device creation for control module core
. The MFD core driver for system control module
. The MFD child for usb-phy pin control
. The MFD child for bandgap sensor
. Very early exposure of OMAP4 thermal zone
. All added drivers are only supporting DT probing
. The series is based on linux-omap master, as it has the hwmod entries for SCM.

The overall idea of this series is to put in place the infrastructure. It is not touching nor removing the existing APIs under mach-omap2/control.c for now. But the target is to have these APIs moved to the MFD core driver.

Quoted 7 lines

For early access, like ID checking, I have written the platform driver as an early platform driver and you will see also early device addition and probing under device.c for this case. This is of course a proposal. I see that there are people that thing this is a bit of an overkill. Konstantin (CCd) was proposing a simpler solution by having APIs with early_* prefixes, and solve the IO address mapping with a DT entry, for instance. But feel free to propose better ways.

Quoted 2 lines

In my latest version I got rid from early API set, check out patch for V3 patch set. I'll attach patch for current version later.

Please send it across so we can compare your approach with the one present in this series.

Quoted 123 lines

BR,
? ?Konstantin Baydarov.

Quoted 118 lines

This code has been ripped off from the Android 3.1 branch. I have rewritten a couple of things, but the major driver functions and API's entries are kept.

So, based on this series, I see as a TODO list, for system control core driver:
- Start to move all the existing APIs under mach-omap2/control.c to the mfd core.
- Rewrite the users of the existing APIs, mentioned on previous item Once we decide the API and agree on how to deal with early calls.
- Add remaining children (from top of my head, the CAM is one of them, but I also think we should prob have one for HWOBS for instance)
- Test on boards that use the existing APIs.

TODO list for bandgap driver:
- Improve thermal zone definition for OMAP4
- Introduce the thermal zones for OMAP5

Amit, due to hwmod dep, I didn't include any cooling binding in this series, based on the generic CPU cooling device.

Overall series has been tested only with panda board OMAP4460.

Your comments are welcome.

All best,

Eduardo Valentin (9):
? ARM: OMAP: expose control.h to mach area
? OMAP: Add early device for system control module
? mfd: omap: control: core system control driver
? OMAP2+: use control module mfd driver in omap_type
? mfd: omap: control: usb-phy: introduce the ctrl-module usb driver ? ARM: OMAP4+: Adding the temperature sensor register set bit fields ? ARM: OMAP4+: thermal: introduce bandgap temperature sensor ? omap4: thermal: add basic CPU thermal zone
? ARM: DT: Add support to system control module for OMAP4

Kishon Vijay Abraham I (1):
? arm: omap: device: create a device for system control module

Santosh Shilimkar (1):
? ARM: OMAP4: Remove un-used control module headers and defines.

?.../devicetree/bindings/mfd/omap_control.txt ? ? ? | ? 44 +
?.../devicetree/bindings/thermal/omap_bandgap.txt ? | ? 27 +
?arch/arm/boot/dts/omap4.dtsi ? ? ? ? ? ? ? ? ? ? ? | ? 13 +
?arch/arm/mach-omap2/Kconfig ? ? ? ? ? ? ? ? ? ? ? ?| ? ?1 +
?arch/arm/mach-omap2/am35xx-emac.c ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-3430sdp.c ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-4430sdp.c ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-am3517crane.c ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-am3517evm.c ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-apollon.c ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-cm-t3517.c ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/board-h4.c ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/board-igep0020.c ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/board-ldp.c ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/board-omap3logic.c ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/board-omap4panda.c ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/board-omap4pcm049.c ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/clock2420_data.c ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/clock2430_data.c ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/clock3xxx_data.c ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/clock44xx_data.c ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/common.c ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/control.c ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/cpuidle34xx.c ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/devices.c ? ? ? ? ? ? ? ? ? ? ?| ? 57 +-
?arch/arm/mach-omap2/display.c ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/hsmmc.c ? ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/id.c ? ? ? ? ? ? ? ? ? ? ? ? ? | ? 18 +-
?arch/arm/mach-omap2/{ => include/mach}/control.h ? | ?163 ++-
?.../include/mach/ctrl_module_core_44xx.h ? ? ? ? ? | ?391 -----
?.../include/mach/ctrl_module_pad_core_44xx.h ? ? ? | 1409 -----------------
?.../include/mach/ctrl_module_pad_wkup_44xx.h ? ? ? | ?236 ---
?.../include/mach/ctrl_module_wkup_44xx.h ? ? ? ? ? | ? 92 --
?arch/arm/mach-omap2/mcbsp.c ? ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/omap_phy_internal.c ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/opp3xxx_data.c ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/opp4xxx_data.c ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/pm24xx.c ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/pm34xx.c ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/prcm.c ? ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/serial.c ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/sleep34xx.S ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/sr_device.c ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-omap2/usb-fs.c ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +-
?arch/arm/mach-omap2/voltage.c ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/plat-omap/Kconfig ? ? ? ? ? ? ? ? ? ? ? ? | ? ?3 +
?drivers/mfd/Kconfig ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| ? ?9 +
?drivers/mfd/Makefile ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 +
?drivers/mfd/omap-control-core.c ? ? ? ? ? ? ? ? ? ?| ?211 +++
?drivers/thermal/Kconfig ? ? ? ? ? ? ? ? ? ? ? ? ? ?| ? 25 +
?drivers/thermal/Makefile ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ?5 +-
?drivers/thermal/omap-bandgap.c ? ? ? ? ? ? ? ? ? ? | 1602 ++++++++++++++++++++
?drivers/thermal/omap-bandgap.h ? ? ? ? ? ? ? ? ? ? | ? 75 +
?drivers/thermal/omap4-thermal.c ? ? ? ? ? ? ? ? ? ?| ? 72 +
?drivers/usb/otg/Kconfig ? ? ? ? ? ? ? ? ? ? ? ? ? ?| ? 13 +
?drivers/usb/otg/Makefile ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 +
?drivers/usb/otg/omap4-usb-phy.c ? ? ? ? ? ? ? ? ? ?| ?130 ++
?include/linux/mfd/omap_control.h ? ? ? ? ? ? ? ? ? | ? 69 +
?include/linux/usb/omap4_usb_phy.h ? ? ? ? ? ? ? ? ?| ? 53 +

?60 files changed, 2617 insertions(+), 2173 deletions(-)
?create mode 100644 Documentation/devicetree/bindings/mfd/omap_control.txt ?create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt ?rename arch/arm/mach-omap2/{ => include/mach}/control.h (75%) ?delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h ?delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h ?delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h ?delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h ?create mode 100644 drivers/mfd/omap-control-core.c
?create mode 100644 drivers/thermal/omap-bandgap.c
?create mode 100644 drivers/thermal/omap-bandgap.h
?create mode 100644 drivers/thermal/omap4-thermal.c
?create mode 100644 drivers/usb/otg/omap4-usb-phy.c
?create mode 100644 include/linux/mfd/omap_control.h
?create mode 100644 include/linux/usb/omap4_usb_phy.h

Signature · 1 line
Eduardo Valentin
#81 lore raw

cover OMAP System Control Module

Hi.

Quoted 35 lines · Eduardo

Konstantin,

Quoted 31 lines · Konstantin Baydarov

Hi.

Quoted 28 lines · Eduardo Valentin

Hello Paul and Tony,

This is a series of patches adding a basic support for system control module, on OMAP4+ context. It is a working in progress, but I wanted to share already to get your feedback.

I've modeled the driver as an MFD. You will see in this series:
. A rework of the system control module header (patch from Santosh, picked from the list) . Device creation for control module core
. Early device creation for control module core
. The MFD core driver for system control module
. The MFD child for usb-phy pin control
. The MFD child for bandgap sensor
. Very early exposure of OMAP4 thermal zone
. All added drivers are only supporting DT probing
. The series is based on linux-omap master, as it has the hwmod entries for SCM.

The overall idea of this series is to put in place the infrastructure. It is not touching nor removing the existing APIs under mach-omap2/control.c for now. But the target is to have these APIs moved to the MFD core driver.

For early access, like ID checking, I have written the platform driver as an early platform driver and you will see also early device addition and probing under device.c for this case. This is of course a proposal. I see that there are people that thing this is a bit of an overkill. Konstantin (CCd) was proposing a simpler solution by having APIs with early_* prefixes, and solve the IO address mapping with a DT entry, for instance. But feel free to propose better ways.

Quoted 5 lines
Quoted 2 lines

In my latest version I got rid from early API set, check out patch for V3 patch set. I'll attach patch for current version later.

Please send it across so we can compare your approach with the one present in this series.

Moved control module window remap to early_initcall to allow usage of control module API very early during kernel initialization. Switched omap_type() to omap-control-core.c API.

drivers/mfd/omap-control-core.c +61 -23
Index: omap-thermal/drivers/mfd/omap-control-core.c
===================================================================
@@ -31,12 +31,16 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/omap_control.h>
 
+#include <linux/of.h>
+#include <linux/of_address.h>
+
 static struct omap_control *omap_control_module;
+struct omap_control omap_control_data;
 
 /**
  * omap_control_readl: Read a single omap control module register.
  *
- * @dev: device to read from.
+ * @dev: unused - there is only one controle module
  * @reg: register to read.
  * @val: output with register value.
  *
@@ -44,7 +48,7 @@ static struct omap_control *omap_control
  */
 int omap_control_readl(struct device *dev, u32 reg, u32 *val)
 {
-	struct omap_control *omap_control = dev_get_drvdata(dev);
+	struct omap_control *omap_control = omap_control_module;
 
 	if (!omap_control)
 		return -EINVAL;
@@ -58,7 +62,7 @@ EXPORT_SYMBOL_GPL(omap_control_readl);
 /**
  * omap_control_writel: Write a single omap control module register.
  *
- * @dev: device to read from.
+ * @dev: unused - there is only one controle module
  * @val: value to write.
  * @reg: register to write to.
  *
@@ -66,7 +70,7 @@ EXPORT_SYMBOL_GPL(omap_control_readl);
  */
 int omap_control_writel(struct device *dev, u32 val, u32 reg)
 {
-	struct omap_control *omap_control = dev_get_drvdata(dev);
+	struct omap_control *omap_control = omap_control_module;
 	unsigned long flags;
 
 	if (!omap_control)
@@ -130,40 +134,26 @@ static const struct of_device_id of_omap
 
 static int __devinit omap_control_probe(struct platform_device *pdev)
 {
-	struct resource *res;
-	void __iomem *base;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct omap_control *omap_control;
 
-	omap_control = devm_kzalloc(dev, sizeof(*omap_control), GFP_KERNEL);
-	if (!omap_control) {
-		dev_err(dev, "not enough memory for omap_control\n");
-		return -ENOMEM;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "missing memory base resource\n");
-		return -EINVAL;
-	}
-
-	base = devm_request_and_ioremap(dev, res);
-	if (!base) {
+	if (!omap_control_module) {
 		dev_err(dev, "ioremap failed\n");
 		return -EADDRNOTAVAIL;
 	}
+	omap_control = omap_control_module;
 
-	omap_control->base = base;
 	omap_control->dev = dev;
 	spin_lock_init(&omap_control->reg_lock);
 
 	platform_set_drvdata(pdev, omap_control);
-	omap_control_module = omap_control;
 
 	return of_platform_populate(np, of_omap_control_match, NULL, dev);
 }
 
+/* Looks like that there is no need to remove control module */
+#if 0
 static int __devexit omap_control_remove(struct platform_device *pdev)
 {
 	struct omap_control *omap_control = platform_get_drvdata(pdev);
@@ -181,10 +171,11 @@ static int __devexit omap_control_remove
 
 	return 0;
 }
+#endif
 
 static struct platform_driver omap_control_driver = {
 	.probe			= omap_control_probe,
-	.remove			= __devexit_p(omap_control_remove),
+//	.remove			= __devexit_p(omap_control_remove),
 	.driver = {
 		.name		= "omap-control-core",
 		.owner		= THIS_MODULE,
@@ -192,6 +183,53 @@ static struct platform_driver omap_contr
 	},
 };
 
+int __init omap_control_of_init(struct device_node *node,
+			     struct device_node *parent)
+{
+	struct resource res;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	if (of_address_to_resource(node, 0, &res)) {
+		WARN(1, "unable to get intc registers\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void __init of_omap_control_init(const struct of_device_id *matches)
+{
+	struct device_node *np;
+	struct property *pp = 0;
+	unsigned long phys_base = 0;
+	size_t mapsize = 0;
+
+	for_each_matching_node(np, matches) {
+
+		pp = of_find_property(np, "reg", NULL);
+		if(pp) {
+			phys_base = (unsigned long)be32_to_cpup(pp->value);
+			mapsize = (size_t)be32_to_cpup( (void*)((char*)pp->value + 4) );
+			omap_control_data.base = ioremap(phys_base, mapsize);
+			if(omap_control_data.base)
+				omap_control_module = &omap_control_data;
+
+//			printk("\t\t **** of_omap_control_init(): ioremap addr %x \n", omap_control_data.base);
+		}
+	}
+}
+
+static int __init
+omap_control_early_initcall(void)
+{
+	of_omap_control_init(of_omap_control_match);
+
+	return 0;
+}
+early_initcall(omap_control_early_initcall);
+
 static int __init omap_control_init(void)
 {
 	return platform_driver_register(&omap_control_driver);
arch/arm/boot/dts/omap4.dtsi +3 -0
Index: omap-thermal/arch/arm/boot/dts/omap4.dtsi
===================================================================
@@ -275,7 +275,10 @@
 
 		ctrl_module_core: ctrl_module_core at 4a002000 {
 			compatible = "ti,omap4-control";
+			#address-cells = <1>;
+			#size-cells = <1>;
 			ti,hwmods = "ctrl_module_core";
+			reg = <0x4a002000 0x1000>;
 			bandgap {
 				compatible = "ti,omap4460-bandgap";
 				interrupts = <0 126 4>; /* talert */
arch/arm/mach-omap2/id.c +3 -13
Index: omap-thermal/arch/arm/mach-omap2/id.c
===================================================================
@@ -39,16 +39,12 @@ unsigned int omap_rev(void)
 }
 EXPORT_SYMBOL(omap_rev);
 
+int omap_control_readl(struct device *dev, u32 reg, u32 *val);
+
 int omap_type(void)
 {
-	struct device *scm;
-	int ret = 0;
 	u32 val = 0;
 
-	scm = omap_control_get();
-	if (IS_ERR_OR_NULL(scm))
-		return 0;
-
 	if (cpu_is_omap24xx()) {
 		val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
 	} else if (cpu_is_am33xx()) {
@@ -56,23 +52,17 @@ int omap_type(void)
 	} else if (cpu_is_omap34xx()) {
 		val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
 	} else if (cpu_is_omap44xx()) {
-		ret = omap_control_readl(scm, OMAP4_CTRL_MODULE_CORE_STATUS,
+		omap_control_readl(0x0, OMAP4_CTRL_MODULE_CORE_STATUS,
 					 &val);
 	} else {
 		pr_err("Cannot detect omap type!\n");
 		goto out;
 	}
 
-	if (ret) {
-		pr_err("problem while fetching omap type\n");
-		goto out;
-	}
-
 	val &= OMAP2_DEVICETYPE_MASK;
 	val >>= 8;
 
 out:
-	omap_control_put(scm);
 	return val;
 }
 EXPORT_SYMBOL(omap_type);
arch/arm/mach-omap2/devices.c +2 -0
Index: omap-thermal/arch/arm/mach-omap2/devices.c
===================================================================
@@ -40,6 +40,7 @@
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
 
+#if 0
 static struct resource control_resources[] = {
 	[0] = {
 		.start	= 0x4a002000,
@@ -68,6 +69,7 @@ static int __init plat_early_device_setu
 	return 0;
 }
 early_initcall(plat_early_device_setup);
+#endif
 
 static int omap_init_control(void)
 {
#82 lore raw

cover OMAP System Control Module

In reply to Eduardo Valentin

Hi Eduardo,

Quoted 5 lines · Eduardo Valentin

Hello Paul and Tony,

This is a series of patches adding a basic support for system control module, on OMAP4+ context. It is a working in progress, but I wanted to share already to get your feedback.

This is a great start, thanks for working on this. We have been needing to do this for awhile now so I'm glad to see you working on it.

Quoted 11 lines

I've modeled the driver as an MFD. You will see in this series:
. A rework of the system control module header (patch from Santosh, picked from the list) . Device creation for control module core
. Early device creation for control module core
. The MFD core driver for system control module
. The MFD child for usb-phy pin control
. The MFD child for bandgap sensor
. Very early exposure of OMAP4 thermal zone
. All added drivers are only supporting DT probing
. The series is based on linux-omap master, as it has the hwmod entries for SCM.

Quoted 3 lines

The overall idea of this series is to put in place the infrastructure. It is not touching nor removing the existing APIs under mach-omap2/control.c for now. But the target is to have these APIs moved to the MFD core driver.

IMO, the best time to create the APIs is when the new MFD children are created.

The goal should be that none of these drivers should be doing direct read/writes to the control module.

Kevin

#83 lore raw

RFC PATCH v2 1/11 ARM: OMAP4: Remove un-used control module headers and defines.

In reply to Eduardo Valentin

From: Santosh Shilimkar <[email protected]>

Most of the OMAP4 control module register defines are not used and can be removed. Keep only needed defines and move them to common control module header just like other OMAP versions.

---
 arch/arm/mach-omap2/control.h                      |   45 +-
 .../include/mach/ctrl_module_core_44xx.h           |  391 ------
 .../include/mach/ctrl_module_pad_core_44xx.h       | 1409 --------------------
 .../include/mach/ctrl_module_pad_wkup_44xx.h       |  236 ----
 .../include/mach/ctrl_module_wkup_44xx.h           |   92 --
 5 files changed, 40 insertions(+), 2133 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
 delete mode 100644 arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
arch/arm/mach-omap2/control.h +40 -5
index a406fd0..dad2903 100644
@@ -16,11 +16,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
 #define __ARCH_ARM_MACH_OMAP2_CONTROL_H
 
-#include <mach/ctrl_module_core_44xx.h>
-#include <mach/ctrl_module_wkup_44xx.h>
-#include <mach/ctrl_module_pad_core_44xx.h>
-#include <mach/ctrl_module_pad_wkup_44xx.h>
-
 #ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)					\
 		OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
@@ -183,6 +178,43 @@
 #define OMAP3630_CONTROL_FUSE_OPP50_VDD2        (OMAP2_CONTROL_GENERAL + 0x0128)
 #define OMAP3630_CONTROL_FUSE_OPP100_VDD2       (OMAP2_CONTROL_GENERAL + 0x012C)
 
+/* OMAP4 IDCODE CONTROL */
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1		0x0218
+#define OMAP4_CTRL_MODULE_CORE_STATUS				0x02c4
+
+/* CONTROL_I2C_1 */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1		0x0624
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK			(1 << 28)
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK			(1 << 24)
+
+/* DSI CONTROL_DSIPHY */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY		0x0618
+#define OMAP4_DSI2_LANEENABLE_SHIFT				29
+#define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT				24
+#define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT					19
+#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT					14
+#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
+
+/* CONTROL_PBIASLITE */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE		0x0600
+#define OMAP4_MMC1_PWRDNZ_MASK					(1 << 26)
+#define OMAP4_MMC1_PBIASLITE_VMODE_MASK				(1 << 21)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK			(1 << 22)
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK			(1 << 23)
+
+/* CONTROL_MMC1 */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1			0x0628
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK			(1 << 31)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK			(1 << 30)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK			(1 << 29)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK			(1 << 28)
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK				(1 << 27)
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK				(1 << 26)
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK				(1 << 25)
+
 /* OMAP44xx control efuse offsets */
 #define OMAP44XX_CONTROL_FUSE_IVA_OPP50		0x22C
 #define OMAP44XX_CONTROL_FUSE_IVA_OPP100	0x22F
@@ -195,6 +227,9 @@
 #define OMAP44XX_CONTROL_FUSE_CORE_OPP50	0x254
 #define OMAP44XX_CONTROL_FUSE_CORE_OPP100	0x257
 
+/* OMAP44xx control McBSP padconf */
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP	0x061c
+
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
 #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h deleted +0 -391

391 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h deleted +0 -1409

1,409 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h deleted +0 -236

236 lines not on this page · raw message

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h deleted +0 -92

92 lines not on this page · raw message

-- 1.7.7.1.488.ge8e1c

#84 lore raw

RFC PATCH v2 2/11 ARM: OMAP: expose control.h to mach area

In reply to Eduardo Valentin

This patch exposes the definitions under control.h to drivers outside the machine code.

---
 arch/arm/mach-omap2/am35xx-emac.c                |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c              |    2 +-
 arch/arm/mach-omap2/board-4430sdp.c              |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c          |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c            |    2 +-
 arch/arm/mach-omap2/board-apollon.c              |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c             |    2 +-
 arch/arm/mach-omap2/board-h4.c                   |    2 +-
 arch/arm/mach-omap2/board-igep0020.c             |    2 +-
 arch/arm/mach-omap2/board-ldp.c                  |    2 +-
 arch/arm/mach-omap2/board-omap3logic.c           |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c           |    2 +-
 arch/arm/mach-omap2/board-omap4pcm049.c          |    2 +-
 arch/arm/mach-omap2/clock2420_data.c             |    2 +-
 arch/arm/mach-omap2/clock2430_data.c             |    2 +-
 arch/arm/mach-omap2/clock3xxx_data.c             |    2 +-
 arch/arm/mach-omap2/clock44xx_data.c             |    2 +-
 arch/arm/mach-omap2/common.c                     |    2 +-
 arch/arm/mach-omap2/control.c                    |    2 +-
 arch/arm/mach-omap2/cpuidle34xx.c                |    2 +-
 arch/arm/mach-omap2/devices.c                    |    2 +-
 arch/arm/mach-omap2/display.c                    |    2 +-
 arch/arm/mach-omap2/hsmmc.c                      |    2 +-
 arch/arm/mach-omap2/id.c                         |    2 +-
 arch/arm/mach-omap2/{ => include/mach}/control.h |    2 +-
 arch/arm/mach-omap2/mcbsp.c                      |    2 +-
 arch/arm/mach-omap2/mux.c                        |    2 +-
 arch/arm/mach-omap2/omap_phy_internal.c          |    2 +-
 arch/arm/mach-omap2/opp3xxx_data.c               |    2 +-
 arch/arm/mach-omap2/opp4xxx_data.c               |    2 +-
 arch/arm/mach-omap2/pm24xx.c                     |    2 +-
 arch/arm/mach-omap2/pm34xx.c                     |    2 +-
 arch/arm/mach-omap2/prcm.c                       |    2 +-
 arch/arm/mach-omap2/serial.c                     |    2 +-
 arch/arm/mach-omap2/sleep34xx.S                  |    2 +-
 arch/arm/mach-omap2/sr_device.c                  |    2 +-
 arch/arm/mach-omap2/usb-fs.c                     |    2 +-
 arch/arm/mach-omap2/voltage.c                    |    2 +-
 38 files changed, 38 insertions(+), 38 deletions(-)
 rename arch/arm/mach-omap2/{ => include/mach}/control.h (99%)
arch/arm/mach-omap2/am35xx-emac.c +1 -1
index 447682c..c3da28a 100644
@@ -21,7 +21,7 @@
 #include <plat/irqs.h>
 #include <mach/am35xx.h>
 
-#include "control.h"
+#include <mach/control.h>
 
 static struct mdio_platform_data am35xx_emac_mdio_pdata;
 
arch/arm/mach-omap2/board-3430sdp.c +1 -1
index 37abb0d..ad1132b 100644
@@ -46,7 +46,7 @@
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #define CONFIG_DISABLE_HFCLK 1
arch/arm/mach-omap2/board-4430sdp.c +1 -1
index 94af6cd..8f7f76b 100644
@@ -47,7 +47,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #define ETH_KS8851_IRQ			34
arch/arm/mach-omap2/board-am3517crane.c +1 -1
index 3b8a53c..2ad514d 100644
@@ -32,7 +32,7 @@
 
 #include "am35xx-emac.h"
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define GPIO_USB_POWER		35
 #define GPIO_USB_NRESET		38
arch/arm/mach-omap2/board-am3517evm.c +1 -1
index 99790eb..bef6586 100644
@@ -41,7 +41,7 @@
 
 #include "am35xx-emac.h"
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "hsmmc.h"
 
 #define LCD_PANEL_PWR		176
arch/arm/mach-omap2/board-apollon.c +1 -1
index 768ece2..bd04fe2 100644
@@ -44,7 +44,7 @@
 #include <video/omap-panel-generic-dpi.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* LED & Switch macros */
 #define LED0_GPIO13		13
arch/arm/mach-omap2/board-cm-t3517.c +1 -1
index 9e66e16..1d2b7a3 100644
@@ -47,7 +47,7 @@
 #include <mach/am35xx.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 #include "am35xx-emac.h"
 
arch/arm/mach-omap2/board-h4.c +1 -1
index 0bbbabe..623a231 100644
@@ -43,7 +43,7 @@
 #include <video/omap-panel-generic-dpi.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define H4_FLASH_CS	0
 #define H4_SMC91X_CS	1
arch/arm/mach-omap2/board-igep0020.c +1 -1
index 7a27409..ebef044 100644
@@ -42,7 +42,7 @@
 #include "sdram-numonyx-m65kxxxxam.h"
 #include "common-board-devices.h"
 #include "board-flash.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
arch/arm/mach-omap2/board-ldp.c +1 -1
index 1b60495..6383a76 100644
@@ -50,7 +50,7 @@
 #include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #define LDP_SMSC911X_CS		1
arch/arm/mach-omap2/board-omap3logic.c +1 -1
index c008bf8..ca3e075 100644
@@ -37,7 +37,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common-board-devices.h"
 
 #include <plat/mux.h>
arch/arm/mach-omap2/board-omap4panda.c +1 -1
index 847a857..b1c8517 100644
@@ -45,7 +45,7 @@
 #include <video/omap-panel-tfp410.h>
 
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 #include "common-board-devices.h"
 
arch/arm/mach-omap2/board-omap4pcm049.c +1 -1
index a95f426..101e984 100644
@@ -48,7 +48,7 @@
 
 #include "common.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 #include "common-board-devices.h"
 
arch/arm/mach-omap2/clock2420_data.c +1 -1
index bace930..f350e96 100644
@@ -30,7 +30,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
 
arch/arm/mach-omap2/clock2430_data.c +1 -1
index 3b4d09a..dd08bcb 100644
@@ -29,7 +29,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 #define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
 
arch/arm/mach-omap2/clock3xxx_data.c +1 -1
index 4e1a3b0..694625f 100644
@@ -34,7 +34,7 @@
 #include "cm-regbits-34xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
-#include "control.h"
+#include <mach/control.h>
 
 /*
  * clocks
arch/arm/mach-omap2/clock44xx_data.c +1 -1
index 2172f66..ce11ee4 100644
@@ -39,7 +39,7 @@
 #include "cm-regbits-44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
-#include "control.h"
+#include <mach/control.h>
 #include "scrm44xx.h"
 
 /* OMAP4 modulemode control */
arch/arm/mach-omap2/common.c +1 -1
index 8a6953a..3dc94d0 100644
@@ -25,7 +25,7 @@
 #include "iomap.h"
 #include "common.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* Global address base setup code */
 
arch/arm/mach-omap2/control.c +1 -1
index 08e674b..92e35bf 100644
@@ -26,7 +26,7 @@
 #include "cm2xxx_3xxx.h"
 #include "sdrc.h"
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* Used by omap3_ctrl_save_padconf() */
 #define START_PADCONF_SAVE		0x2
arch/arm/mach-omap2/cpuidle34xx.c +1 -1
index 207bc1c..7d82c6bb 100644
@@ -33,7 +33,7 @@
 #include "clockdomain.h"
 
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 #include "common.h"
 
 #ifdef CONFIG_CPU_IDLE
arch/arm/mach-omap2/devices.c +1 -1
index 7b4b932..152c266 100644
@@ -34,7 +34,7 @@
 #include <plat/omap4-keypad.h>
 
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "devices.h"
 
 #define L3_MODULES_MAX_LEN 12
arch/arm/mach-omap2/display.c +1 -1
index db5a88a..0681407 100644
@@ -32,7 +32,7 @@
 
 #include "iomap.h"
 #include "mux.h"
-#include "control.h"
+#include <mach/control.h>
 #include "display.h"
 
 #define DISPC_CONTROL		0x0040
arch/arm/mach-omap2/hsmmc.c +1 -1
index be697d4..33b3d62 100644
@@ -22,7 +22,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "control.h"
+#include <mach/control.h>
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
arch/arm/mach-omap2/id.c +1 -1
index 0389b32..5bb9746 100644
@@ -26,7 +26,7 @@
 
 #include <mach/id.h>
 
-#include "control.h"
+#include <mach/control.h>
 
 static unsigned int omap_revision;
 static const char *cpu_rev;
arch/arm/mach-omap2/include/mach/control.h renamed from arch/arm/mach-omap2/control.h +1 -1
similarity index 99%
rename from arch/arm/mach-omap2/control.h
rename to arch/arm/mach-omap2/include/mach/control.h
index dad2903..cf42764 100644
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-omap2/control.h
+ * arch/arm/mach-omap2/include/mach/control.h
  *
  * OMAP2/3/4 System Control Module definitions
  *
arch/arm/mach-omap2/mcbsp.c +1 -1
index 577cb77..0367035 100644
@@ -25,7 +25,7 @@
 #include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
 
-#include "control.h"
+#include <mach/control.h>
 
 /*
  * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
arch/arm/mach-omap2/mux.c +1 -1
index 3268ee2..f23e6618 100644
@@ -38,7 +38,7 @@
 
 #include <plat/omap_hwmod.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 #include "prm.h"
 
arch/arm/mach-omap2/omap_phy_internal.c +1 -1
index 4c90477..b2c9253 100644
@@ -29,7 +29,7 @@
 #include <linux/usb.h>
 
 #include <plat/usb.h>
-#include "control.h"
+#include <mach/control.h>
 
 /* OMAP control module register for UTMI PHY */
 #define CONTROL_DEV_CONF		0x300
arch/arm/mach-omap2/opp3xxx_data.c +1 -1
index d95f3f9..6dafdbb 100644
@@ -21,7 +21,7 @@
 
 #include <plat/cpu.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "omap_opp_data.h"
 #include "pm.h"
 
arch/arm/mach-omap2/opp4xxx_data.c +1 -1
index 2293ba2..27f823c 100644
@@ -22,7 +22,7 @@
 
 #include <plat/cpu.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "omap_opp_data.h"
 #include "pm.h"
 
arch/arm/mach-omap2/pm24xx.c +1 -1
index facfffc..7ebca30 100644
@@ -49,7 +49,7 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 #include "pm.h"
-#include "control.h"
+#include <mach/control.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
 
arch/arm/mach-omap2/pm34xx.c +1 -1
index 8b43aef..1d2a51c 100644
@@ -49,7 +49,7 @@
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
arch/arm/mach-omap2/prcm.c +1 -1
index 480f40a..fff0b09 100644
@@ -37,7 +37,7 @@
 #include "prminst44xx.h"
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-44xx.h"
-#include "control.h"
+#include <mach/control.h>
 
 void __iomem *prm_base;
 void __iomem *cm_base;
arch/arm/mach-omap2/serial.c +1 -1
index 678dd1d..97b09da5 100644
@@ -39,7 +39,7 @@
 #include "pm.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 
 /*
arch/arm/mach-omap2/sleep34xx.S +1 -1
index 1f62f23..b3f6bfc 100644
@@ -33,7 +33,7 @@
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
 #include "sdrc.h"
-#include "control.h"
+#include <mach/control.h>
 
 /*
  * Registers access definitions
arch/arm/mach-omap2/sr_device.c +1 -1
index a503e1e..48a01f6 100644
@@ -26,7 +26,7 @@
 
 #include "smartreflex.h"
 #include "voltage.h"
-#include "control.h"
+#include <mach/control.h>
 #include "pm.h"
 
 static bool sr_enable_on_init;
arch/arm/mach-omap2/usb-fs.c +1 -1
index 1481078..94d471c 100644
@@ -32,7 +32,7 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 
-#include "control.h"
+#include <mach/control.h>
 #include "mux.h"
 
 #define INT_USB_IRQ_GEN		INT_24XX_USB_IRQ_GEN
arch/arm/mach-omap2/voltage.c +1 -1
index 4dc60e8..d2f0644 100644
@@ -34,7 +34,7 @@
 #include "prm44xx.h"
 #include "prcm44xx.h"
 #include "prminst44xx.h"
-#include "control.h"
+#include <mach/control.h>
 
 #include "voltage.h"
 #include "powerdomain.h"

-- 1.7.7.1.488.ge8e1c

maintainer
#85 lore raw

RFC PATCH v2 2/11 ARM: OMAP: expose control.h to mach area

Quoted 2 lines · Konstantin Baydarov

This patch exposes the definitions under control.h to drivers outside the machine code.

As discussed earlier, this will likely lead into misuse of these registers that will be a big mess to clean up.

Can't you make these private to the driver(s)?

Tony

#86 lore raw

RFC PATCH v2 3/11 mfd: omap: control: core system control driver

In reply to Eduardo Valentin

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.

Changes since previous version:
- omap-control-core: driver is basically the same as arch/arm/mach-omap2/control.c, but resources aren't hardcoded, they are specified in dts file.
- omap-control-core: Control module is a built-in driver - added control module select to ARCH_HAS_CONTROL_MODULE and ARCH_OMAP4. Probably, no configuration option is required!
- omap-control-core: Added early init call that ioremaps control module IOMEM window, this allows
omap-control-core.c API to be called very early, for example from omap_type()
- omap-control-core: Removed device pointer from omap-control-core API arguments, becuase there can be only one instance control module device.

---
 Documentation/devicetree/bindings/mfd/omap_control.txt |   44 +++++
 arch/arm/mach-omap2/Kconfig                            |    1 
 arch/arm/plat-omap/Kconfig                             |    4 
 drivers/mfd/Kconfig                                    |    9 +
 drivers/mfd/Makefile                                   |    1 
 drivers/mfd/omap-control-core.c                        |  141 +++++++++++++++++
 include/linux/mfd/omap_control.h                       |   70 ++++++++
 7 files changed, 270 insertions(+)
Documentation/devicetree/bindings/mfd/omap_control.txt new file +44 -0
Index: linux-2.6/Documentation/devicetree/bindings/mfd/omap_control.txt
===================================================================
@@ -0,0 +1,44 @@
+* 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";
+
+Sub-nodes:
+- bandgap : contains the bandgap node
+
+  The bindings details of individual bandgap device can be found in:
+  Documentation/devicetree/bindings/thermal/omap_bandgap.txt
+
+- usb : contains the usb phy pin control node
+
+  The only required property for this child is:
+    - compatible = "ti,omap4-control-usb";
+
+Examples:
+
+ctrl_module_core: ctrl_module_core at 4a002000 {
+	compatible = "ti,omap4-control";
+	ti,hwmods = "ctrl_module_core";
+	bandgap {
+		compatible = "ti,omap4460-bandgap";
+		interrupts = <0 126 4>; /* talert */
+		ti,tshut-gpio = <86>; /* tshut */
+	};
+	usb {
+		compatible = "ti,omap4-usb-phy";
+	};
+};
arch/arm/mach-omap2/Kconfig +1 -0
Index: linux-2.6/arch/arm/mach-omap2/Kconfig
===================================================================
@@ -52,6 +52,7 @@ config ARCH_OMAP4
 	select PL310_ERRATA_727915
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
+	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: linux-2.6/arch/arm/plat-omap/Kconfig
===================================================================
@@ -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 +9 -0
Index: linux-2.6/drivers/mfd/Kconfig
===================================================================
@@ -822,6 +822,15 @@ 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. This driver
+	  is responsible for creating the control module mfd child,
+	  like USB-pin control, pin muxing, MMC-pbias and DDR IO dynamic
+	  change for off mode.
+
 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: linux-2.6/drivers/mfd/Makefile
===================================================================
@@ -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 +141 -0

141 lines not on this page · raw message

include/linux/mfd/omap_control.h new file +70 -0

70 lines not on this page · raw message

maintainer
#87 lore raw

RFC PATCH v2 3/11 mfd: omap: control: core system control driver

Quoted 10 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.

+++ linux-2.6/drivers/mfd/omap-control-core.c

...

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

Quoted 9 lines
drivers/mfd/omap-control-core.c new file +9 -0
+u32 omap_control_readl(u16 offset)
+{
+	return __raw_readl(omap_control_base + (offset));
+}
+
+void omap_control_writel(u32 val, u16 offset)
+{
+	__raw_writel(val, omap_control_base + (offset));
+}

There should not be any need to have the individual drivers use these. Please instead just set up something where individual drivers register with the control module core, and get their own iobase returned so they can use readl/writel and behave like normal device drivers.

Regards,

Tony

#88 lore raw

RFC PATCH v2 3/11 mfd: omap: control: core system control driver

Hi, Tony.

Quoted 13 lines · Tony Lindgren
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.
+++ linux-2.6/drivers/mfd/omap-control-core.c

...

Quoted 14 lines

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

Quoted 9 lines
drivers/mfd/omap-control-core.c new file +9 -0
+u32 omap_control_readl(u16 offset)
+{
+	return __raw_readl(omap_control_base + (offset));
+}
+
+void omap_control_writel(u32 val, u16 offset)
+{
+	__raw_writel(val, omap_control_base + (offset));
+}

There should not be any need to have the individual drivers use these. Please instead just set up something where individual drivers register with the control module core, and get their own iobase returned so they can use readl/writel and behave like normal device drivers.

IIUC one of the reasons drivers/mfd/omap-control-core.c introduction is replacement of arch/arm/mach-omap2/control.c. control.c provides omap_ctrl_readl/omap_ctrl_writel API which are heavily used in arch/arm/mach-omap2/:
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/usb-fs.c
arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/id.c
...

So,the same API set (omap_control_readl/omap_control_writel) was added to omap-control-core.c.

If omap-control-core.c should only service users from driver/ directory, than I agree - we can remove
omap_control_readl/omap_control_writel from omap-control-core.c.
But IIUC you are agree to "switch" arch/arm/mach-omap2/id.c from control.c to omap-control-core.c. If arch/arm/mach-omap2/id.c is switched to control.c, then I guess all arch/arm/mach-omap2/*.c should be "switched" to omap-control-core.c as well. But this means that omap-control-core.c should provide omap_control_readl/omap_control_writel API.

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