ARM: tegra: cardhu: switch off PMU at high temperature
venu byravarasu [Wed, 3 Aug 2011 11:21:57 +0000 (16:21 +0530)]
Add board support needed for PMU switch off when tsensor
detects temperature > TH3 threshold set.

bug 850047

Original-Change-Id: I7a283cedc735264dd8ea52801f7f1a103e9293cb
Reviewed-on: http://git-master/r/41531
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

Rebase-Id: Rc4bf2206a7207e28434b46baed442cd6f2797fbc

arch/arm/mach-tegra/board-cardhu-power.c
arch/arm/mach-tegra/board-cardhu.c
arch/arm/mach-tegra/board-cardhu.h
arch/arm/mach-tegra/board-enterprise-power.c
arch/arm/mach-tegra/board-enterprise.c
arch/arm/mach-tegra/board-enterprise.h
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/include/mach/tsensor.h
arch/arm/mach-tegra/tegra3_tsensor.c

index bab3e72..319b9b1 100644 (file)
@@ -33,6 +33,7 @@
 #include <mach/irqs.h>
 #include <mach/pinmux.h>
 #include <mach/edp.h>
+#include <mach/tsensor.h>
 
 #include "gpio-names.h"
 #include "board.h"
@@ -994,6 +995,22 @@ int __init cardhu_power_off_init(void)
        return 0;
 }
 
+static struct tegra_tsensor_pmu_data  tpdata = {
+       .poweroff_reg_addr = 0x3F,
+       .poweroff_reg_data = 0x80,
+       .reset_tegra = 1,
+       .controller_type = 0,
+       .i2c_controller_id = 4,
+       .pinmux = 0,
+       .pmu_16bit_ops = 0,
+       .pmu_i2c_addr = 0x2D,
+};
+
+void __init cardhu_tsensor_init(void)
+{
+       tegra3_tsensor_init(&tpdata);
+}
+
 #ifdef CONFIG_TEGRA_EDP_LIMITS
 
 int __init cardhu_edp_init(void)
index 09e9f96..c468415 100644 (file)
@@ -739,7 +739,7 @@ static void __init tegra_cardhu_init(void)
        cardhu_edp_init();
 #endif
        cardhu_uart_init();
-       tegra_tsensor_init();
+       cardhu_tsensor_init();
        platform_add_devices(cardhu_devices, ARRAY_SIZE(cardhu_devices));
        cardhu_sdhci_init();
        cardhu_regulator_init();
index 01a29c5..711fadb 100644 (file)
@@ -170,6 +170,7 @@ int cardhu_emc_init(void);
 int cardhu_power_off_init(void);
 int cardhu_edp_init(void);
 int cardhu_pmon_init(void);
+void __init cardhu_tsensor_init(void);
 
 /* Baseband GPIO addresses */
 #define BB_GPIO_BB_EN                  TEGRA_GPIO_PR5
index 52ef8fc..edc25a3 100644 (file)
@@ -400,6 +400,11 @@ static void enterprise_power_off(void)
        while(1);
 }
 
