aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/tegra3_tsensor.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/tegra3_tsensor.c')
-rw-r--r--arch/arm/mach-tegra/tegra3_tsensor.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra3_tsensor.c b/arch/arm/mach-tegra/tegra3_tsensor.c
new file mode 100644
index 00000000000..01d3cd7ec62
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra3_tsensor.c
@@ -0,0 +1,187 @@
1/*
2 * arch/arm/mach-tegra/tegra3_tsensor.c
3 *
4 * Copyright (C) 2011 NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/ioport.h>
21#include <linux/slab.h>
22
23#include <mach/tsensor.h>
24#include <mach/tegra_fuse.h>
25#include <mach/iomap.h>
26#include <mach/thermal.h>
27#include <mach/tsensor.h>
28
29#include "devices.h"
30#include "tegra3_tsensor.h"
31
32/* fuse revision constants used for tsensor */
33#define TSENSOR_FUSE_REVISION_DECIMAL 8
34#define TSENSOR_FUSE_REVISION_INTEGER 0
35
36/* scratch register offsets needed for powering off PMU */
37#define SCRATCH54_OFFSET 0x258
38#define SCRATCH55_OFFSET 0x25C
39
40/* scratch 54 register bit field offsets */
41#define PMU_OFF_DATA_OFFSET 8
42
43/* scratch 55 register bit field offsets */
44#define RESET_TEGRA_OFFSET 31
45#define CONTROLLER_TYPE_OFFSET 30
46#define I2C_CONTROLLER_ID_OFFSET 27
47#define PINMUX_OFFSET 24
48#define CHECKSUM_OFFSET 16
49#define PMU_16BIT_SUPPORT_OFFSET 15
50/* scratch 55 register bit field masks */
51#define RESET_TEGRA_MASK 0x1
52#define CONTROLLER_TYPE_MASK 0x1
53#define I2C_CONTROLLER_ID_MASK 0x7
54#define PINMUX_MASK 0x7
55#define CHECKSUM_MASK 0xff
56#define PMU_16BIT_SUPPORT_MASK 0x1
57
58#define TSENSOR_OFFSET (4000 + 5000)
59
60static int tsensor_get_temp(void *vdata, long *milli_temp)
61{
62 struct tegra_tsensor_data *data = vdata;
63 return tsensor_thermal_get_temp(data, milli_temp);
64}
65
66static int tsensor_get_temp_low(void *vdata, long *milli_temp)
67{
68 struct tegra_tsensor_data *data = vdata;
69 return tsensor_thermal_get_temp_low(data, milli_temp);
70}
71
72static int tsensor_set_limits(void *vdata,
73 long lo_limit_milli,
74 long hi_limit_milli)
75{
76 struct tegra_tsensor_data *data = vdata;
77 return tsensor_thermal_set_limits(data,
78 lo_limit_milli,
79 hi_limit_milli);
80}
81
82static int tsensor_set_alert(void *vdata,
83 void (*alert_func)(void *),
84 void *alert_data)
85{
86 struct tegra_tsensor_data *data = vdata;
87 return tsensor_thermal_set_alert(data, alert_func, alert_data);
88}
89
90static int tsensor_set_shutdown_temp(void *vdata, long shutdown_temp_milli)
91{
92 struct tegra_tsensor_data *data = vdata;
93 return tsensor_thermal_set_shutdown_temp(data, shutdown_temp_milli);
94}
95
96static void tegra3_tsensor_probe_callback(struct tegra_tsensor_data *data)
97{
98 struct tegra_thermal_device *thermal_device;
99
100 thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
101 GFP_KERNEL);
102
103 if (!thermal_device) {
104 pr_err("unable to allocate thermal device\n");
105 return;
106 }
107
108 thermal_device->name = "tsensor";
109 thermal_device->data = data;
110 thermal_device->offset = TSENSOR_OFFSET;
111 thermal_device->get_temp = tsensor_get_temp;
112 thermal_device->get_temp_low = tsensor_get_temp_low;
113 thermal_device->set_limits = tsensor_set_limits;
114 thermal_device->set_alert = tsensor_set_alert;
115 thermal_device->set_shutdown_temp = tsensor_set_shutdown_temp;
116
117 if (tegra_thermal_set_device(thermal_device)) /* This should not fail */
118 BUG();
119}
120
121static struct tegra_tsensor_platform_data tsensor_data = {
122 .probe_callback = tegra3_tsensor_probe_callback,
123};
124
125void __init tegra3_tsensor_init(struct tegra_tsensor_pmu_data *data)
126{
127 unsigned int reg;
128 int err;
129 u32 val, checksum;
130 void __iomem *pMem = NULL;
131 /* tsensor driver is instantiated based on fuse revision */
132 err = tegra_fuse_get_revision(&reg);
133 if (err)
134 goto labelEnd;
135 pr_info("\nTegra3 fuse revision %d ", reg);
136 if (reg < TSENSOR_FUSE_REVISION_DECIMAL)
137 goto labelEnd;
138
139 if (!data)
140 goto labelSkipPowerOff;
141
142 if (!request_mem_region(TEGRA_PMC_BASE +
143 SCRATCH54_OFFSET, 8, "tegra-tsensor"))
144 pr_err(" [%s, line=%d]: Error mem busy\n",
145 __func__, __LINE__);
146
147 pMem = ioremap(TEGRA_PMC_BASE + SCRATCH54_OFFSET, 8);
148 if (!pMem) {
149 pr_err(" [%s, line=%d]: can't ioremap "
150 "pmc iomem\n", __FILE__, __LINE__);
151 goto labelEnd;
152 }
153
154 /*
155 * Fill scratch registers to power off the device
156 * in case if temperature crosses threshold TH3
157 */
158 val = (data->poweroff_reg_data << PMU_OFF_DATA_OFFSET) |
159 data->poweroff_reg_addr;
160 writel(val, pMem);
161
162 val = ((data->reset_tegra & RESET_TEGRA_MASK) << RESET_TEGRA_OFFSET) |
163 ((data->controller_type & CONTROLLER_TYPE_MASK) <<
164 CONTROLLER_TYPE_OFFSET) |
165 ((data->i2c_controller_id & I2C_CONTROLLER_ID_MASK) <<
166 I2C_CONTROLLER_ID_OFFSET) |
167 ((data->pinmux & PINMUX_MASK) << PINMUX_OFFSET) |
168 ((data->pmu_16bit_ops & PMU_16BIT_SUPPORT_MASK) <<
169 PMU_16BIT_SUPPORT_OFFSET) | data->pmu_i2c_addr;
170
171 checksum = data->poweroff_reg_addr +
172 data->poweroff_reg_data + (val & 0xFF) +
173 ((val >> 8) & 0xFF) + ((val >> 24) & 0xFF);
174 checksum &= 0xFF;
175 checksum = 0x100 - checksum;
176
177 val |= (checksum << CHECKSUM_OFFSET);
178 writel(val, pMem + 4);
179
180labelSkipPowerOff:
181 /* set platform data for device before register */
182 tegra_tsensor_device.dev.platform_data = &tsensor_data;
183 platform_device_register(&tegra_tsensor_device);
184
185labelEnd:
186 return;
187}