From: Rocky Hao Date: Mon, 10 Apr 2017 02:45:22 +0000 (+0800) Subject: thermal: rockchip: rk3368: ajust tsadc's data path according request of qos X-Git-Tag: firefly_0821_release~64 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=commitdiff_plain;h=d464c9367c8233be1219e0945ad9f8d567cb3eb7;ds=sidebyside thermal: rockchip: rk3368: ajust tsadc's data path according request of qos we dynamically ajust data path according to request of qos to do the balance between system's performance and tsadc's precision. Change-Id: Iec6d6af6efce3932f894d9a07298daa9653cc87e Signed-off-by: Rocky Hao --- diff --git a/drivers/thermal/rk3368_thermal.c b/drivers/thermal/rk3368_thermal.c index 290bd4d5aad8..937c0b67f104 100644 --- a/drivers/thermal/rk3368_thermal.c +++ b/drivers/thermal/rk3368_thermal.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include /** * If the temperature over a period of time High, @@ -142,6 +144,7 @@ struct rk3368_tsadc_chip { enum tshut_mode tshut_mode; enum tsadc_mode mode; enum tshut_polarity tshut_polarity; + int latency_bound; const struct chip_tsadc_table *temp_table; @@ -207,6 +210,8 @@ struct rk3368_thermal_data { struct kobject *rk3368_thermal_kobj; struct regulator *ref_regulator; int regulator_uv; + int latency_req; + int latency_bound; struct notifier_block tsadc_nb; }; @@ -214,6 +219,8 @@ static struct rk3368_thermal_data *thermal_ctx; static DEFINE_MUTEX(thermal_reg_mutex); +static DEFINE_MUTEX(thermal_lat_mutex); + static const struct tsadc_table code_table_3368[] = { {0, MIN_TEMP}, {106, MIN_TEMP}, @@ -413,6 +420,7 @@ static int rk3368_code_to_temp(const struct chip_tsadc_table *tmp_table, static const struct rk3368_tsadc_chip rk3368_tsadc_data = { .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ + .latency_bound = 50000, /* default 50000 us */ .hw_shut_temp = 125000, .mode = TSHUT_USER_MODE, .chn_num = 2, @@ -427,6 +435,8 @@ static int rk3368_configure_from_dt(struct device *dev, { u32 shut_temp; u32 rate; + u32 cycle; + int lat_bound; int ret; if (of_property_read_u32(np, "clock-frequency", &rate)) { @@ -435,6 +445,13 @@ static int rk3368_configure_from_dt(struct device *dev, } ret = clk_set_rate(thermal->clk, rate); + cycle = DIV_ROUND_UP(1000000000, rate) / 1000; + + if (scpi_thermal_set_clk_cycle(cycle)) { + dev_err(dev, "scpi_thermal_set_clk_cycle error.\n"); + return -EINVAL; + } + if (of_property_read_u32(np, "hw-shut-temp", &shut_temp)) { dev_warn(dev, "Missing tshut temp property, using default %ld\n", @@ -444,6 +461,15 @@ static int rk3368_configure_from_dt(struct device *dev, thermal->hw_shut_temp = shut_temp; } + if (of_property_read_u32(np, "latency-bound", &lat_bound)) { + dev_warn(dev, + "Missing latency-bound property, using default %d\n", + thermal->chip->latency_bound); + thermal->latency_bound = thermal->chip->latency_bound; + } else { + thermal->latency_bound = lat_bound; + } + if (thermal->hw_shut_temp > INT_MAX) { dev_err(dev, "Invalid tshut temperature specified: %ld\n", thermal->hw_shut_temp); @@ -538,12 +564,15 @@ static int get_raw_code_internal(void) #define RAW_CODE_MIN (50) #define RAW_CODE_MAX (225) -static int rk3368_get_raw_code(void) +static int rk3368_get_raw_code(struct rk3368_thermal_data *ctx) { static int old_data = 130; int tsadc_data = 0; - tsadc_data = get_raw_code_internal(); + if (ctx->latency_req > ctx->latency_bound) + tsadc_data = scpi_thermal_get_temperature(); + else + tsadc_data = get_raw_code_internal(); if ((tsadc_data < RAW_CODE_MIN) || (tsadc_data > RAW_CODE_MAX)) tsadc_data = old_data; @@ -609,7 +638,7 @@ static int rk3368_thermal_get_temp(void *_sensor, int *out_temp) pdev = ctx->pdev; mutex_lock(&thermal_reg_mutex); - raw_code = rk3368_get_raw_code(); + raw_code = rk3368_get_raw_code(ctx); temp = rk3368_convert_code_2_temp(raw_code, ctx->regulator_uv); *out_temp = predict_temp(temp / 1000) * 1000; mutex_unlock(&thermal_reg_mutex); @@ -831,6 +860,39 @@ static int rk3368_thermal_notify(struct notifier_block *nb, return NOTIFY_OK; } +/* + * This function gets called when a part of the kernel has a new latency + * requirement. We record this requirement to instruct us to get temperature. + */ +static int tsadc_latency_notify(struct notifier_block *b, + unsigned long l, void *v) +{ + struct rk3368_thermal_data *ctx = rk3368_thermal_get_data(); + + if (!ctx) + return NOTIFY_OK; + + mutex_lock(&thermal_lat_mutex); + ctx->latency_req = (int)l; + mutex_unlock(&thermal_lat_mutex); + + return NOTIFY_OK; +} + +static struct notifier_block tsadc_latency_notifier = { + .notifier_call = tsadc_latency_notify, +}; + +static inline int tsadc_add_latency_notifier(struct notifier_block *n) +{ + return pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, n); +} + +static inline int tsadc_remove_latency_notifier(struct notifier_block *n) +{ + return pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY, n); +} + static const struct of_device_id of_rk3368_thermal_match[] = { { .compatible = "rockchip,rk3368-tsadc-legacy", @@ -852,6 +914,7 @@ static int rk3368_thermal_probe(struct platform_device *pdev) int error; int uv; int ajust_code = 0; + int latency_req = 0; match = of_match_node(of_rk3368_thermal_match, np); if (!match) @@ -956,6 +1019,19 @@ static int rk3368_thermal_probe(struct platform_device *pdev) ctx->regulator_uv = uv; mutex_unlock(&thermal_reg_mutex); + error = tsadc_add_latency_notifier(&tsadc_latency_notifier); + if (error) { + dev_err(&pdev->dev, "latency notifier request failed\n"); + goto err_unreg_notifier; + } + + latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); + + mutex_lock(&thermal_lat_mutex); + if (!ctx->latency_req) + ctx->latency_req = latency_req; + mutex_unlock(&thermal_lat_mutex); + rk3368_get_ajust_code(np, &ajust_code); ctx->cpu_temp_adjust = (int)ajust_code; @@ -971,7 +1047,7 @@ static int rk3368_thermal_probe(struct platform_device *pdev) for (j = 0; j < i; j++) thermal_zone_of_sensor_unregister(&pdev->dev, ctx->sensors[j].tzd); - goto err_unreg_notifier; + goto err_remove_latancy_notifier; } } @@ -981,7 +1057,7 @@ static int rk3368_thermal_probe(struct platform_device *pdev) error = -ENOMEM; dev_err(&pdev->dev, "failed to creat debug node : error= %d\n", error); - goto err_unreg_notifier; + goto err_remove_latancy_notifier; } for (i = 0; i < ARRAY_SIZE(rk3368_thermal_attrs); i++) { @@ -996,7 +1072,7 @@ static int rk3368_thermal_probe(struct platform_device *pdev) sysfs_remove_file(ctx->rk3368_thermal_kobj, &rk3368_thermal_attrs[j].attr); - goto err_unreg_notifier; + goto err_remove_latancy_notifier; } } @@ -1011,6 +1087,8 @@ static int rk3368_thermal_probe(struct platform_device *pdev) return 0; +err_remove_latancy_notifier: + tsadc_remove_latency_notifier(&tsadc_latency_notifier); err_unreg_notifier: regulator_unregister_notifier(ctx->ref_regulator, &ctx->tsadc_nb); @@ -1027,11 +1105,15 @@ static int rk3368_thermal_remove(struct platform_device *pdev) struct rk3368_thermal_data *ctx = platform_get_drvdata(pdev); int i; + atomic_notifier_chain_unregister(&panic_notifier_list, + &rk3368_thermal_panic_block); for (i = 0; i < ctx->chip->chn_num; i++) { struct rk3368_thermal_sensor *sensor = &ctx->sensors[i]; thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd); } + tsadc_remove_latency_notifier(&tsadc_latency_notifier); + regulator_unregister_notifier(ctx->ref_regulator, &ctx->tsadc_nb); clk_disable_unprepare(ctx->pclk); clk_disable_unprepare(ctx->clk);