+void __init enterprise_tsensor_init(void)
+{
+/* To be implemented */
+}
+
 int __init enterprise_regulator_init(void)
 {
        void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
index 90677ae..430e685 100644 (file)
@@ -476,7 +476,7 @@ static void __init tegra_enterprise_init(void)
        enterprise_pinmux_init();
        enterprise_i2c_init();
        enterprise_uart_init();
-       tegra_tsensor_init();
+       enterprise_tsensor_init();
        platform_add_devices(enterprise_devices, ARRAY_SIZE(enterprise_devices));
        enterprise_regulator_init();
        enterprise_sdhci_init();
index 6d82274..296250f 100644 (file)
@@ -37,6 +37,7 @@ int enterprise_regulator_init(void);
 int enterprise_modem_init(void);
 int enterprise_suspend_init(void);
 int enterprise_edp_init(void);
+void __init enterprise_tsensor_init(void);
 
 /* Touchscreen GPIO addresses   */
 #ifdef CONFIG_TOUCHSCREEN_ATMEL_MT_T9
index 1a0be73..942a186 100644 (file)
@@ -44,7 +44,6 @@ int __init tegra_pcie_init(bool init_port0, bool init_port1);
 void tegra_init_cache(void);
 void __init tegra_release_bootloader_fb(void);
 void __init tegra_protected_aperture_init(unsigned long aperture);
-void __init tegra_tsensor_init(void);
 void tegra_move_framebuffer(unsigned long to, unsigned long from,
        unsigned long size);
 bool is_tegra_debug_uartport_hs(void);
index d4d8c64..63a9c96 100644 (file)
 
 #define MAX_ZONES      16
 
+struct tegra_tsensor_pmu_data {
+       u8 poweroff_reg_data;
+       u8 poweroff_reg_addr;
+       u8 reset_tegra;
+       u8 controller_type;
+       u8 i2c_controller_id;
+       u8 pinmux;
+       u8 pmu_16bit_ops;
+       u8 pmu_i2c_addr;
+};
+
 struct tegra_tsensor_platform_data {
        int sw_intr_temperature;
        int hw_clk_div_temperature;
@@ -36,5 +47,7 @@ struct tegra_tsensor_platform_data {
        void (*alarm_fn)(bool raised);
 };
 
+void __init tegra3_tsensor_init(struct tegra_tsensor_pmu_data *);
+
 #endif /* __MACH_TEGRA_TSENSOR_H */
 
index 0195132..00c3b6d 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include "board.h"
 
 #ifdef CONFIG_SENSORS_TEGRA_TSENSOR
+#include <linux/io.h>
+#include <linux/ioport.h>
+
+#include <mach/iomap.h>
 #include <mach/tsensor.h>
 #include <mach/tegra_fuse.h>
 
+#include "board.h"
 #include "devices.h"
 #include "fuse.h"
 
@@ -36,10 +40,35 @@ static struct tegra_tsensor_platform_data tsensor_data = {
 #define TSENSOR_FUSE_REVISION_DECIMAL 8
 #define TSENSOR_FUSE_REVISION_INTEGER 0
 
-void __init tegra_tsensor_init(void)
+/* scratch register offsets needed for powering off PMU */
+#define SCRATCH54_OFFSET                       0x258
+#define SCRATCH55_OFFSET                       0x25C
+
+/* scratch 54 register bit field offsets */
+#define PMU_OFF_DATA_OFFSET                    8
+
+/* scratch 55 register bit field offsets */
+#define RESET_TEGRA_OFFSET                     31
+#define CONTROLLER_TYPE_OFFSET                 30
+#define I2C_CONTROLLER_ID_OFFSET               27
+#define PINMUX_OFFSET                          24
+#define CHECKSUM_OFFSET                                16
+#define PMU_16BIT_SUPPORT_OFFSET               15
+/* scratch 55 register bit field masks */
+#define RESET_TEGRA_MASK                       0x1
+#define CONTROLLER_TYPE_MASK                   0x1
+#define I2C_CONTROLLER_ID_MASK                 0x7
+#define PINMUX_MASK                            0x7
+#define CHECKSUM_MASK                          0xff
+#define PMU_16BIT_SUPPORT_MASK                 0x1
+
+
+void __init tegra3_tsensor_init(struct tegra_tsensor_pmu_data *data)
 {
        unsigned int reg, fuse_rev_integer, fuse_rev_decimal;
        int err;
+       u32 val, checksum;
+       void __iomem *pMem = NULL;
        /* tsensor driver is instantiated based on fuse revision */
        err = tegra_fuse_get_revision(&reg);
        if (err)
@@ -50,6 +79,47 @@ void __init tegra_tsensor_init(void)
                fuse_rev_decimal);
        if ((fuse_rev_decimal >= TSENSOR_FUSE_REVISION_DECIMAL) &&
                (fuse_rev_integer >= TSENSOR_FUSE_REVISION_INTEGER)) {
+
+               if (!request_mem_region(TEGRA_PMC_BASE + SCRATCH54_OFFSET,
+                       8, "tegra-tsensor")) {
+                       pr_err(" [%s, line=%d]: Error mem busy\n",
+                               __func__, __LINE__);
+               }
+
+               pMem = ioremap(TEGRA_PMC_BASE + SCRATCH54_OFFSET, 8);
+               if (!pMem) {
+                       pr_err(" [%s, line=%d]: can't ioremap "
+                               "pmc iomem\n", __FILE__, __LINE__);
+               }
+
+               /*
+                       Fill scratch registers to power off the device
+                       in case if temperature crosses threshold TH3
+               */
+               val = (data->poweroff_reg_data << PMU_OFF_DATA_OFFSET) |
+                       data->poweroff_reg_addr;
+               writel(val, pMem);
+
+               val = ((data->reset_tegra & RESET_TEGRA_MASK) <<
+                               RESET_TEGRA_OFFSET) |
+                       ((data->controller_type & CONTROLLER_TYPE_MASK) <<
+                               CONTROLLER_TYPE_OFFSET) |
+                       ((data->i2c_controller_id & I2C_CONTROLLER_ID_MASK) <<
+                               I2C_CONTROLLER_ID_OFFSET) |
+                       ((data->pinmux & PINMUX_MASK) << PINMUX_OFFSET) |
+                       ((data->pmu_16bit_ops & PMU_16BIT_SUPPORT_MASK) <<
+                               PMU_16BIT_SUPPORT_OFFSET) |
+                       data->pmu_i2c_addr;
+
+               checksum = data->poweroff_reg_addr +
+                       data->poweroff_reg_data + (val & 0xFF) +
+                       ((val >> 8) & 0xFF) + ((val >> 24) & 0xFF);
+               checksum &= 0xFF;
+               checksum = 0x100 - checksum;
+
+               val |= (checksum << CHECKSUM_OFFSET);
+               writel(val, pMem + 4);
+
                /* set platform data for device before register */
                tegra_tsensor_device.dev.platform_data = &tsensor_data;
                platform_device_register(&tegra_tsensor_device);
@@ -59,6 +129,6 @@ errLabel:
 }
 
 #else
-void __init tegra_tsensor_init(void) { }
+void __init tegra3_tsensor_init(void) { }
 #endif