Arm: Tegra: Tmon: USB registers update
sreenivasulu velpula [Thu, 21 Feb 2013 11:40:01 +0000 (16:40 +0530)]
Add USB registers update functionality based on
remote temperature.

Bug 1182410

Reviewed-on: http://git-master/r/202909
(cherry picked from commit e22c06287fe0b5be1ede8ecefc8d45a7d6eb74ab)

Change-Id: If3191744fffab8462cb634688015c4f534ae4420
Signed-off-by: sreenivasulu velpula <svelpula@nvidia.com>
Reviewed-on: http://git-master/r/206272
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>

arch/arm/mach-tegra/therm-monitor.c
arch/arm/mach-tegra/therm-monitor.h

index f87fd56..53ef902 100644 (file)
@@ -33,11 +33,88 @@ static struct tmon_plat_data tmon_pdata;
 /* For now assume only one entry */
 struct i2c_board_info __initdata tgr_i2c_board_info[1];
 
+/*  T30 USB Base address:                  USB1,       USB2,       USB3     */
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static unsigned int s_tegra_usb_base[] = {0x7D000000, 0x7D004000, 0x7D008000};
+#endif
+
+/*  Fuse USB Calib Value. */
+static unsigned int s_fuse_usb_calib_value;
+
+static void get_fuse_usb_calib_value(void)
+{
+       s_fuse_usb_calib_value = readl(IO_TO_VIRT(TEGRA_FUSE_BASE +
+                                               FUSE_USB_CALIB_0));
+}
+
 static inline void pg_writel(unsigned long value, unsigned long offset)
 {
        writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE) + offset);
 }
 
