summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra3_tsensor.c
blob: 866c6a9f35c57b6bee62c90d832bbad24ad24932 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * arch/arm/mach-tegra/tegra3_tsensor.c
 *
 * 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.
 *
 */

#include <linux/kernel.h>
#include <linux/init.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"

static struct tegra_tsensor_platform_data tsensor_data = {
	.hysteresis = 5,
	.sw_intr_temperature = 75,
	.hw_clk_div_temperature = 80,
	.hw_reset_temperature = 90,
};

/* fuse revision constants used for tsensor */
#define TSENSOR_FUSE_REVISION_DECIMAL 8
#define TSENSOR_FUSE_REVISION_INTEGER 0

/* 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;
	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)
		goto labelEnd;
	pr_info("\nTegra3 fuse revision %d ", reg);
	if (reg < TSENSOR_FUSE_REVISION_DECIMAL)
		goto labelEnd;

	if (!data)
		goto labelSkipPowerOff;

	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);

labelSkipPowerOff:
	/* set platform data for device before register */
	tegra_tsensor_device.dev.platform_data = &tsensor_data;
	platform_device_register(&tegra_tsensor_device);

labelEnd:
	return;
}

#else
void __init tegra3_tsensor_init(void) { }
#endif