ARM: tegra: powermon: Fix copyrights from GPLv3 to GPLv2
[linux-3.10.git] / arch / arm / mach-tegra / therm-monitor.c
1 /*
2  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * arch/arm/mach-tegra/therm-monitor.c
17  *
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/i2c.h>
22 #include <linux/i2c-tegra.h>
23 #include <linux/platform_data/tmon_tmp411.h>
24 #include <mach/iomap.h>
25 #include <mach/io.h>
26 #include <asm/io.h>
27 #include "therm-monitor.h"
28
29 static struct therm_monitor_ldep_data *lc_temp_reg_data;
30
31 static struct tmon_plat_data tmon_pdata;
32
33 /* For now assume only one entry */
34 struct i2c_board_info __initdata tgr_i2c_board_info[1];
35
36 /*  T30 USB Base address:                  USB1,       USB2,       USB3     */
37 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
38 static unsigned int s_tegra_usb_base[] = {0x7D000000, 0x7D004000, 0x7D008000};
39 #endif
40
41 /*  Fuse USB Calib Value. */
42 static unsigned int s_fuse_usb_calib_value;
43
44 static void get_fuse_usb_calib_value(void)
45 {
46         s_fuse_usb_calib_value = readl(IO_TO_VIRT(TEGRA_FUSE_BASE +
47                                                 FUSE_USB_CALIB_0));
48 }
49
50 static inline void pg_writel(unsigned long value, unsigned long offset)
51 {
52         writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE) + offset);
53 }
54
55 static void utmip_temp_dep_update(int curr_rtemp, int utmip_temp_bound)
56 {
57         static int prev_temp;
58         static char initial_update = 1;
59         unsigned int fuse_usb_calib_value = s_fuse_usb_calib_value;
60         int i;
61         char utmip_update_require = 0;
62
63         /* Extract bits[3:0]. */
64         fuse_usb_calib_value = fuse_usb_calib_value & 0xF;
65
66         /* If previous and currentt temperatures falls in the same temperature
67            boundary then no need to update the  UTMIP_SPARE_CFG */
68         if ((prev_temp >= utmip_temp_bound) && (curr_rtemp >= utmip_temp_bound))
69                 utmip_update_require = 0;
70         else if ((prev_temp < utmip_temp_bound) &&
71                                 (curr_rtemp < utmip_temp_bound))
72                 utmip_update_require = 0;
73         else
74                 utmip_update_require = 1;
75
76         /*  For Initial call , need to update the UTMIP_SPARE_CFG */
77         if (initial_update) {
78                 utmip_update_require = 1;
79                 initial_update = 0;
80                 prev_temp = curr_rtemp;
81         }
82
83         if (utmip_update_require) {
84                 prev_temp = curr_rtemp;
85                 if (curr_rtemp >= utmip_temp_bound) {
86                         fuse_usb_calib_value += 0x1;
87                         /*  Check if there is a overflow. */
88                         if (fuse_usb_calib_value > UTMIP_XCVR_SETUP_MAX_VAL)
89                                 fuse_usb_calib_value = UTMIP_XCVR_SETUP_MAX_VAL;
90                 }
91
92                 for (i = 0; i < ARRAY_SIZE(s_tegra_usb_base); i++) {
93                         unsigned int regval;
94                         regval = readl(IO_TO_VIRT(s_tegra_usb_base[i] +
95                                         UTMIP_SPARE_CFG0));
96                         regval &= ~FUSE_SETUP_SEL;
97                         writel(regval, IO_TO_VIRT(s_tegra_usb_base[i] +
98                                         UTMIP_SPARE_CFG0));
99
100                         regval = readl(IO_TO_VIRT(s_tegra_usb_base[i] +
101                                         UTMIP_XCVR_CFG0));
102                         /* If low_to_high, then write 0x2 to HSSLEW_MSB
103                          else write 0x8 */
104                         regval &= ~UTMIP_XCVR_HSSLEW_MSB_MSK;
105                         regval |= (curr_rtemp >= utmip_temp_bound) ?
106                                         UTMIP_XCVR_HSSLEW_MSB_HIGH_TEMP_VAL :
107                                         UTMIP_XCVR_HSSLEW_MSB_LOW_TEMP_VAL;
108                         /* write fuse_usb_calib_value to SETUP field
109                         of UTMIP_XCVR_CFG0. */
110                         regval &= ~UTMIP_XCVR_SETUP_MSK;
111                         regval |= fuse_usb_calib_value;
112                         writel(regval, IO_TO_VIRT(s_tegra_usb_base[i] +
113                                         UTMIP_XCVR_CFG0));
114                 }
115         }
116 }
117
118 /* Call back function, invoked by driver */
119 static void ltemp_dependent_reg_update(int curr_ltemp)
120 {
121         int i, j;
122         for (i = 0; lc_temp_reg_data[i].reg_addr != INVALID_ADDR; i++) {
123                 for (j = 0; ((j < MAX_NUM_TEMPERAT) &&
124                         (lc_temp_reg_data[i].temperat[j] != INT_MAX)); j++) {
125                         if (curr_ltemp <= lc_temp_reg_data[i].temperat[j]) {
126                                 if (lc_temp_reg_data[i].previous_val !=
127                                                 lc_temp_reg_data[i].value[j]) {
128                                         pg_writel(lc_temp_reg_data[i].value[j],
129                                                 lc_temp_reg_data[i].reg_addr);
130                                         lc_temp_reg_data[i].previous_val =
131                                                 lc_temp_reg_data[i].value[j];
132                                 }
133                                 break;
134                         }
135                 }
136         }
137 }
138
139 void register_therm_monitor(struct therm_monitor_data *brd_therm_monitor_data)
140 {
141         /* Array which has list of register values with temperature ranges */
142         lc_temp_reg_data = brd_therm_monitor_data->brd_ltemp_reg_data;
143
144         /* Thermal monitor operational parameters */
145         tmon_pdata.delta_temp = brd_therm_monitor_data->delta_temp;
146         tmon_pdata.delta_time = brd_therm_monitor_data->delta_time;
147         tmon_pdata.remote_offset = brd_therm_monitor_data->remote_offset;
148
149         /* Local temperature monitoring: Used for pad controls */
150         if (brd_therm_monitor_data->local_temp_update)
151                 tmon_pdata.ltemp_dependent_reg_update =
152                         ltemp_dependent_reg_update;
153
154         /* utmip registers update */
155         if (brd_therm_monitor_data->utmip_reg_update) {
156                 tmon_pdata.utmip_temp_bound =
157                         brd_therm_monitor_data->utmip_temp_bound;
158                 tmon_pdata.utmip_temp_dep_update =
159                         utmip_temp_dep_update;
160         }
161
162         /* Fill the i2c board info */
163         strcpy(tgr_i2c_board_info[0].type,
164                 brd_therm_monitor_data->i2c_dev_name);
165         tgr_i2c_board_info[0].addr = brd_therm_monitor_data->i2c_dev_addrs;
166         tgr_i2c_board_info[0].platform_data = &tmon_pdata;
167
168         i2c_register_board_info(brd_therm_monitor_data->i2c_bus_num,
169                                 tgr_i2c_board_info, 1);
170         get_fuse_usb_calib_value();
171 }