diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c index 7d124a011273..5449287eddbf 100644 --- a/drivers/thermal/msm-tsens.c +++ b/drivers/thermal/msm-tsens.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -157,6 +157,8 @@ static int get_device_tree_data(struct platform_device *pdev, return PTR_ERR(tmdev->tsens_tm_addr); } + tmdev->phys_addr_tm = res_tsens_mem->start; + /* TSENS eeprom register region */ res_tsens_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_eeprom_physical"); @@ -224,6 +226,7 @@ int tsens_tm_probe(struct platform_device *pdev) { struct tsens_device *tmdev = NULL; int rc; + char tsens_name[40]; if (!(pdev->dev.of_node)) return -ENODEV; @@ -260,6 +263,33 @@ int tsens_tm_probe(struct platform_device *pdev) return rc; } + snprintf(tsens_name, sizeof(tsens_name), "tsens_%pa_0", + &tmdev->phys_addr_tm); + + tmdev->ipc_log0 = ipc_log_context_create(IPC_LOGPAGES, + tsens_name, 0); + if (!tmdev->ipc_log0) + pr_err("%s : unable to create IPC Logging 0 for tsens %pa\n", + __func__, &tmdev->phys_addr_tm); + + snprintf(tsens_name, sizeof(tsens_name), "tsens_%pa_1", + &tmdev->phys_addr_tm); + + tmdev->ipc_log1 = ipc_log_context_create(IPC_LOGPAGES, + tsens_name, 0); + if (!tmdev->ipc_log1) + pr_err("%s : unable to create IPC Logging 1 for tsens %pa\n", + __func__, &tmdev->phys_addr_tm); + + snprintf(tsens_name, sizeof(tsens_name), "tsens_%pa_2", + &tmdev->phys_addr_tm); + + tmdev->ipc_log2 = ipc_log_context_create(IPC_LOGPAGES, + tsens_name, 0); + if (!tmdev->ipc_log2) + pr_err("%s : unable to create IPC Logging 2 for tsens %pa\n", + __func__, &tmdev->phys_addr_tm); + list_add_tail(&tmdev->list, &tsens_device_list); platform_set_drvdata(pdev, tmdev); diff --git a/drivers/thermal/tsens-dbg.c b/drivers/thermal/tsens-dbg.c index a18346a3ebfa..6b7f5098a639 100644 --- a/drivers/thermal/tsens-dbg.c +++ b/drivers/thermal/tsens-dbg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #include @@ -244,6 +244,8 @@ static int tsens_dbg_log_temp_reads(struct tsens_device *data, u32 id, idx++; tmdev->tsens_dbg.sensor_dbg_info[sensor->hw_id].idx = idx; + TSENS_DBG(tmdev, "Sensor_id: %d temp: %d\n", id, *temp); + return 0; } @@ -291,7 +293,7 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr); cntrl_id = readl_relaxed(controller_id_addr); - pr_err("Controller_id: 0x%x\n", cntrl_id); + TSENS_DUMP(tmdev, "TSENS Controller_id: 0x%x\n", cntrl_id); loop = 0; i = 0; @@ -304,8 +306,11 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, r2 = readl_relaxed(debug_data_addr); r3 = readl_relaxed(debug_data_addr); r4 = readl_relaxed(debug_data_addr); - pr_err("cntrl:%d, bus-id:%d value:0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + + TSENS_DUMP(tmdev, + "ctl:%d, bus-id:%d val:0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", cntrl_id, i, debug_dump, r1, r2, r3, r4); + loop++; } @@ -317,8 +322,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, TSENS_DEBUG_CONTROL(tmdev->tsens_tm_addr)); while (loop < TSENS_DEBUG_LOOP_COUNT) { debug_dump = readl_relaxed(debug_data_addr); - pr_err("cntrl:%d, bus-id:%d with value: 0x%x\n", - cntrl_id, i, debug_dump); + TSENS_DUMP(tmdev, + "cntrl:%d, bus-id:%d with value: 0x%x\n", + cntrl_id, i, debug_dump); if (i == TSENS_DBG_BUS_ID_2) usleep_range( TSENS_DEBUG_BUS_ID2_MIN_CYCLE, @@ -327,7 +333,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, } } - pr_err("Start of TSENS TM dump\n"); + TSENS_DUMP(tmdev, "Start of TSENS TM dump for ctr 0x%x\n", + cntrl_id); + for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) { r1 = readl_relaxed(controller_id_addr + offset); r2 = readl_relaxed(controller_id_addr + (offset + @@ -337,13 +345,16 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, r4 = readl_relaxed(controller_id_addr + (offset + TSENS_DEBUG_OFFSET_WORD3)); - pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - cntrl_id, offset, r1, r2, r3, r4); + TSENS_DUMP(tmdev, + "ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + cntrl_id, offset, r1, r2, r3, r4); + offset += TSENS_DEBUG_OFFSET_ROW; } offset = 0; - pr_err("Start of TSENS SROT dump\n"); + TSENS_DUMP(tmdev, "Start of TSENS SROT dump for ctr 0x%x\n", + cntrl_id); for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) { r1 = readl_relaxed(srot_addr + offset); r2 = readl_relaxed(srot_addr + (offset + @@ -353,8 +364,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, r4 = readl_relaxed(srot_addr + (offset + TSENS_DEBUG_OFFSET_WORD3)); - pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - cntrl_id, offset, r1, r2, r3, r4); + TSENS_DUMP(tmdev, + "ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + cntrl_id, offset, r1, r2, r3, r4); offset += TSENS_DEBUG_OFFSET_ROW; } @@ -362,7 +374,8 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, while (loop < TSENS_DEBUG_LOOP_COUNT) { offset = TSENS_DEBUG_OFFSET_ROW * TSENS_DEBUG_STATUS_REG_START; - pr_err("Start of TSENS TM dump %d\n", loop); + TSENS_DUMP(tmdev, "Start of TSENS TM dump %d\n", + loop); /* Limited dump of the registers for the temperature */ for (i = 0; i < TSENS_DEBUG_LOOP_COUNT; i++) { r1 = readl_relaxed(controller_id_addr + offset); @@ -373,8 +386,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data, r4 = readl_relaxed(controller_id_addr + (offset + TSENS_DEBUG_OFFSET_WORD3)); - pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - cntrl_id, offset, r1, r2, r3, r4); + TSENS_DUMP(tmdev, + "ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + cntrl_id, offset, r1, r2, r3, r4); offset += TSENS_DEBUG_OFFSET_ROW; } loop++; diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h index 60482052fd37..8ee67c6be159 100644 --- a/drivers/thermal/tsens.h +++ b/drivers/thermal/tsens.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ #ifndef __QCOM_TSENS_H__ @@ -13,6 +13,7 @@ #include #include #include +#include #define DEBUG_SIZE 10 #define TSENS_MAX_SENSORS 16 @@ -29,6 +30,8 @@ #define SLOPE_FACTOR 1000 #define SLOPE_DEFAULT 3200 +#define IPC_LOGPAGES 10 + enum tsens_dbg_type { TSENS_DBG_POLL, TSENS_DBG_LOG_TEMP_READS, @@ -42,6 +45,54 @@ enum tsens_dbg_type { struct tsens_device; +#ifdef CONFIG_DEBUG_FS +#define TSENS_IPC(idx, dev, msg, args...) do { \ + if (dev) { \ + if ((idx == 0) && (dev)->ipc_log0) \ + ipc_log_string((dev)->ipc_log0, \ + "%s: " msg, __func__, args); \ + else if ((idx == 1) && (dev)->ipc_log1) \ + ipc_log_string((dev)->ipc_log1, \ + "%s: " msg, __func__, args); \ + else if ((idx == 2) && (dev)->ipc_log2) \ + ipc_log_string((dev)->ipc_log2, \ + "%s: " msg, __func__, args); \ + else \ + pr_debug("tsens: invalid logging index\n"); \ + } \ + } while (0) +#define TSENS_DUMP(dev, msg, args...) do { \ + TSENS_IPC(2, dev, msg, args); \ + pr_info(msg, ##args); \ + } while (0) +#define TSENS_ERR(dev, msg, args...) do { \ + pr_err(msg, ##args); \ + TSENS_IPC(1, dev, msg, args); \ + } while (0) +#define TSENS_INFO(dev, msg, args...) do { \ + pr_info(msg, ##args); \ + TSENS_IPC(1, dev, msg, args); \ + } while (0) +#define TSENS_DBG(dev, msg, args...) do { \ + pr_debug(msg, ##args); \ + if (dev) { \ + TSENS_IPC(0, dev, msg, args); \ + } \ + } while (0) +#define TSENS_DBG1(dev, msg, args...) do { \ + pr_debug(msg, ##args); \ + if (dev) { \ + TSENS_IPC(1, dev, msg, args); \ + } \ + } while (0) +#else +#define TSENS_DBG1(x...) pr_debug(x) +#define TSENS_DBG(x...) pr_debug(x) +#define TSENS_INFO(x...) pr_info(x) +#define TSENS_ERR(x...) pr_err(x) +#define TSENS_DUMP(x...) pr_info(x) +#endif + #if defined(CONFIG_THERMAL_TSENS) int tsens2xxx_dbg(struct tsens_device *data, u32 id, u32 dbg_type, int *temp); #else @@ -147,11 +198,16 @@ struct tsens_device { void __iomem *tsens_tm_addr; void __iomem *tsens_calib_addr; const struct tsens_ops *ops; + void *ipc_log0; + void *ipc_log1; + void *ipc_log2; + phys_addr_t phys_addr_tm; struct tsens_dbg_context tsens_dbg; spinlock_t tsens_crit_lock; spinlock_t tsens_upp_low_lock; const struct tsens_data *ctrl_data; struct tsens_mtc_sysfs mtcsys; + int trdy_fail_ctr; struct tsens_sensor sensor[0]; }; diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c index 2580c5c8bb88..062e53e26fd0 100644 --- a/drivers/thermal/tsens2xxx.c +++ b/drivers/thermal/tsens2xxx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ #include @@ -88,10 +88,22 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) code = readl_relaxed_no_log(trdy); if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >> TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) { - pr_err("TSENS device first round not complete0x%x\n", code); + pr_err("tsens device first round not complete0x%x, ctr is %d\n", + code, tmdev->trdy_fail_ctr); + tmdev->trdy_fail_ctr++; + + if (tmdev->trdy_fail_ctr >= 50) { + if (tmdev->ops->dbg) + tmdev->ops->dbg(tmdev, 0, + TSENS_DBG_LOG_BUS_ID_DATA, NULL); + BUG(); + } + return -ENODATA; } + tmdev->trdy_fail_ctr = 0; + code = readl_relaxed_no_log(sensor_addr + (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET)); last_temp = code & TSENS_TM_SN_LAST_TEMP_MASK;