ARM: tegra: soctherm: Create soctherm driver
Joshua Primero [Mon, 23 Jul 2012 19:30:58 +0000 (12:30 -0700)]
Created initial soctherm drivers. Initialized soctherm
registers.

Change-Id: Ie32c4635c0fb9495a4e1c599fbbcf4cfb43b506b
Signed-off-by: Joshua Primero <jprimero@nvidia.com>
Reviewed-on: http://git-master/r/120545
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-curacao-power.c
arch/arm/mach-tegra/board-curacao.c
arch/arm/mach-tegra/board-curacao.h
arch/arm/mach-tegra/include/mach/iomap.h
arch/arm/mach-tegra/include/mach/irqs.h
arch/arm/mach-tegra/tegra11_soctherm.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra11_soctherm.h [new file with mode: 0644]

index 0c6d3f8..7074aaa 100644 (file)
@@ -105,6 +105,7 @@ obj-$(CONFIG_TEGRA_SYSTEM_DMA)              += dma.o apbio.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)                 += pcie.o
 obj-$(CONFIG_USB_SUPPORT)               += usb_phy.o
+obj-$(CONFIG_ARCH_TEGRA_11x_SOC)        += tegra11_soctherm.o
 ifeq ($(CONFIG_TEGRA_THERMAL_THROTTLE),y)
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_throttle.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += tegra3_throttle.o
index 4d9a2d1..8723fea 100644 (file)
@@ -38,6 +38,7 @@
 #include "board-curacao.h"
 #include "tegra_cl_dvfs.h"
 #include "gpio-names.h"
+#include "tegra11_soctherm.h"
 
 #define PMC_CTRL                0x0
 #define PMC_CTRL_INTR_LOW       (1 << 17)
@@ -492,6 +493,11 @@ int __init curacao_suspend_init(void)
        return 0;
 }
 
+int __init curacao_soctherm_init(void)
+{
+       return tegra11_soctherm_init();
+}
+
 #ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
 
 #define COSIM_SHUTDOWN_REG         0x538f0ffc
index cc7efb6..f677b82 100644 (file)
@@ -615,6 +615,7 @@ static void __init tegra_curacao_init(void)
        curacao_hs_uart_init();
        curacao_bt_rfkill();
        curacao_sensors_init();
+       curacao_soctherm_init();
 }
 
 static void __init tegra_curacao_reserve(void)
index 17f5255..ff6a0c8 100644 (file)
@@ -44,6 +44,7 @@ int curacao_sdhci_init(void);
 int curacao_pinmux_init(void);
 int curacao_panel_init(void);
 int curacao_sensors_init(void);
+int curacao_soctherm_init(void);
 
 #ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
 #define CURACAO_BOARD_NAME "curacao_sim"
index 3aa18f7..5b68b58 100644 (file)
 #define TEGRA_CSITE_BASE               0x70040000
 #define TEGRA_CSITE_SIZE               SZ_256K
 
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+#define TEGRA_SOCTHERM_BASE            0x700E2000
+#define TEGRA_SOCTHERM_SIZE            SZ_4K
+#endif
+
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
 
 #define TEGRA_USB_BASE                 0xC5000000
index 2897747..9918fea 100644 (file)
 #define INT_ACTMON                     (INT_SEC_BASE + 13)
 #define INT_UARTC                      (INT_SEC_BASE + 14)
 #define INT_MIPI                       (INT_SEC_BASE + 15)
+#define INT_THERMAL                    (INT_SEC_BASE + 16)
 #ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
 #define IRQ_ETH                         (INT_SEC_BASE + 16)
 #endif
