2 * arch/arm/mach-tegra/tegra11_soctherm.c
4 * Copyright (C) 2011-2012 NVIDIA Corporation
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include <linux/debugfs.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/list.h>
25 #include <linux/spinlock.h>
26 #include <linux/delay.h>
27 #include <linux/err.h>
29 #include <linux/clk.h>
30 #include <linux/cpufreq.h>
31 #include <linux/seq_file.h>
32 #include <linux/irq.h>
33 #include <linux/interrupt.h>
35 #include <mach/iomap.h>
38 #define CONF_STAT_MEM0 0x8
39 #define CONF_STAT_MEM0_UP_THRESH_SHIFT 17
40 #define CONF_STAT_MEM0_UP_THRESH_MASK 0xff
41 #define CONF_STAT_MEM0_DN_THRESH_SHIFT 9
42 #define CONF_STAT_MEM0_DN_THRESH_MASK 0xff
43 #define CONF_STAT_MEM0_EN_SHIFT 8
44 #define CONF_STAT_MEM0_EN_MASK 0x1
45 #define CONF_STAT_MEM0_CPU_THROT_SHIFT 5
46 #define CONF_STAT_MEM0_CPU_THROT_MASK 0x3
47 #define CONF_STAT_MEM0_STATUS_SHIFT 0
48 #define CONF_STAT_MEM0_STATUS_MASK 0x3
50 #define THERMTRIP 0x80
51 #define THERMTRIP_ANY_EN_SHIFT 28
52 #define THERMTRIP_ANY_EN_MASK 0x1
53 #define THERMTRIP_CPU_EN_SHIFT 25
54 #define THERMTRIP_CPU_EN_MASK 0x1
55 #define THERMTRIP_CPU_THRESH_SHIFT 8
56 #define THERMTRIP_CPU_THRESH_MASK 0xff
58 #define TS_MEM0_CONFIG0 0x140
59 #define TS_MEM0_CONFIG0_TALL_SHIFT 8
60 #define TS_MEM0_CONFIG0_TALL_MASK 0xfffff
62 #define TS_MEM0_CONFIG1 0x144
63 #define TS_MEM0_CONFIG1_EN_SHIFT 31
64 #define TS_MEM0_CONFIG1_EN_MASK 0x1
65 #define TS_MEM0_CONFIG1_TIDDQ_SHIFT 15
66 #define TS_MEM0_CONFIG1_TIDDQ_MASK 0x3f
67 #define TS_MEM0_CONFIG1_TEN_COUNT_SHIFT 24
68 #define TS_MEM0_CONFIG1_TEN_COUNT_MASK 0x3f
69 #define TS_MEM0_CONFIG1_TSAMPLE_SHIFT 0
70 #define TS_MEM0_CONFIG1_TSAMPLE_MASK 0x3ff
72 #define TS_MEM0_CONFIG2 0x148
73 #define TS_MEM0_CONFIG2_THERM_A_SHIFT 16
74 #define TS_MEM0_CONFIG2_THERM_A_MASK 0xffff
75 #define TS_MEM0_CONFIG2_THERM_B_SHIFT 0
76 #define TS_MEM0_CONFIG2_THERM_B_MASK 0xffff
78 #define TS_MEM0_STATUS0 0x14c
79 #define TS_MEM0_STATUS0_CAPTURE_SHIFT 0
80 #define TS_MEM0_STATUS0_CAPTURE_MASK 0xffff
82 #define TS_MEM0_STATUS1 0x150
84 #define TS_MEM0_STATUS2 0x154
87 #define TS_PDIV_MEM_SHIFT 4
88 #define TS_PDIV_MEM_MASK 0xf
91 #define UP_STATS_L0 0x10
92 #define DN_STATS_L0 0x14
94 #define INTR_STATUS 0x84
97 #define INTR_EN_CU0_SHIFT 8
98 #define INTR_EN_CD0_SHIFT 9
100 #define INTR_DIS 0x8c
101 #define LOCK_CTL 0x90
102 #define STATS_CTL 0x94
104 #define REG_SET(r,_name,val) \
105 ((r)&~(_name##_MASK<<_name##_SHIFT))|(((val)&_name##_MASK)<<_name##_SHIFT)
107 #define REG_GET(r,_name) \
108 (((r)&(_name##_MASK<<_name##_SHIFT))>>_name##_SHIFT)
110 static void __iomem *reg_soctherm_base = IO_ADDRESS(TEGRA_SOCTHERM_BASE);
112 #define soctherm_writel(value, reg) \
113 __raw_writel(value, (u32)reg_soctherm_base + (reg))
114 #define soctherm_readl(reg) \
115 __raw_readl((u32)reg_soctherm_base + (reg))
117 static struct dentry *tegra_soctherm_root;
119 int soctherm_set_limits(long lo_limit_milli, long hi_limit_milli)
121 u32 r = soctherm_readl(CONF_STAT_MEM0);
122 r = REG_SET(r, CONF_STAT_MEM0_DN_THRESH, lo_limit_milli/1000);
123 r = REG_SET(r, CONF_STAT_MEM0_UP_THRESH, hi_limit_milli/1000);
124 soctherm_writel(r, CONF_STAT_MEM0);
126 soctherm_writel(1<<INTR_EN_CU0_SHIFT, INTR_EN);
127 soctherm_writel(1<<INTR_EN_CD0_SHIFT, INTR_EN);
132 int soctherm_get_temp(long *temp)
137 int soctherm_set_shutdown(long shutdown_temp_milli)
139 u32 r = soctherm_readl(THERMTRIP);
140 r = REG_SET(r, THERMTRIP_CPU_THRESH, shutdown_temp_milli/1000);
141 r = REG_SET(r, THERMTRIP_CPU_EN, 1);
142 soctherm_writel(r, THERMTRIP);
147 static int pdiv_set(void *data, u64 val)
150 r = REG_SET(0, TS_PDIV_MEM, val);
151 soctherm_writel(r, TS_PDIV);
155 static int pdiv_get(void *data, u64 *val)
157 *val = (u64)soctherm_readl(TS_PDIV);
161 DEFINE_SIMPLE_ATTRIBUTE(pdiv_fops,
166 static int regs_show(struct seq_file *s, void *data)
170 r = soctherm_readl(CONF_STAT_MEM0);
171 seq_printf(s, "SOC_THERM_THERMCTL_LEVEL0_GROUP_MEM_0: 0x%x\n", r);
173 r = soctherm_readl(TS_MEM0_STATUS0);
174 seq_printf(s, "SOC_THERM_TSENSOR_MEM0_STATUS0_0: 0x%x\n", r);
176 r = soctherm_readl(TS_MEM0_STATUS1);
177 seq_printf(s, "SOC_THERM_TSENSOR_MEM0_STATUS1_0: 0x%x\n", r);
179 r = soctherm_readl(TS_MEM0_CONFIG0);
180 seq_printf(s, "SOC_THERM_TSENSOR_MEM0_CONFIG0_0: 0x%x\n", r);
182 r = soctherm_readl(TS_MEM0_CONFIG1);
183 seq_printf(s, "SOC_THERM_TSENSOR_MEM0_CONFIG1_0: 0x%x\n", r);
185 r = soctherm_readl(TS_MEM0_CONFIG2);
186 seq_printf(s, "SOC_THERM_TSENSOR_MEM0_CONFIG2_0: 0x%x\n", r);
188 r = soctherm_readl(INTR_STATUS);
189 seq_printf(s, "SOC_THERM_THERMCTL_INTR_STATUS_0: 0x%x\n", r);
194 static int regs_open(struct inode *inode, struct file *file)
196 return single_open(file, regs_show, inode->i_private);
199 static const struct file_operations regs_fops = {
203 .release = single_release,
206 static irqreturn_t soctherm_isr(int irq, void *arg_data)
211 int __init tegra11_soctherm_init(void)
216 r = soctherm_readl(CONF_STAT_MEM0);
217 r = REG_SET(r, CONF_STAT_MEM0_EN, 1);
218 soctherm_writel(r, CONF_STAT_MEM0);
220 r = REG_SET(0, TS_MEM0_CONFIG0_TALL, 15);
221 soctherm_writel(r, TS_MEM0_CONFIG0);
223 r = REG_SET(0, TS_MEM0_CONFIG1_TIDDQ, 1);
224 r = REG_SET(r, TS_MEM0_CONFIG1_EN, 1);
225 r = REG_SET(r, TS_MEM0_CONFIG1_TEN_COUNT, 1);
226 r = REG_SET(r, TS_MEM0_CONFIG1_TSAMPLE, 10);
227 soctherm_writel(r, TS_MEM0_CONFIG1);
229 r = REG_SET(0, TS_MEM0_CONFIG2_THERM_A, 114);
230 r = REG_SET(r, TS_MEM0_CONFIG2_THERM_B, 0);
231 soctherm_writel(r, TS_MEM0_CONFIG2);
234 soctherm_set_limits(20000, 40000);
236 err = request_irq(INT_THERMAL, soctherm_isr,
237 IRQF_ONESHOT, "soctherm", NULL);
239 tegra_soctherm_root = debugfs_create_dir("tegra_soctherm", 0);
240 debugfs_create_file("pdiv", 0644, tegra_soctherm_root, NULL, &pdiv_fops);
241 debugfs_create_file("regs", 0644, tegra_soctherm_root, NULL, ®s_fops);