+static void utmip_temp_dep_update(int curr_rtemp, int utmip_temp_bound)
+{
+       static int prev_temp;
+       static char initial_update = 1;
+       unsigned int fuse_usb_calib_value = s_fuse_usb_calib_value;
+       int i;
+       char utmip_update_require = 0;
+
+       /* Extract bits[3:0]. */
+       fuse_usb_calib_value = fuse_usb_calib_value & 0xF;
+
+       /* If previous and currentt temperatures falls in the same temperature
+          boundary then no need to update the  UTMIP_SPARE_CFG */
+       if ((prev_temp >= utmip_temp_bound) && (curr_rtemp >= utmip_temp_bound))
+               utmip_update_require = 0;
+       else if ((prev_temp < utmip_temp_bound) &&
+                               (curr_rtemp < utmip_temp_bound))
+               utmip_update_require = 0;
+       else
+               utmip_update_require = 1;
+
+       /*  For Initial call , need to update the UTMIP_SPARE_CFG */
+       if (initial_update) {
+               utmip_update_require = 1;
+               initial_update = 0;
+               prev_temp = curr_rtemp;
+       }
+
+       if (utmip_update_require) {
+               prev_temp = curr_rtemp;
+               if (curr_rtemp >= utmip_temp_bound) {
+                       fuse_usb_calib_value += 0x1;
+                       /*  Check if there is a overflow. */
+                       if (fuse_usb_calib_value > UTMIP_XCVR_SETUP_MAX_VAL)
+                               fuse_usb_calib_value = UTMIP_XCVR_SETUP_MAX_VAL;
+               }
+
+               for (i = 0; i < ARRAY_SIZE(s_tegra_usb_base); i++) {
+                       unsigned int regval;
+                       regval = readl(IO_TO_VIRT(s_tegra_usb_base[i] +
+                                       UTMIP_SPARE_CFG0));
+                       regval &= ~FUSE_SETUP_SEL;
+                       writel(regval, IO_TO_VIRT(s_tegra_usb_base[i] +
+                                       UTMIP_SPARE_CFG0));
+
+                       regval = readl(IO_TO_VIRT(s_tegra_usb_base[i] +
+                                       UTMIP_XCVR_CFG0));
+                       /* If low_to_high, then write 0x2 to HSSLEW_MSB
+                        else write 0x8 */
+                       regval &= ~UTMIP_XCVR_HSSLEW_MSB_MSK;
+                       regval |= (curr_rtemp >= utmip_temp_bound) ?
+                                       UTMIP_XCVR_HSSLEW_MSB_HIGH_TEMP_VAL :
+                                       UTMIP_XCVR_HSSLEW_MSB_LOW_TEMP_VAL;
+                       /* write fuse_usb_calib_value to SETUP field
+                       of UTMIP_XCVR_CFG0. */
+                       regval &= ~UTMIP_XCVR_SETUP_MSK;
+                       regval |= fuse_usb_calib_value;
+                       writel(regval, IO_TO_VIRT(s_tegra_usb_base[i] +
+                                       UTMIP_XCVR_CFG0));
+               }
+       }
+}
+
 /* Call back function, invoked by driver */
 static void ltemp_dependent_reg_update(int curr_ltemp)
 {
@@ -74,14 +151,12 @@ void register_therm_monitor(struct therm_monitor_data *brd_therm_monitor_data)
                tmon_pdata.ltemp_dependent_reg_update =
                        ltemp_dependent_reg_update;
 
-       /* Remote temperature monitoring: Used for USB registers */
-       if (brd_therm_monitor_data->remote_temp_update) {
-               tmon_pdata.rtemp_low_boundary =
-                       brd_therm_monitor_data->rtemp_low_boundary;
-               tmon_pdata.rtemp_high_boundary =
-                       brd_therm_monitor_data->rtemp_high_boundary;
-               /*tmon_pdata.rtemp_dependent_reg_update =
-                       rtemp_dependent_reg_update;*/
+       /* utmip registers update */
+       if (brd_therm_monitor_data->utmip_reg_update) {
+               tmon_pdata.utmip_temp_bound =
+                       brd_therm_monitor_data->utmip_temp_bound;
+               tmon_pdata.utmip_temp_dep_update =
+                       utmip_temp_dep_update;
        }
 
        /* Fill the i2c board info */
@@ -92,4 +167,5 @@ void register_therm_monitor(struct therm_monitor_data *brd_therm_monitor_data)
 
        i2c_register_board_info(brd_therm_monitor_data->i2c_bus_num,
                                tgr_i2c_board_info, 1);
+       get_fuse_usb_calib_value();
 }
index 1479e26..a3e4b0a 100644 (file)
 #define MAX_NUM_TEMPERAT 10
 #define INVALID_ADDR 0xffffffff
 
+#define UTMIP_XCVR_CFG0                        0x808
+#define UTMIP_SPARE_CFG0               0x834
+#define FUSE_SETUP_SEL                 (1 << 3)
+#define UTMIP_XCVR_SETUP_MSK           0xF
+#define UTMIP_XCVR_HSSLEW_MSB_MSK      (0x7F << 25)
+#define FUSE_USB_CALIB_0               0x1F0
+#define UTMIP_XCVR_SETUP_MAX_VAL       0xF
+#define UTMIP_XCVR_HSSLEW_MSB_BIT_OFFS 25
+/* Remote Temp < rtemp_boundary. */
+#define UTMIP_XCVR_HSSLEW_MSB_LOW_TEMP_VAL \
+       (0x8 << UTMIP_XCVR_HSSLEW_MSB_BIT_OFFS)
+/* Remote Temp >= rtemp_boundary. */
+#define UTMIP_XCVR_HSSLEW_MSB_HIGH_TEMP_VAL \
+       (0x2 << UTMIP_XCVR_HSSLEW_MSB_BIT_OFFS)
+
+
 struct therm_monitor_ldep_data {
        unsigned int reg_addr;
        int temperat[MAX_NUM_TEMPERAT];
@@ -36,10 +52,9 @@ struct therm_monitor_data {
        unsigned int delta_temp;
        unsigned int delta_time;
        unsigned int remote_offset;
-       int rtemp_low_boundary;
-       int rtemp_high_boundary;
+       int utmip_temp_bound;
        unsigned char local_temp_update;
-       unsigned char remote_temp_update;
+       unsigned char utmip_reg_update;
        unsigned char i2c_bus_num;
        unsigned int i2c_dev_addrs;
        unsigned char *i2c_dev_name;