diff --git a/arch/arm/mach-tegra/tegra11_soctherm.c b/arch/arm/mach-tegra/tegra11_soctherm.c
new file mode 100644 (file)
index 0000000..f84197d
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * arch/arm/mach-tegra/tegra11_soctherm.c
+ *
+ * Copyright (C) 2011-2012 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <mach/iomap.h>
+
+
+#define CONF_STAT_MEM0                 0x8
+#define CONF_STAT_MEM0_UP_THRESH_SHIFT 17
+#define CONF_STAT_MEM0_UP_THRESH_MASK  0xff
+#define CONF_STAT_MEM0_DN_THRESH_SHIFT 9
+#define CONF_STAT_MEM0_DN_THRESH_MASK  0xff
+#define CONF_STAT_MEM0_EN_SHIFT                8
+#define CONF_STAT_MEM0_EN_MASK         0x1
+#define CONF_STAT_MEM0_CPU_THROT_SHIFT 5
+#define CONF_STAT_MEM0_CPU_THROT_MASK  0x3
+#define CONF_STAT_MEM0_STATUS_SHIFT    0
+#define CONF_STAT_MEM0_STATUS_MASK     0x3
+
+#define THERMTRIP                      0x80
+#define THERMTRIP_ANY_EN_SHIFT         28
+#define THERMTRIP_ANY_EN_MASK          0x1
+#define THERMTRIP_CPU_EN_SHIFT         25
+#define THERMTRIP_CPU_EN_MASK          0x1
+#define THERMTRIP_CPU_THRESH_SHIFT     8
+#define THERMTRIP_CPU_THRESH_MASK      0xff
+
+#define TS_MEM0_CONFIG0                        0x140
+#define TS_MEM0_CONFIG0_TALL_SHIFT     8
+#define TS_MEM0_CONFIG0_TALL_MASK      0xfffff
+
+#define TS_MEM0_CONFIG1                        0x144
+#define TS_MEM0_CONFIG1_EN_SHIFT       31
+#define TS_MEM0_CONFIG1_EN_MASK                0x1
+#define TS_MEM0_CONFIG1_TIDDQ_SHIFT    15
+#define TS_MEM0_CONFIG1_TIDDQ_MASK     0x3f
+#define TS_MEM0_CONFIG1_TEN_COUNT_SHIFT        24
+#define TS_MEM0_CONFIG1_TEN_COUNT_MASK 0x3f
+#define TS_MEM0_CONFIG1_TSAMPLE_SHIFT  0
+#define TS_MEM0_CONFIG1_TSAMPLE_MASK   0x3ff
+
+#define TS_MEM0_CONFIG2                        0x148
+#define TS_MEM0_CONFIG2_THERM_A_SHIFT  16
+#define TS_MEM0_CONFIG2_THERM_A_MASK   0xffff
+#define TS_MEM0_CONFIG2_THERM_B_SHIFT  0
+#define TS_MEM0_CONFIG2_THERM_B_MASK   0xffff
+
+#define TS_MEM0_STATUS0                        0x14c
+#define TS_MEM0_STATUS0_CAPTURE_SHIFT  0
+#define TS_MEM0_STATUS0_CAPTURE_MASK   0xffff
+
+#define TS_MEM0_STATUS1                        0x150
+
+#define TS_MEM0_STATUS2                        0x154
+
+#define TS_PDIV                                0x1c0
+#define TS_PDIV_MEM_SHIFT              4
+#define TS_PDIV_MEM_MASK               0xf
+
+
+#define UP_STATS_L0            0x10
+#define DN_STATS_L0            0x14
+
+#define INTR_STATUS            0x84
+
+#define INTR_EN                        0x88
+#define INTR_EN_CU0_SHIFT      8
+#define INTR_EN_CD0_SHIFT      9
+
+#define INTR_DIS               0x8c
+#define LOCK_CTL               0x90
+#define STATS_CTL              0x94
+
+#define REG_SET(r,_name,val) \
+       ((r)&~(_name##_MASK<<_name##_SHIFT))|(((val)&_name##_MASK)<<_name##_SHIFT)
+
+#define REG_GET(r,_name) \
+       (((r)&(_name##_MASK<<_name##_SHIFT))>>_name##_SHIFT)
+
+static void __iomem *reg_soctherm_base = IO_ADDRESS(TEGRA_SOCTHERM_BASE);
+
+#define soctherm_writel(value, reg) \
+       __raw_writel(value, (u32)reg_soctherm_base + (reg))
+#define soctherm_readl(reg) \
+       __raw_readl((u32)reg_soctherm_base + (reg))
+
+static struct dentry *tegra_soctherm_root;
+
+int soctherm_set_limits(long lo_limit_milli, long hi_limit_milli)
+{
+       u32 r = soctherm_readl(CONF_STAT_MEM0);
+       r = REG_SET(r, CONF_STAT_MEM0_DN_THRESH, lo_limit_milli/1000);
+       r = REG_SET(r, CONF_STAT_MEM0_UP_THRESH, hi_limit_milli/1000);
+       soctherm_writel(r, CONF_STAT_MEM0);
+
+       soctherm_writel(1<<INTR_EN_CU0_SHIFT, INTR_EN);
+       soctherm_writel(1<<INTR_EN_CD0_SHIFT, INTR_EN);
+
+       return 0;
+}
+
+int soctherm_get_temp(long *temp)
+{
+       return 0;
+}
+
+int soctherm_set_shutdown(long shutdown_temp_milli)
+{
+       u32 r = soctherm_readl(THERMTRIP);
+       r = REG_SET(r, THERMTRIP_CPU_THRESH, shutdown_temp_milli/1000);
+       r = REG_SET(r, THERMTRIP_CPU_EN, 1);
+       soctherm_writel(r, THERMTRIP);
+
+       return 0;
+}
+
+static int pdiv_set(void *data, u64 val)
+{
+       u32 r;
+       r = REG_SET(0, TS_PDIV_MEM, val);
+       soctherm_writel(r, TS_PDIV);
+       return 0;
+}
+
+static int pdiv_get(void *data, u64 *val)
+{
+       *val = (u64)soctherm_readl(TS_PDIV);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pdiv_fops,
+                       pdiv_get,
+                       pdiv_set,
+                       "%llu\n");
+
+static int regs_show(struct seq_file *s, void *data)
+{
+       u32 r;
+
+       r = soctherm_readl(CONF_STAT_MEM0);
+       seq_printf(s, "SOC_THERM_THERMCTL_LEVEL0_GROUP_MEM_0: 0x%x\n", r);
+
+       r = soctherm_readl(TS_MEM0_STATUS0);
+       seq_printf(s, "SOC_THERM_TSENSOR_MEM0_STATUS0_0:      0x%x\n", r);
+
+       r = soctherm_readl(TS_MEM0_STATUS1);
+       seq_printf(s, "SOC_THERM_TSENSOR_MEM0_STATUS1_0:      0x%x\n", r);
+
+       r = soctherm_readl(TS_MEM0_CONFIG0);
+       seq_printf(s, "SOC_THERM_TSENSOR_MEM0_CONFIG0_0:      0x%x\n", r);
+
+       r = soctherm_readl(TS_MEM0_CONFIG1);
+       seq_printf(s, "SOC_THERM_TSENSOR_MEM0_CONFIG1_0:      0x%x\n", r);
+
+       r = soctherm_readl(TS_MEM0_CONFIG2);
+       seq_printf(s, "SOC_THERM_TSENSOR_MEM0_CONFIG2_0:      0x%x\n", r);
+
+       r = soctherm_readl(INTR_STATUS);
+       seq_printf(s, "SOC_THERM_THERMCTL_INTR_STATUS_0:      0x%x\n", r);
+
+       return 0;
+}
+
+static int regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, regs_show, inode->i_private);
+}
+
+static const struct file_operations regs_fops = {
+       .open           = regs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static irqreturn_t soctherm_isr(int irq, void *arg_data)
+{
+       return IRQ_HANDLED;
+}
+
+int __init tegra11_soctherm_init(void)
+{
+       int err;
+       u32 r;
+
+       r = soctherm_readl(CONF_STAT_MEM0);
+       r = REG_SET(r, CONF_STAT_MEM0_EN, 1);
+       soctherm_writel(r, CONF_STAT_MEM0);
+
+       r = REG_SET(0, TS_MEM0_CONFIG0_TALL, 15);
+       soctherm_writel(r, TS_MEM0_CONFIG0);
+
+       r = REG_SET(0, TS_MEM0_CONFIG1_TIDDQ, 1);
+       r = REG_SET(r, TS_MEM0_CONFIG1_EN, 1);
+       r = REG_SET(r, TS_MEM0_CONFIG1_TEN_COUNT, 1);
+       r = REG_SET(r, TS_MEM0_CONFIG1_TSAMPLE, 10);
+       soctherm_writel(r, TS_MEM0_CONFIG1);
+
+       r = REG_SET(0, TS_MEM0_CONFIG2_THERM_A, 114);
+       r = REG_SET(r, TS_MEM0_CONFIG2_THERM_B, 0);
+       soctherm_writel(r, TS_MEM0_CONFIG2);
+
+
+       soctherm_set_limits(20000, 40000);
+
+       err = request_irq(INT_THERMAL, soctherm_isr,
+                               IRQF_ONESHOT, "soctherm", NULL);
+
+       tegra_soctherm_root = debugfs_create_dir("tegra_soctherm", 0);
+       debugfs_create_file("pdiv", 0644, tegra_soctherm_root, NULL, &pdiv_fops);
+       debugfs_create_file("regs", 0644, tegra_soctherm_root, NULL, &regs_fops);
+
+       return 0;
+}
+
diff --git a/arch/arm/mach-tegra/tegra11_soctherm.h b/arch/arm/mach-tegra/tegra11_soctherm.h
new file mode 100644 (file)
index 0000000..4884333
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-tegra/tegra3_tsensor.h
+ *
+ * Tegra tsensor header file
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 __MACH_TEGRA_TEGRA3_SOCTHERM_H
+#define __MACH_TEGRA_TEGRA3_SOCTHERM_H
+
+int __init tegra11_soctherm_init(void);
+
+#endif