summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/board-curacao-power.c6
-rw-r--r--arch/arm/mach-tegra/board-curacao.c1
-rw-r--r--arch/arm/mach-tegra/board-curacao.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/iomap.h5
-rw-r--r--arch/arm/mach-tegra/include/mach/irqs.h1
-rw-r--r--arch/arm/mach-tegra/tegra11_soctherm.c245
-rw-r--r--arch/arm/mach-tegra/tegra11_soctherm.h24
8 files changed, 284 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 0c6d3f861604..7074aaae1d5f 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -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
diff --git a/arch/arm/mach-tegra/board-curacao-power.c b/arch/arm/mach-tegra/board-curacao-power.c
index 4d9a2d1f729a..8723fea197cc 100644
--- a/arch/arm/mach-tegra/board-curacao-power.c
+++ b/arch/arm/mach-tegra/board-curacao-power.c
@@ -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
diff --git a/arch/arm/mach-tegra/board-curacao.c b/arch/arm/mach-tegra/board-curacao.c
index cc7efb6dc9cc..f677b8247346 100644
--- a/arch/arm/mach-tegra/board-curacao.c
+++ b/arch/arm/mach-tegra/board-curacao.c
@@ -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)
diff --git a/arch/arm/mach-tegra/board-curacao.h b/arch/arm/mach-tegra/board-curacao.h
index 17f5255a056a..ff6a0c865b08 100644
--- a/arch/arm/mach-tegra/board-curacao.h
+++ b/arch/arm/mach-tegra/board-curacao.h
@@ -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"
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index 3aa18f7beee0..5b68b58e6040 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -535,6 +535,11 @@
#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
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
index 2897747dca29..9918fea6addb 100644
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ b/arch/arm/mach-tegra/include/mach/irqs.h
@@ -430,6 +430,7 @@
#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
index 000000000000..f84197dd3309
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra11_soctherm.c
@@ -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
index 000000000000..488433355816
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra11_soctherm.h
@@ -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