X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=blobdiff_plain;f=drivers%2Fthermal%2Frockchip_thermal.c;h=0360d87d189e09ce84c80c21c64bba5bb65716ff;hp=26cbda55a6ab00001f38bb9f78b50d70ab52870d;hb=25e1c1c2865f7b91b8d60a16734100f3cb67722d;hpb=018a31660d1e87a711de4f9f030d7d706a25a786 diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 26cbda55a6ab..0360d87d189e 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -213,8 +213,8 @@ struct rockchip_thermal_data { #define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4 #define TSADCV2_AUTO_PERIOD_TIME 250 /* 250ms */ #define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* 50ms */ -#define TSADCV3_AUTO_PERIOD_TIME 187500 /* 250ms */ -#define TSADCV3_AUTO_PERIOD_HT_TIME 37500 /* 50ms */ +#define TSADCV3_AUTO_PERIOD_TIME 1875 /* 2.5ms */ +#define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */ #define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */ @@ -222,10 +222,10 @@ struct rockchip_thermal_data { #define GRF_TSADC_TESTBIT_L 0x0e648 #define GRF_TSADC_TESTBIT_H 0x0e64c -#define GRF_TSADC_TSEN_PD_ON (0x30003 << 0) -#define GRF_TSADC_TSEN_PD_OFF (0x30000 << 0) #define GRF_SARADC_TESTBIT_ON (0x10001 << 2) #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2) +#define GRF_TSADC_VCM_EN_L (0x10001 << 7) +#define GRF_TSADC_VCM_EN_H (0x10001 << 7) /** * struct tsadc_table - code to temperature conversion table @@ -319,6 +319,44 @@ static const struct tsadc_table rk3288_code_table[] = { {3421, 125000}, }; +static const struct tsadc_table rk3328_code_table[] = { + {0, -40000}, + {296, -40000}, + {304, -35000}, + {313, -30000}, + {331, -20000}, + {340, -15000}, + {349, -10000}, + {359, -5000}, + {368, 0}, + {378, 5000}, + {388, 10000}, + {398, 15000}, + {408, 20000}, + {418, 25000}, + {429, 30000}, + {440, 35000}, + {451, 40000}, + {462, 45000}, + {473, 50000}, + {485, 55000}, + {496, 60000}, + {508, 65000}, + {521, 70000}, + {533, 75000}, + {546, 80000}, + {559, 85000}, + {572, 90000}, + {586, 95000}, + {600, 100000}, + {614, 105000}, + {629, 110000}, + {644, 115000}, + {659, 120000}, + {675, 125000}, + {TSADCV2_DATA_MASK, 125000}, +}; + static const struct tsadc_table rk3368_code_table[] = { {0, -40000}, {106, -40000}, @@ -401,13 +439,15 @@ static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, int temp) { int high, low, mid; + u32 error = table.data_mask; low = 0; high = table.length - 1; mid = (high + low) / 2; + /* Return mask code data when the temp is over table range */ if (temp < table.id[low].temp || temp > table.id[high].temp) - return 0; + goto exit; while (low <= high) { if (temp == table.id[mid].temp) @@ -419,7 +459,11 @@ static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, mid = (low + high) / 2; } - return 0; +exit: + pr_err("%s: Invalid conversion table: code=%d, temperature=%d\n", + __func__, error, temp); + + return error; } static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, @@ -469,7 +513,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, } break; default: - pr_err("Invalid the conversion table\n"); + pr_err("%s: Invalid the conversion table mode=%d\n", + __func__, table.mode); } /* @@ -518,11 +563,6 @@ static void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs, regs + TSADCV2_AUTO_PERIOD_HT); writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); - - if (IS_ERR(grf)) { - pr_warn("%s: Missing rockchip,grf property\n", __func__); - return; - } } /** @@ -560,9 +600,10 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); } else { - regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_ON); - mdelay(10); - regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_OFF); + /* Enable the voltage common mode feature */ + regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_VCM_EN_L); + regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_VCM_EN_H); + udelay(100); /* The spec note says at least 15 us */ regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON); regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON); @@ -649,7 +690,11 @@ static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table, { u32 alarm_value, int_en; + /* Make sure the value is valid */ alarm_value = rk_tsadcv2_temp_to_code(table, temp); + if (alarm_value == table.data_mask) + return; + writel_relaxed(alarm_value & table.data_mask, regs + TSADCV2_COMP_INT(chn)); @@ -663,7 +708,11 @@ static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table, { u32 tshut_value, val; + /* Make sure the value is valid */ tshut_value = rk_tsadcv2_temp_to_code(table, temp); + if (tshut_value == table.data_mask) + return; + writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); /* TSHUT will be valid */ @@ -737,6 +786,29 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = { }, }; +static const struct rockchip_tsadc_chip rk3328_tsadc_data = { + .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ + .chn_num = 1, /* one channels for tsadc */ + + .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ + .tshut_temp = 95000, + + .initialize = rk_tsadcv2_initialize, + .irq_ack = rk_tsadcv3_irq_ack, + .control = rk_tsadcv3_control, + .get_temp = rk_tsadcv2_get_temp, + .set_alarm_temp = rk_tsadcv2_alarm_temp, + .set_tshut_temp = rk_tsadcv2_tshut_temp, + .set_tshut_mode = rk_tsadcv2_tshut_mode, + + .table = { + .id = rk3328_code_table, + .length = ARRAY_SIZE(rk3328_code_table), + .data_mask = TSADCV2_DATA_MASK, + .mode = ADC_INCREMENT, + }, +}; + static const struct rockchip_tsadc_chip rk3366_tsadc_data = { .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ @@ -821,6 +893,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = { .compatible = "rockchip,rk3288-tsadc", .data = (void *)&rk3288_tsadc_data, }, + { + .compatible = "rockchip,rk3328-tsadc", + .data = (void *)&rk3328_tsadc_data, + }, { .compatible = "rockchip,rk3366-tsadc", .data = (void *)&rk3366_tsadc_data, @@ -953,6 +1029,8 @@ static int rockchip_configure_from_dt(struct device *dev, * need this property. */ thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(thermal->grf)) + dev_warn(dev, "Missing rockchip,grf property\n"); return 0; } @@ -994,6 +1072,48 @@ static void rockchip_thermal_reset_controller(struct reset_control *reset) reset_control_deassert(reset); } +static struct platform_device *thermal_device; + +void rockchip_dump_temperature(void) +{ + struct rockchip_thermal_data *thermal; + struct platform_device *pdev; + int i; + + if (!thermal_device) + return; + + pdev = thermal_device; + thermal = platform_get_drvdata(pdev); + + for (i = 0; i < thermal->chip->chn_num; i++) { + struct rockchip_thermal_sensor *sensor = &thermal->sensors[i]; + struct thermal_zone_device *tz = sensor->tzd; + + if (tz->temperature != THERMAL_TEMP_INVALID) + dev_warn(&pdev->dev, "channal %d: temperature(%d C)\n", + i, tz->temperature / 1000); + } + + if (thermal->regs) { + pr_warn("THERMAL REGS:\n"); + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, + 32, 4, thermal->regs, 0x88, false); + } +} +EXPORT_SYMBOL_GPL(rockchip_dump_temperature); + +static int rockchip_thermal_panic(struct notifier_block *this, + unsigned long ev, void *ptr) +{ + rockchip_dump_temperature(); + return NOTIFY_DONE; +} + +static struct notifier_block rockchip_thermal_panic_block = { + .notifier_call = rockchip_thermal_panic, +}; + static int rockchip_thermal_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1106,6 +1226,11 @@ static int rockchip_thermal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, thermal); + thermal_device = pdev; + + atomic_notifier_chain_register(&panic_notifier_list, + &rockchip_thermal_panic_block); + return 0; err_disable_pclk: