Loading Documentation/devicetree/bindings/thermal/tsens.txt +8 −17 Original line number Diff line number Diff line Loading @@ -21,34 +21,25 @@ Required properties: The compatible property is used to identify the respective controller to use for the corresponding SoC. - reg : offset and length of the TSENS registers with associated property in reg-names as "tsens_physical" for TSENS TM physical address region. as "tsens_srot_physical" for TSENS SROT physical address region. TSENS TM physical address region as "tsens_tm_physical". - reg-names : resource names used for the physical address of the TSENS registers. Should be "tsens_physical" for physical address of the TSENS. registers. Should be "tsens_srot_physical" for physical address of the TSENS SROT region and "tsens_tm_physical" for physical address of the TM region. - interrupts : TSENS interrupt to notify Upper/Lower and Critical temperature threshold. - interrupt-names: Should be "tsens-upper-lower" for temperature threshold. Add "tsens-critical" for Critical temperature threshold notification in addition to "tsens-upper-lower" for 8996 TSENS since 8996 supports Upper/Lower and Critical temperature threshold. - qcom,sensors : Total number of available Temperature sensors for TSENS. Optional properties: - qcom,sensor-id : If the flag is present map the TSENS sensors based on the remote sensors that are enabled in HW. Ensure the mapping is not more than the number of supported sensors. - qcom,client-id : If the flag is present use it to identify the SW ID mapping used to associate it with the controller and the physical sensor mapping within the controller. The physical sensor mapping within each controller is done using the qcom,sensor-id property. If the property is not present the SW ID mapping with default from 0 to total number of supported sensors with each controller instance. Example: tsens@fc4a8000 { compatible = "qcom,msm-tsens"; reg = <0xfc4a8000 0x2000>;, reg-names = "tsens_physical"; reg = <0xfc4a8000 0x10>, <0xfc4b8000 0x1ff>; reg-names = "tsens_srot_physical", "tsens_tm_physical"; interrupts = <0 184 0>; interrupt-names = "tsens-upper-lower"; qcom,sensors = <11>; }; drivers/thermal/msm-tsens.c +45 −79 Original line number Diff line number Diff line Loading @@ -24,29 +24,28 @@ LIST_HEAD(tsens_device_list); static int tsens_get_temp(struct tsens_sensor *s, int *temp) static int tsens_get_temp(void *data, int *temp) { struct tsens_sensor *s = data; struct tsens_device *tmdev = s->tmdev; return tmdev->ops->get_temp(s, temp); } static int tsens_set_trip_temp(struct tsens_sensor *s, int trip, int temp) static int tsens_set_trip_temp(void *data, int low_temp, int high_temp) { struct tsens_sensor *s = data; struct tsens_device *tmdev = s->tmdev; if (tmdev->ops->set_trip_temp) return tmdev->ops->set_trip_temp(s, trip, temp); if (tmdev->ops->set_trips) return tmdev->ops->set_trips(s, low_temp, high_temp); return 0; } static int tsens_init(struct tsens_device *tmdev) { if (tmdev->ops->hw_init) return tmdev->ops->hw_init(tmdev); return 0; } static int tsens_register_interrupts(struct tsens_device *tmdev) Loading Loading @@ -85,19 +84,16 @@ MODULE_DEVICE_TABLE(of, tsens_table); static struct thermal_zone_of_device_ops tsens_tm_thermal_zone_ops = { .get_temp = tsens_get_temp, .set_trip_temp = tsens_set_trip_temp, .set_trips = tsens_set_trip_temp, }; static int get_device_tree_data(struct platform_device *pdev, struct tsens_device *tmdev) { struct device_node *of_node = pdev->dev.of_node; u32 *hw_id, *client_id; u32 rc = 0, i, tsens_num_sensors = 0; int tsens_len; const struct of_device_id *id; const struct tsens_data *data; struct resource *res_tsens_mem, *res_mem = NULL; struct resource *res_tsens_mem; if (!of_match_node(tsens_table, of_node)) { pr_err("Need to read SoC specific fuse map\n"); Loading @@ -111,16 +107,6 @@ static int get_device_tree_data(struct platform_device *pdev, } data = id->data; hw_id = devm_kzalloc(&pdev->dev, tsens_num_sensors * sizeof(u32), GFP_KERNEL); if (!hw_id) return -ENOMEM; client_id = devm_kzalloc(&pdev->dev, tsens_num_sensors * sizeof(u32), GFP_KERNEL); if (!client_id) return -ENOMEM; tmdev->ops = data->ops; tmdev->ctrl_data = data; tmdev->pdev = pdev; Loading @@ -132,49 +118,32 @@ static int get_device_tree_data(struct platform_device *pdev, /* TSENS register region */ res_tsens_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_physical"); IORESOURCE_MEM, "tsens_srot_physical"); if (!res_tsens_mem) { pr_err("Could not get tsens physical address resource\n"); return -EINVAL; } tsens_len = res_tsens_mem->end - res_tsens_mem->start + 1; res_mem = request_mem_region(res_tsens_mem->start, tsens_len, res_tsens_mem->name); if (!res_mem) { pr_err("Request tsens physical memory region failed\n"); return -EINVAL; tmdev->tsens_srot_addr = devm_ioremap_resource(&pdev->dev, res_tsens_mem); if (IS_ERR(tmdev->tsens_srot_addr)) { dev_err(&pdev->dev, "Failed to IO map TSENS registers.\n"); return PTR_ERR(tmdev->tsens_srot_addr); } tmdev->tsens_addr = ioremap(res_mem->start, tsens_len); if (!tmdev->tsens_addr) { pr_err("Failed to IO map TSENS registers.\n"); /* TSENS TM register region */ res_tsens_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_tm_physical"); if (!res_tsens_mem) { pr_err("Could not get tsens physical address resource\n"); return -EINVAL; } rc = of_property_read_u32_array(of_node, "qcom,sensor-id", hw_id, tsens_num_sensors); if (rc) { pr_err("Default sensor id mapping\n"); for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].hw_id = i; } else { pr_err("Use specified sensor id mapping\n"); for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].hw_id = hw_id[i]; } rc = of_property_read_u32_array(of_node, "qcom,client-id", client_id, tsens_num_sensors); if (rc) { for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].id = i; pr_debug("Default client id mapping\n"); } else { for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].id = client_id[i]; pr_debug("Use specified client id mapping\n"); tmdev->tsens_tm_addr = devm_ioremap_resource(&pdev->dev, res_tsens_mem); if (IS_ERR(tmdev->tsens_tm_addr)) { dev_err(&pdev->dev, "Failed to IO map TSENS TM registers.\n"); return PTR_ERR(tmdev->tsens_tm_addr); } return 0; Loading @@ -182,20 +151,28 @@ static int get_device_tree_data(struct platform_device *pdev, static int tsens_thermal_zone_register(struct tsens_device *tmdev) { int rc = 0, i = 0; int i = 0, sensor_missing = 0; for (i = 0; i < tmdev->num_sensors; i++) { for (i = 0; i < TSENS_MAX_SENSORS; i++) { tmdev->sensor[i].tmdev = tmdev; tmdev->sensor[i].tzd = devm_thermal_zone_of_sensor_register( &tmdev->pdev->dev, i, &tmdev->sensor[i], &tsens_tm_thermal_zone_ops); tmdev->sensor[i].hw_id = i; tmdev->sensor[i].tzd = devm_thermal_zone_of_sensor_register( &tmdev->pdev->dev, i, &tmdev->sensor[i], &tsens_tm_thermal_zone_ops); if (IS_ERR(tmdev->sensor[i].tzd)) { pr_err("Error registering sensor:%d\n", i); pr_debug("Error registering sensor:%d\n", i); sensor_missing++; continue; } } return rc; if (sensor_missing == TSENS_MAX_SENSORS) { pr_err("No TSENS sensors to register?\n"); return -ENODEV; } return 0; } static int tsens_tm_remove(struct platform_device *pdev) Loading @@ -207,32 +184,19 @@ static int tsens_tm_remove(struct platform_device *pdev) int tsens_tm_probe(struct platform_device *pdev) { struct device_node *of_node = pdev->dev.of_node; struct tsens_device *tmdev = NULL; u32 tsens_num_sensors = 0; int rc; if (!(pdev->dev.of_node)) return -ENODEV; rc = of_property_read_u32(of_node, "qcom,sensors", &tsens_num_sensors); if (rc || (!tsens_num_sensors)) { dev_err(&pdev->dev, "missing sensors\n"); return -ENODEV; } tmdev = devm_kzalloc(&pdev->dev, sizeof(struct tsens_device) + tsens_num_sensors * TSENS_MAX_SENSORS * sizeof(struct tsens_sensor), GFP_KERNEL); if (tmdev == NULL) { pr_err("%s: kzalloc() failed.\n", __func__); if (tmdev == NULL) return -ENOMEM; } tmdev->num_sensors = tsens_num_sensors; rc = get_device_tree_data(pdev, tmdev); if (rc) { Loading @@ -241,8 +205,10 @@ int tsens_tm_probe(struct platform_device *pdev) } rc = tsens_init(tmdev); if (rc) if (rc) { pr_err("Error initializing TSENS controller\n"); return rc; } rc = tsens_thermal_zone_register(tmdev); if (rc) { Loading drivers/thermal/tsens.h +5 −4 Original line number Diff line number Diff line Loading @@ -23,9 +23,9 @@ #define DEBUG_SIZE 10 #define TSENS_MAX_SENSORS 16 #define TSENS_CONTROLLER_ID(n) ((n) + 0x1000) #define TSENS_CONTROLLER_ID(n) (n) #define TSENS_CTRL_ADDR(n) (n) #define TSENS_TM_SN_STATUS(n) ((n) + 0x10a0) #define TSENS_TM_SN_STATUS(n) ((n) + 0xa0) enum tsens_dbg_type { TSENS_DBG_POLL, Loading Loading @@ -87,7 +87,7 @@ struct tsens_sensor { struct tsens_ops { int (*hw_init)(struct tsens_device *); int (*get_temp)(struct tsens_sensor *, int *); int (*set_trip_temp)(struct tsens_sensor *, int, int); int (*set_trips)(struct tsens_sensor *, int, int); int (*interrupts_reg)(struct tsens_device *); int (*dbg)(struct tsens_device *, u32, u32, int *); }; Loading Loading @@ -121,7 +121,8 @@ struct tsens_device { u32 num_sensors; struct regmap *map; struct regmap_field *status_field; void *tsens_addr; void __iomem *tsens_srot_addr; void __iomem *tsens_tm_addr; const struct tsens_ops *ops; struct tsens_dbg_context tsens_dbg; spinlock_t tsens_crit_lock; Loading drivers/thermal/tsens2xxx.c +137 −98 Original line number Diff line number Diff line Loading @@ -18,19 +18,20 @@ #include <linux/of.h> #include <linux/vmalloc.h> #include "tsens.h" #include "thermal_core.h" #define TSENS_DRIVER_NAME "msm-tsens" #define TSENS_TM_INT_EN(n) ((n) + 0x1004) #define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x1014) #define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x1018) #define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x101c) #define TSENS_TM_INT_EN(n) ((n) + 0x4) #define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x14) #define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x18) #define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x1c) #define TSENS_TM_CRITICAL_WD_BARK BIT(31) #define TSENS_TM_CRITICAL_CYCLE_MONITOR BIT(30) #define TSENS_TM_CRITICAL_INT_EN BIT(2) #define TSENS_TM_UPPER_INT_EN BIT(1) #define TSENS_TM_LOWER_INT_EN BIT(0) #define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x1020) #define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x20) #define TSENS_TM_SN_ADDR_OFFSET 0x4 #define TSENS_TM_UPPER_THRESHOLD_SET(n) ((n) << 12) #define TSENS_TM_UPPER_THRESHOLD_VALUE_SHIFT(n) ((n) >> 12) Loading @@ -39,13 +40,13 @@ #define TSENS_TM_UPPER_THRESHOLD_MASK 0xfff000 #define TSENS_TM_LOWER_THRESHOLD_MASK 0xfff #define TSENS_TM_UPPER_THRESHOLD_SHIFT 12 #define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x1060) #define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x60) #define TSENS_STATUS_ADDR_OFFSET 2 #define TSENS_TM_UPPER_INT_MASK(n) (((n) & 0xffff0000) >> 16) #define TSENS_TM_LOWER_INT_MASK(n) ((n) & 0xffff) #define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x1008) #define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0x100c) #define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x1010) #define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x8) #define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0xc) #define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x10) #define TSENS_TM_UPPER_INT_SET(n) (1 << (n + 16)) #define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK 0xfff #define TSENS_TM_SN_STATUS_VALID_BIT BIT(21) Loading @@ -55,6 +56,7 @@ #define TSENS_TM_SN_LAST_TEMP_MASK 0xfff #define TSENS_TM_CODE_BIT_MASK 0xfff #define TSENS_TM_CODE_SIGN_BIT 0x800 #define TSENS_TM_SCALE_DECI_MILLIDEG 100 #define TSENS_EN BIT(0) Loading @@ -67,7 +69,7 @@ static void msm_tsens_convert_temp(int last_temp, int *temp) last_temp |= code_mask; } *temp = last_temp * 100; *temp = last_temp * TSENS_TM_SCALE_DECI_MILLIDEG; } static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) Loading @@ -81,7 +83,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) return -EINVAL; tmdev = sensor->tmdev; sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr); sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_tm_addr); code = readl_relaxed_no_log(sensor_addr + (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET)); Loading Loading @@ -130,7 +132,6 @@ static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, { struct tsens_device *tmdev = NULL; unsigned int reg_cntl, mask; unsigned long flags; int rc = 0; /* clear the interrupt and unmask */ Loading @@ -141,56 +142,57 @@ static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, if (!tmdev) return -EINVAL; spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags); mask = (tm_sensor->hw_id); switch (trip) { case THERMAL_TRIP_CRITICAL: tmdev->sensor[tm_sensor->hw_id]. thr_state.crit_th_state = mode; reg_cntl = readl_relaxed(TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr)); (tmdev->tsens_tm_addr)); if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | (1 << mask), (TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); else writel_relaxed(reg_cntl & ~(1 << mask), (TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); break; case THERMAL_TRIP_ACTIVE: case THERMAL_TRIP_CONFIGURABLE_HI: tmdev->sensor[tm_sensor->hw_id]. thr_state.high_th_state = mode; reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr)); (tmdev->tsens_tm_addr)); if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | (TSENS_TM_UPPER_INT_SET(mask)), (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); else writel_relaxed(reg_cntl & ~(TSENS_TM_UPPER_INT_SET(mask)), (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); break; case THERMAL_TRIP_PASSIVE: case THERMAL_TRIP_CONFIGURABLE_LOW: tmdev->sensor[tm_sensor->hw_id]. thr_state.low_th_state = mode; reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr)); (tmdev->tsens_tm_addr)); if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | (1 << mask), (TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr))); (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_tm_addr))); else writel_relaxed(reg_cntl & ~(1 << mask), (TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr))); (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_tm_addr))); break; default: rc = -EINVAL; } spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags); /* Activate and enable the respective trip threshold setting */ mb(); Loading @@ -198,14 +200,14 @@ static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, } static int tsens2xxx_set_trip_temp(struct tsens_sensor *tm_sensor, int trip, int temp) int low_temp, int high_temp) { unsigned int reg_cntl; unsigned long flags; struct tsens_device *tmdev = NULL; int rc = 0; if (!tm_sensor || trip < 0) if (!tm_sensor) return -EINVAL; tmdev = tm_sensor->tmdev; Loading @@ -213,56 +215,65 @@ static int tsens2xxx_set_trip_temp(struct tsens_sensor *tm_sensor, return -EINVAL; spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags); switch (trip) { case THERMAL_TRIP_CRITICAL: tmdev->sensor[tm_sensor->hw_id]. thr_state.crit_temp = temp; temp &= TSENS_TM_SN_CRITICAL_THRESHOLD_MASK; writel_relaxed(temp, (TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET))); break; case THERMAL_TRIP_ACTIVE: if (high_temp != INT_MAX) { tmdev->sensor[tm_sensor->hw_id]. thr_state.high_temp = temp; thr_state.high_temp = high_temp; reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_addr)) + (tmdev->tsens_tm_addr)) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)); temp = TSENS_TM_UPPER_THRESHOLD_SET(temp); temp &= TSENS_TM_UPPER_THRESHOLD_MASK; high_temp /= TSENS_TM_SCALE_DECI_MILLIDEG; high_temp = TSENS_TM_UPPER_THRESHOLD_SET(high_temp); high_temp &= TSENS_TM_UPPER_THRESHOLD_MASK; reg_cntl &= ~TSENS_TM_UPPER_THRESHOLD_MASK; writel_relaxed(reg_cntl | temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr) + writel_relaxed(reg_cntl | high_temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_tm_addr) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET))); break; case THERMAL_TRIP_PASSIVE: } if (low_temp != INT_MIN) { tmdev->sensor[tm_sensor->hw_id]. thr_state.low_temp = temp; thr_state.low_temp = low_temp; reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_addr)) + (tmdev->tsens_tm_addr)) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)); temp &= TSENS_TM_LOWER_THRESHOLD_MASK; low_temp /= TSENS_TM_SCALE_DECI_MILLIDEG; low_temp &= TSENS_TM_LOWER_THRESHOLD_MASK; reg_cntl &= ~TSENS_TM_LOWER_THRESHOLD_MASK; writel_relaxed(reg_cntl | temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr) + writel_relaxed(reg_cntl | low_temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_tm_addr) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET))); break; default: pr_err("Invalid trip to TSENS: %d\n", trip); rc = -EINVAL; } spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags); /* Set trip temperature thresholds */ mb(); rc = tsens_tm_activate_trip_type(tm_sensor, trip, if (high_temp != INT_MAX) { rc = tsens_tm_activate_trip_type(tm_sensor, THERMAL_TRIP_CONFIGURABLE_HI, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) pr_err("Error during trip activation :%d\n", rc); if (rc) { pr_err("Error during trip high activation :%d\n", rc); goto fail; } } if (low_temp != INT_MIN) { rc = tsens_tm_activate_trip_type(tm_sensor, THERMAL_TRIP_CONFIGURABLE_LOW, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) { pr_err("Error during trip low activation :%d\n", rc); goto fail; } } fail: spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags); return rc; } Loading @@ -277,13 +288,13 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) void __iomem *wd_critical_addr; int wd_mask; sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr); sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr); sensor_int_mask_addr = TSENS_TM_CRITICAL_INT_MASK(tm->tsens_addr); TSENS_TM_CRITICAL_INT_MASK(tm->tsens_tm_addr); sensor_critical_addr = TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_addr); TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_tm_addr); wd_critical_addr = TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_addr); TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_tm_addr); if (tm->ctrl_data->wd_bark) { wd_mask = readl_relaxed(wd_critical_addr); Loading @@ -294,19 +305,22 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) */ writel_relaxed(wd_mask | TSENS_TM_CRITICAL_WD_BARK, (TSENS_TM_CRITICAL_INT_CLEAR (tm->tsens_addr))); (tm->tsens_tm_addr))); writel_relaxed(wd_mask & ~(TSENS_TM_CRITICAL_WD_BARK), (TSENS_TM_CRITICAL_INT_CLEAR (tm->tsens_addr))); (tm->tsens_tm_addr))); tm->tsens_dbg.tsens_critical_wd_cnt++; return IRQ_HANDLED; } } for (i = 0; i < tm->num_sensors; i++) { for (i = 0; i < TSENS_MAX_SENSORS; i++) { int int_mask, int_mask_val; u32 addr_offset; if (IS_ERR(tm->sensor[i].tzd)) continue; spin_lock_irqsave(&tm->tsens_crit_lock, flags); addr_offset = tm->sensor[i].hw_id * TSENS_TM_SN_ADDR_OFFSET; Loading @@ -320,13 +334,14 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) /* Mask the corresponding interrupt for the sensors */ writel_relaxed(int_mask | int_mask_val, TSENS_TM_CRITICAL_INT_MASK( tm->tsens_addr)); tm->tsens_tm_addr)); /* Clear the corresponding sensors interrupt */ writel_relaxed(int_mask_val, TSENS_TM_CRITICAL_INT_CLEAR(tm->tsens_addr)); TSENS_TM_CRITICAL_INT_CLEAR (tm->tsens_tm_addr)); writel_relaxed(0, TSENS_TM_CRITICAL_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); tm->sensor[i].thr_state. crit_th_state = THERMAL_DEVICE_DISABLED; } Loading @@ -342,22 +357,31 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) static irqreturn_t tsens_tm_irq_thread(int irq, void *data) { struct tsens_device *tm = data; unsigned int i, status, threshold; unsigned int i, status, threshold, temp; unsigned long flags; void __iomem *sensor_status_addr; void __iomem *sensor_int_mask_addr; void __iomem *sensor_upper_lower_addr; u32 addr_offset = 0; sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr); sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr); sensor_int_mask_addr = TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_addr); TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_tm_addr); sensor_upper_lower_addr = TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_addr); TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_tm_addr); for (i = 0; i < tm->num_sensors; i++) { for (i = 0; i < TSENS_MAX_SENSORS; i++) { bool upper_thr = false, lower_thr = false; int int_mask, int_mask_val = 0; int int_mask, int_mask_val = 0, rc; if (IS_ERR(tm->sensor[i].tzd)) continue; rc = tsens2xxx_get_temp(&tm->sensor[i], &temp); if (rc) { pr_debug("Error:%d reading temp sensor:%d\n", rc, i); continue; } spin_lock_irqsave(&tm->tsens_upp_low_lock, flags); addr_offset = tm->sensor[i].hw_id * Loading @@ -376,18 +400,29 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data) /* Mask the corresponding interrupt for the sensors */ writel_relaxed(int_mask | int_mask_val, TSENS_TM_UPPER_LOWER_INT_MASK( tm->tsens_addr)); tm->tsens_tm_addr)); /* Clear the corresponding sensors interrupt */ writel_relaxed(int_mask_val, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); writel_relaxed(0, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); if (TSENS_TM_UPPER_THRESHOLD_VALUE(threshold) > (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) { pr_debug("Re-arm high threshold\n"); rc = tsens_tm_activate_trip_type( &tm->sensor[i], THERMAL_TRIP_CONFIGURABLE_HI, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) pr_err("high rearm failed:%d\n", rc); } else { upper_thr = true; tm->sensor[i].thr_state. high_th_state = THERMAL_DEVICE_DISABLED; } } if ((status & TSENS_TM_SN_STATUS_LOWER_STATUS) && !(int_mask & Loading @@ -397,32 +432,36 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data) /* Mask the corresponding interrupt for the sensors */ writel_relaxed(int_mask | int_mask_val, TSENS_TM_UPPER_LOWER_INT_MASK( tm->tsens_addr)); tm->tsens_tm_addr)); /* Clear the corresponding sensors interrupt */ writel_relaxed(int_mask_val, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); writel_relaxed(0, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); if (TSENS_TM_LOWER_THRESHOLD_VALUE(threshold) < (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) { pr_debug("Re-arm low threshold\n"); rc = tsens_tm_activate_trip_type( &tm->sensor[i], THERMAL_TRIP_CONFIGURABLE_LOW, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) pr_err("low rearm failed:%d\n", rc); } else { lower_thr = true; tm->sensor[i].thr_state. low_th_state = THERMAL_DEVICE_DISABLED; } } spin_unlock_irqrestore(&tm->tsens_upp_low_lock, flags); if (upper_thr || lower_thr) { int temp; enum thermal_trip_type trip = THERMAL_TRIP_CONFIGURABLE_LOW; if (upper_thr) trip = THERMAL_TRIP_CONFIGURABLE_HI; tsens2xxx_get_temp(&tm->sensor[i], &temp); /* Use id for multiple controllers */ pr_debug("sensor:%d trigger temp (%d degC)\n", tm->sensor[i].hw_id, (status & TSENS_TM_SN_LAST_TEMP_MASK)); tm->sensor[i].hw_id, temp); of_thermal_handle_trip(tm->sensor[i].tzd); } } Loading @@ -442,7 +481,7 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev) unsigned int srot_val; int crit_mask; srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_addr + 0x4); srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4); srot_val = readl_relaxed(srot_addr); if (!(srot_val & TSENS_EN)) { pr_err("TSENS device is not enabled\n"); Loading @@ -451,18 +490,18 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev) if (tmdev->ctrl_data->cycle_monitor) { sensor_int_mask_addr = TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_addr); TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_tm_addr); crit_mask = readl_relaxed(sensor_int_mask_addr); writel_relaxed( crit_mask | tmdev->ctrl_data->cycle_compltn_monitor_val, (TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); /*Update critical cycle monitoring*/ mb(); } writel_relaxed(TSENS_TM_CRITICAL_INT_EN | TSENS_TM_UPPER_INT_EN | TSENS_TM_LOWER_INT_EN, TSENS_TM_INT_EN(tmdev->tsens_addr)); TSENS_TM_INT_EN(tmdev->tsens_tm_addr)); spin_lock_init(&tmdev->tsens_crit_lock); spin_lock_init(&tmdev->tsens_upp_low_lock); Loading Loading @@ -513,7 +552,7 @@ static int tsens2xxx_register_interrupts(struct tsens_device *tmdev) static const struct tsens_ops ops_tsens2xxx = { .hw_init = tsens2xxx_hw_init, .get_temp = tsens2xxx_get_temp, .set_trip_temp = tsens2xxx_set_trip_temp, .set_trips = tsens2xxx_set_trip_temp, .interrupts_reg = tsens2xxx_register_interrupts, .dbg = tsens2xxx_dbg, }; Loading Loading
Documentation/devicetree/bindings/thermal/tsens.txt +8 −17 Original line number Diff line number Diff line Loading @@ -21,34 +21,25 @@ Required properties: The compatible property is used to identify the respective controller to use for the corresponding SoC. - reg : offset and length of the TSENS registers with associated property in reg-names as "tsens_physical" for TSENS TM physical address region. as "tsens_srot_physical" for TSENS SROT physical address region. TSENS TM physical address region as "tsens_tm_physical". - reg-names : resource names used for the physical address of the TSENS registers. Should be "tsens_physical" for physical address of the TSENS. registers. Should be "tsens_srot_physical" for physical address of the TSENS SROT region and "tsens_tm_physical" for physical address of the TM region. - interrupts : TSENS interrupt to notify Upper/Lower and Critical temperature threshold. - interrupt-names: Should be "tsens-upper-lower" for temperature threshold. Add "tsens-critical" for Critical temperature threshold notification in addition to "tsens-upper-lower" for 8996 TSENS since 8996 supports Upper/Lower and Critical temperature threshold. - qcom,sensors : Total number of available Temperature sensors for TSENS. Optional properties: - qcom,sensor-id : If the flag is present map the TSENS sensors based on the remote sensors that are enabled in HW. Ensure the mapping is not more than the number of supported sensors. - qcom,client-id : If the flag is present use it to identify the SW ID mapping used to associate it with the controller and the physical sensor mapping within the controller. The physical sensor mapping within each controller is done using the qcom,sensor-id property. If the property is not present the SW ID mapping with default from 0 to total number of supported sensors with each controller instance. Example: tsens@fc4a8000 { compatible = "qcom,msm-tsens"; reg = <0xfc4a8000 0x2000>;, reg-names = "tsens_physical"; reg = <0xfc4a8000 0x10>, <0xfc4b8000 0x1ff>; reg-names = "tsens_srot_physical", "tsens_tm_physical"; interrupts = <0 184 0>; interrupt-names = "tsens-upper-lower"; qcom,sensors = <11>; };
drivers/thermal/msm-tsens.c +45 −79 Original line number Diff line number Diff line Loading @@ -24,29 +24,28 @@ LIST_HEAD(tsens_device_list); static int tsens_get_temp(struct tsens_sensor *s, int *temp) static int tsens_get_temp(void *data, int *temp) { struct tsens_sensor *s = data; struct tsens_device *tmdev = s->tmdev; return tmdev->ops->get_temp(s, temp); } static int tsens_set_trip_temp(struct tsens_sensor *s, int trip, int temp) static int tsens_set_trip_temp(void *data, int low_temp, int high_temp) { struct tsens_sensor *s = data; struct tsens_device *tmdev = s->tmdev; if (tmdev->ops->set_trip_temp) return tmdev->ops->set_trip_temp(s, trip, temp); if (tmdev->ops->set_trips) return tmdev->ops->set_trips(s, low_temp, high_temp); return 0; } static int tsens_init(struct tsens_device *tmdev) { if (tmdev->ops->hw_init) return tmdev->ops->hw_init(tmdev); return 0; } static int tsens_register_interrupts(struct tsens_device *tmdev) Loading Loading @@ -85,19 +84,16 @@ MODULE_DEVICE_TABLE(of, tsens_table); static struct thermal_zone_of_device_ops tsens_tm_thermal_zone_ops = { .get_temp = tsens_get_temp, .set_trip_temp = tsens_set_trip_temp, .set_trips = tsens_set_trip_temp, }; static int get_device_tree_data(struct platform_device *pdev, struct tsens_device *tmdev) { struct device_node *of_node = pdev->dev.of_node; u32 *hw_id, *client_id; u32 rc = 0, i, tsens_num_sensors = 0; int tsens_len; const struct of_device_id *id; const struct tsens_data *data; struct resource *res_tsens_mem, *res_mem = NULL; struct resource *res_tsens_mem; if (!of_match_node(tsens_table, of_node)) { pr_err("Need to read SoC specific fuse map\n"); Loading @@ -111,16 +107,6 @@ static int get_device_tree_data(struct platform_device *pdev, } data = id->data; hw_id = devm_kzalloc(&pdev->dev, tsens_num_sensors * sizeof(u32), GFP_KERNEL); if (!hw_id) return -ENOMEM; client_id = devm_kzalloc(&pdev->dev, tsens_num_sensors * sizeof(u32), GFP_KERNEL); if (!client_id) return -ENOMEM; tmdev->ops = data->ops; tmdev->ctrl_data = data; tmdev->pdev = pdev; Loading @@ -132,49 +118,32 @@ static int get_device_tree_data(struct platform_device *pdev, /* TSENS register region */ res_tsens_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_physical"); IORESOURCE_MEM, "tsens_srot_physical"); if (!res_tsens_mem) { pr_err("Could not get tsens physical address resource\n"); return -EINVAL; } tsens_len = res_tsens_mem->end - res_tsens_mem->start + 1; res_mem = request_mem_region(res_tsens_mem->start, tsens_len, res_tsens_mem->name); if (!res_mem) { pr_err("Request tsens physical memory region failed\n"); return -EINVAL; tmdev->tsens_srot_addr = devm_ioremap_resource(&pdev->dev, res_tsens_mem); if (IS_ERR(tmdev->tsens_srot_addr)) { dev_err(&pdev->dev, "Failed to IO map TSENS registers.\n"); return PTR_ERR(tmdev->tsens_srot_addr); } tmdev->tsens_addr = ioremap(res_mem->start, tsens_len); if (!tmdev->tsens_addr) { pr_err("Failed to IO map TSENS registers.\n"); /* TSENS TM register region */ res_tsens_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_tm_physical"); if (!res_tsens_mem) { pr_err("Could not get tsens physical address resource\n"); return -EINVAL; } rc = of_property_read_u32_array(of_node, "qcom,sensor-id", hw_id, tsens_num_sensors); if (rc) { pr_err("Default sensor id mapping\n"); for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].hw_id = i; } else { pr_err("Use specified sensor id mapping\n"); for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].hw_id = hw_id[i]; } rc = of_property_read_u32_array(of_node, "qcom,client-id", client_id, tsens_num_sensors); if (rc) { for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].id = i; pr_debug("Default client id mapping\n"); } else { for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].id = client_id[i]; pr_debug("Use specified client id mapping\n"); tmdev->tsens_tm_addr = devm_ioremap_resource(&pdev->dev, res_tsens_mem); if (IS_ERR(tmdev->tsens_tm_addr)) { dev_err(&pdev->dev, "Failed to IO map TSENS TM registers.\n"); return PTR_ERR(tmdev->tsens_tm_addr); } return 0; Loading @@ -182,20 +151,28 @@ static int get_device_tree_data(struct platform_device *pdev, static int tsens_thermal_zone_register(struct tsens_device *tmdev) { int rc = 0, i = 0; int i = 0, sensor_missing = 0; for (i = 0; i < tmdev->num_sensors; i++) { for (i = 0; i < TSENS_MAX_SENSORS; i++) { tmdev->sensor[i].tmdev = tmdev; tmdev->sensor[i].tzd = devm_thermal_zone_of_sensor_register( &tmdev->pdev->dev, i, &tmdev->sensor[i], &tsens_tm_thermal_zone_ops); tmdev->sensor[i].hw_id = i; tmdev->sensor[i].tzd = devm_thermal_zone_of_sensor_register( &tmdev->pdev->dev, i, &tmdev->sensor[i], &tsens_tm_thermal_zone_ops); if (IS_ERR(tmdev->sensor[i].tzd)) { pr_err("Error registering sensor:%d\n", i); pr_debug("Error registering sensor:%d\n", i); sensor_missing++; continue; } } return rc; if (sensor_missing == TSENS_MAX_SENSORS) { pr_err("No TSENS sensors to register?\n"); return -ENODEV; } return 0; } static int tsens_tm_remove(struct platform_device *pdev) Loading @@ -207,32 +184,19 @@ static int tsens_tm_remove(struct platform_device *pdev) int tsens_tm_probe(struct platform_device *pdev) { struct device_node *of_node = pdev->dev.of_node; struct tsens_device *tmdev = NULL; u32 tsens_num_sensors = 0; int rc; if (!(pdev->dev.of_node)) return -ENODEV; rc = of_property_read_u32(of_node, "qcom,sensors", &tsens_num_sensors); if (rc || (!tsens_num_sensors)) { dev_err(&pdev->dev, "missing sensors\n"); return -ENODEV; } tmdev = devm_kzalloc(&pdev->dev, sizeof(struct tsens_device) + tsens_num_sensors * TSENS_MAX_SENSORS * sizeof(struct tsens_sensor), GFP_KERNEL); if (tmdev == NULL) { pr_err("%s: kzalloc() failed.\n", __func__); if (tmdev == NULL) return -ENOMEM; } tmdev->num_sensors = tsens_num_sensors; rc = get_device_tree_data(pdev, tmdev); if (rc) { Loading @@ -241,8 +205,10 @@ int tsens_tm_probe(struct platform_device *pdev) } rc = tsens_init(tmdev); if (rc) if (rc) { pr_err("Error initializing TSENS controller\n"); return rc; } rc = tsens_thermal_zone_register(tmdev); if (rc) { Loading
drivers/thermal/tsens.h +5 −4 Original line number Diff line number Diff line Loading @@ -23,9 +23,9 @@ #define DEBUG_SIZE 10 #define TSENS_MAX_SENSORS 16 #define TSENS_CONTROLLER_ID(n) ((n) + 0x1000) #define TSENS_CONTROLLER_ID(n) (n) #define TSENS_CTRL_ADDR(n) (n) #define TSENS_TM_SN_STATUS(n) ((n) + 0x10a0) #define TSENS_TM_SN_STATUS(n) ((n) + 0xa0) enum tsens_dbg_type { TSENS_DBG_POLL, Loading Loading @@ -87,7 +87,7 @@ struct tsens_sensor { struct tsens_ops { int (*hw_init)(struct tsens_device *); int (*get_temp)(struct tsens_sensor *, int *); int (*set_trip_temp)(struct tsens_sensor *, int, int); int (*set_trips)(struct tsens_sensor *, int, int); int (*interrupts_reg)(struct tsens_device *); int (*dbg)(struct tsens_device *, u32, u32, int *); }; Loading Loading @@ -121,7 +121,8 @@ struct tsens_device { u32 num_sensors; struct regmap *map; struct regmap_field *status_field; void *tsens_addr; void __iomem *tsens_srot_addr; void __iomem *tsens_tm_addr; const struct tsens_ops *ops; struct tsens_dbg_context tsens_dbg; spinlock_t tsens_crit_lock; Loading
drivers/thermal/tsens2xxx.c +137 −98 Original line number Diff line number Diff line Loading @@ -18,19 +18,20 @@ #include <linux/of.h> #include <linux/vmalloc.h> #include "tsens.h" #include "thermal_core.h" #define TSENS_DRIVER_NAME "msm-tsens" #define TSENS_TM_INT_EN(n) ((n) + 0x1004) #define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x1014) #define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x1018) #define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x101c) #define TSENS_TM_INT_EN(n) ((n) + 0x4) #define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x14) #define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x18) #define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x1c) #define TSENS_TM_CRITICAL_WD_BARK BIT(31) #define TSENS_TM_CRITICAL_CYCLE_MONITOR BIT(30) #define TSENS_TM_CRITICAL_INT_EN BIT(2) #define TSENS_TM_UPPER_INT_EN BIT(1) #define TSENS_TM_LOWER_INT_EN BIT(0) #define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x1020) #define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x20) #define TSENS_TM_SN_ADDR_OFFSET 0x4 #define TSENS_TM_UPPER_THRESHOLD_SET(n) ((n) << 12) #define TSENS_TM_UPPER_THRESHOLD_VALUE_SHIFT(n) ((n) >> 12) Loading @@ -39,13 +40,13 @@ #define TSENS_TM_UPPER_THRESHOLD_MASK 0xfff000 #define TSENS_TM_LOWER_THRESHOLD_MASK 0xfff #define TSENS_TM_UPPER_THRESHOLD_SHIFT 12 #define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x1060) #define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x60) #define TSENS_STATUS_ADDR_OFFSET 2 #define TSENS_TM_UPPER_INT_MASK(n) (((n) & 0xffff0000) >> 16) #define TSENS_TM_LOWER_INT_MASK(n) ((n) & 0xffff) #define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x1008) #define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0x100c) #define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x1010) #define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x8) #define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0xc) #define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x10) #define TSENS_TM_UPPER_INT_SET(n) (1 << (n + 16)) #define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK 0xfff #define TSENS_TM_SN_STATUS_VALID_BIT BIT(21) Loading @@ -55,6 +56,7 @@ #define TSENS_TM_SN_LAST_TEMP_MASK 0xfff #define TSENS_TM_CODE_BIT_MASK 0xfff #define TSENS_TM_CODE_SIGN_BIT 0x800 #define TSENS_TM_SCALE_DECI_MILLIDEG 100 #define TSENS_EN BIT(0) Loading @@ -67,7 +69,7 @@ static void msm_tsens_convert_temp(int last_temp, int *temp) last_temp |= code_mask; } *temp = last_temp * 100; *temp = last_temp * TSENS_TM_SCALE_DECI_MILLIDEG; } static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) Loading @@ -81,7 +83,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) return -EINVAL; tmdev = sensor->tmdev; sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr); sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_tm_addr); code = readl_relaxed_no_log(sensor_addr + (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET)); Loading Loading @@ -130,7 +132,6 @@ static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, { struct tsens_device *tmdev = NULL; unsigned int reg_cntl, mask; unsigned long flags; int rc = 0; /* clear the interrupt and unmask */ Loading @@ -141,56 +142,57 @@ static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, if (!tmdev) return -EINVAL; spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags); mask = (tm_sensor->hw_id); switch (trip) { case THERMAL_TRIP_CRITICAL: tmdev->sensor[tm_sensor->hw_id]. thr_state.crit_th_state = mode; reg_cntl = readl_relaxed(TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr)); (tmdev->tsens_tm_addr)); if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | (1 << mask), (TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); else writel_relaxed(reg_cntl & ~(1 << mask), (TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); break; case THERMAL_TRIP_ACTIVE: case THERMAL_TRIP_CONFIGURABLE_HI: tmdev->sensor[tm_sensor->hw_id]. thr_state.high_th_state = mode; reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr)); (tmdev->tsens_tm_addr)); if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | (TSENS_TM_UPPER_INT_SET(mask)), (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); else writel_relaxed(reg_cntl & ~(TSENS_TM_UPPER_INT_SET(mask)), (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); break; case THERMAL_TRIP_PASSIVE: case THERMAL_TRIP_CONFIGURABLE_LOW: tmdev->sensor[tm_sensor->hw_id]. thr_state.low_th_state = mode; reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_addr)); (tmdev->tsens_tm_addr)); if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | (1 << mask), (TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr))); (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_tm_addr))); else writel_relaxed(reg_cntl & ~(1 << mask), (TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr))); (TSENS_TM_UPPER_LOWER_INT_MASK (tmdev->tsens_tm_addr))); break; default: rc = -EINVAL; } spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags); /* Activate and enable the respective trip threshold setting */ mb(); Loading @@ -198,14 +200,14 @@ static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, } static int tsens2xxx_set_trip_temp(struct tsens_sensor *tm_sensor, int trip, int temp) int low_temp, int high_temp) { unsigned int reg_cntl; unsigned long flags; struct tsens_device *tmdev = NULL; int rc = 0; if (!tm_sensor || trip < 0) if (!tm_sensor) return -EINVAL; tmdev = tm_sensor->tmdev; Loading @@ -213,56 +215,65 @@ static int tsens2xxx_set_trip_temp(struct tsens_sensor *tm_sensor, return -EINVAL; spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags); switch (trip) { case THERMAL_TRIP_CRITICAL: tmdev->sensor[tm_sensor->hw_id]. thr_state.crit_temp = temp; temp &= TSENS_TM_SN_CRITICAL_THRESHOLD_MASK; writel_relaxed(temp, (TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET))); break; case THERMAL_TRIP_ACTIVE: if (high_temp != INT_MAX) { tmdev->sensor[tm_sensor->hw_id]. thr_state.high_temp = temp; thr_state.high_temp = high_temp; reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_addr)) + (tmdev->tsens_tm_addr)) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)); temp = TSENS_TM_UPPER_THRESHOLD_SET(temp); temp &= TSENS_TM_UPPER_THRESHOLD_MASK; high_temp /= TSENS_TM_SCALE_DECI_MILLIDEG; high_temp = TSENS_TM_UPPER_THRESHOLD_SET(high_temp); high_temp &= TSENS_TM_UPPER_THRESHOLD_MASK; reg_cntl &= ~TSENS_TM_UPPER_THRESHOLD_MASK; writel_relaxed(reg_cntl | temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr) + writel_relaxed(reg_cntl | high_temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_tm_addr) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET))); break; case THERMAL_TRIP_PASSIVE: } if (low_temp != INT_MIN) { tmdev->sensor[tm_sensor->hw_id]. thr_state.low_temp = temp; thr_state.low_temp = low_temp; reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_addr)) + (tmdev->tsens_tm_addr)) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)); temp &= TSENS_TM_LOWER_THRESHOLD_MASK; low_temp /= TSENS_TM_SCALE_DECI_MILLIDEG; low_temp &= TSENS_TM_LOWER_THRESHOLD_MASK; reg_cntl &= ~TSENS_TM_LOWER_THRESHOLD_MASK; writel_relaxed(reg_cntl | temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr) + writel_relaxed(reg_cntl | low_temp, (TSENS_TM_SN_UPPER_LOWER_THRESHOLD (tmdev->tsens_tm_addr) + (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET))); break; default: pr_err("Invalid trip to TSENS: %d\n", trip); rc = -EINVAL; } spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags); /* Set trip temperature thresholds */ mb(); rc = tsens_tm_activate_trip_type(tm_sensor, trip, if (high_temp != INT_MAX) { rc = tsens_tm_activate_trip_type(tm_sensor, THERMAL_TRIP_CONFIGURABLE_HI, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) pr_err("Error during trip activation :%d\n", rc); if (rc) { pr_err("Error during trip high activation :%d\n", rc); goto fail; } } if (low_temp != INT_MIN) { rc = tsens_tm_activate_trip_type(tm_sensor, THERMAL_TRIP_CONFIGURABLE_LOW, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) { pr_err("Error during trip low activation :%d\n", rc); goto fail; } } fail: spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags); return rc; } Loading @@ -277,13 +288,13 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) void __iomem *wd_critical_addr; int wd_mask; sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr); sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr); sensor_int_mask_addr = TSENS_TM_CRITICAL_INT_MASK(tm->tsens_addr); TSENS_TM_CRITICAL_INT_MASK(tm->tsens_tm_addr); sensor_critical_addr = TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_addr); TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_tm_addr); wd_critical_addr = TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_addr); TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_tm_addr); if (tm->ctrl_data->wd_bark) { wd_mask = readl_relaxed(wd_critical_addr); Loading @@ -294,19 +305,22 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) */ writel_relaxed(wd_mask | TSENS_TM_CRITICAL_WD_BARK, (TSENS_TM_CRITICAL_INT_CLEAR (tm->tsens_addr))); (tm->tsens_tm_addr))); writel_relaxed(wd_mask & ~(TSENS_TM_CRITICAL_WD_BARK), (TSENS_TM_CRITICAL_INT_CLEAR (tm->tsens_addr))); (tm->tsens_tm_addr))); tm->tsens_dbg.tsens_critical_wd_cnt++; return IRQ_HANDLED; } } for (i = 0; i < tm->num_sensors; i++) { for (i = 0; i < TSENS_MAX_SENSORS; i++) { int int_mask, int_mask_val; u32 addr_offset; if (IS_ERR(tm->sensor[i].tzd)) continue; spin_lock_irqsave(&tm->tsens_crit_lock, flags); addr_offset = tm->sensor[i].hw_id * TSENS_TM_SN_ADDR_OFFSET; Loading @@ -320,13 +334,14 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) /* Mask the corresponding interrupt for the sensors */ writel_relaxed(int_mask | int_mask_val, TSENS_TM_CRITICAL_INT_MASK( tm->tsens_addr)); tm->tsens_tm_addr)); /* Clear the corresponding sensors interrupt */ writel_relaxed(int_mask_val, TSENS_TM_CRITICAL_INT_CLEAR(tm->tsens_addr)); TSENS_TM_CRITICAL_INT_CLEAR (tm->tsens_tm_addr)); writel_relaxed(0, TSENS_TM_CRITICAL_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); tm->sensor[i].thr_state. crit_th_state = THERMAL_DEVICE_DISABLED; } Loading @@ -342,22 +357,31 @@ static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data) static irqreturn_t tsens_tm_irq_thread(int irq, void *data) { struct tsens_device *tm = data; unsigned int i, status, threshold; unsigned int i, status, threshold, temp; unsigned long flags; void __iomem *sensor_status_addr; void __iomem *sensor_int_mask_addr; void __iomem *sensor_upper_lower_addr; u32 addr_offset = 0; sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr); sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr); sensor_int_mask_addr = TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_addr); TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_tm_addr); sensor_upper_lower_addr = TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_addr); TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_tm_addr); for (i = 0; i < tm->num_sensors; i++) { for (i = 0; i < TSENS_MAX_SENSORS; i++) { bool upper_thr = false, lower_thr = false; int int_mask, int_mask_val = 0; int int_mask, int_mask_val = 0, rc; if (IS_ERR(tm->sensor[i].tzd)) continue; rc = tsens2xxx_get_temp(&tm->sensor[i], &temp); if (rc) { pr_debug("Error:%d reading temp sensor:%d\n", rc, i); continue; } spin_lock_irqsave(&tm->tsens_upp_low_lock, flags); addr_offset = tm->sensor[i].hw_id * Loading @@ -376,18 +400,29 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data) /* Mask the corresponding interrupt for the sensors */ writel_relaxed(int_mask | int_mask_val, TSENS_TM_UPPER_LOWER_INT_MASK( tm->tsens_addr)); tm->tsens_tm_addr)); /* Clear the corresponding sensors interrupt */ writel_relaxed(int_mask_val, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); writel_relaxed(0, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); if (TSENS_TM_UPPER_THRESHOLD_VALUE(threshold) > (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) { pr_debug("Re-arm high threshold\n"); rc = tsens_tm_activate_trip_type( &tm->sensor[i], THERMAL_TRIP_CONFIGURABLE_HI, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) pr_err("high rearm failed:%d\n", rc); } else { upper_thr = true; tm->sensor[i].thr_state. high_th_state = THERMAL_DEVICE_DISABLED; } } if ((status & TSENS_TM_SN_STATUS_LOWER_STATUS) && !(int_mask & Loading @@ -397,32 +432,36 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data) /* Mask the corresponding interrupt for the sensors */ writel_relaxed(int_mask | int_mask_val, TSENS_TM_UPPER_LOWER_INT_MASK( tm->tsens_addr)); tm->tsens_tm_addr)); /* Clear the corresponding sensors interrupt */ writel_relaxed(int_mask_val, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); writel_relaxed(0, TSENS_TM_UPPER_LOWER_INT_CLEAR( tm->tsens_addr)); tm->tsens_tm_addr)); if (TSENS_TM_LOWER_THRESHOLD_VALUE(threshold) < (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) { pr_debug("Re-arm low threshold\n"); rc = tsens_tm_activate_trip_type( &tm->sensor[i], THERMAL_TRIP_CONFIGURABLE_LOW, THERMAL_TRIP_ACTIVATION_ENABLED); if (rc) pr_err("low rearm failed:%d\n", rc); } else { lower_thr = true; tm->sensor[i].thr_state. low_th_state = THERMAL_DEVICE_DISABLED; } } spin_unlock_irqrestore(&tm->tsens_upp_low_lock, flags); if (upper_thr || lower_thr) { int temp; enum thermal_trip_type trip = THERMAL_TRIP_CONFIGURABLE_LOW; if (upper_thr) trip = THERMAL_TRIP_CONFIGURABLE_HI; tsens2xxx_get_temp(&tm->sensor[i], &temp); /* Use id for multiple controllers */ pr_debug("sensor:%d trigger temp (%d degC)\n", tm->sensor[i].hw_id, (status & TSENS_TM_SN_LAST_TEMP_MASK)); tm->sensor[i].hw_id, temp); of_thermal_handle_trip(tm->sensor[i].tzd); } } Loading @@ -442,7 +481,7 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev) unsigned int srot_val; int crit_mask; srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_addr + 0x4); srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4); srot_val = readl_relaxed(srot_addr); if (!(srot_val & TSENS_EN)) { pr_err("TSENS device is not enabled\n"); Loading @@ -451,18 +490,18 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev) if (tmdev->ctrl_data->cycle_monitor) { sensor_int_mask_addr = TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_addr); TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_tm_addr); crit_mask = readl_relaxed(sensor_int_mask_addr); writel_relaxed( crit_mask | tmdev->ctrl_data->cycle_compltn_monitor_val, (TSENS_TM_CRITICAL_INT_MASK (tmdev->tsens_addr))); (tmdev->tsens_tm_addr))); /*Update critical cycle monitoring*/ mb(); } writel_relaxed(TSENS_TM_CRITICAL_INT_EN | TSENS_TM_UPPER_INT_EN | TSENS_TM_LOWER_INT_EN, TSENS_TM_INT_EN(tmdev->tsens_addr)); TSENS_TM_INT_EN(tmdev->tsens_tm_addr)); spin_lock_init(&tmdev->tsens_crit_lock); spin_lock_init(&tmdev->tsens_upp_low_lock); Loading Loading @@ -513,7 +552,7 @@ static int tsens2xxx_register_interrupts(struct tsens_device *tmdev) static const struct tsens_ops ops_tsens2xxx = { .hw_init = tsens2xxx_hw_init, .get_temp = tsens2xxx_get_temp, .set_trip_temp = tsens2xxx_set_trip_temp, .set_trips = tsens2xxx_set_trip_temp, .interrupts_reg = tsens2xxx_register_interrupts, .dbg = tsens2xxx_dbg, }; Loading