Loading drivers/thermal/qcom/bcl_pmic5.c +77 −45 Original line number Diff line number Diff line Loading @@ -56,6 +56,8 @@ #define BCL_VBAT_INC_MV 25 #define BCL_VBAT_MAX_MV 3600 #define MAX_PERPH_COUNT 2 enum bcl_dev_type { BCL_IBAT_LVL0, BCL_IBAT_LVL1, Loading @@ -73,6 +75,8 @@ static char bcl_int_names[BCL_TYPE_MAX][25] = { "bcl-vbat-lvl2", }; struct bcl_device; struct bcl_peripheral_data { int irq_num; long int trip_thresh; Loading @@ -82,6 +86,7 @@ struct bcl_peripheral_data { enum bcl_dev_type type; struct thermal_zone_of_device_ops ops; struct thermal_zone_device *tz_dev; struct bcl_device *dev; }; struct bcl_device { Loading @@ -90,9 +95,11 @@ struct bcl_device { struct bcl_peripheral_data param[BCL_TYPE_MAX]; }; static struct bcl_device *bcl_perph; static struct bcl_device *bcl_devices[MAX_PERPH_COUNT]; static int bcl_device_ct; static int bcl_read_register(int16_t reg_offset, unsigned int *data) static int bcl_read_register(struct bcl_device *bcl_perph, int16_t reg_offset, unsigned int *data) { int ret = 0; Loading @@ -104,26 +111,32 @@ static int bcl_read_register(int16_t reg_offset, unsigned int *data) (bcl_perph->fg_bcl_addr + reg_offset), data); if (ret < 0) pr_err("Error reading register %d. err:%d\n", reg_offset, ret); pr_err("Error reading register 0x%04x err:%d\n", bcl_perph->fg_bcl_addr + reg_offset, ret); else pr_debug("Read register:0x%04x value:0x%02x\n", bcl_perph->fg_bcl_addr + reg_offset, *data); return ret; } static int bcl_write_general_register(int16_t reg_offset, uint16_t base, uint8_t data) static int bcl_write_register(struct bcl_device *bcl_perph, int16_t reg_offset, uint8_t data) { int ret = 0; uint8_t *write_buf = &data; uint16_t base; if (!bcl_perph) { pr_err("BCL device not initialized\n"); return -EINVAL; } base = bcl_perph->fg_bcl_addr; ret = regmap_write(bcl_perph->regmap, (base + reg_offset), *write_buf); if (ret < 0) { pr_err("Error reading register %d. err:%d\n", reg_offset, ret); pr_err("Error reading register:0x%04x val:0x%02x err:%d\n", base + reg_offset, data, ret); return ret; } pr_debug("wrote 0x%02x to 0x%04x\n", data, base + reg_offset); Loading @@ -131,12 +144,6 @@ static int bcl_write_general_register(int16_t reg_offset, return ret; } static int bcl_write_register(int16_t reg_offset, uint8_t data) { return bcl_write_general_register(reg_offset, bcl_perph->fg_bcl_addr, data); } static void convert_adc_to_vbat_thresh_val(int *val) { /* Loading Loading @@ -190,18 +197,21 @@ static int bcl_set_ibat(void *data, int low, int high) ibat_ua = thresh_value; convert_ibat_to_adc_val(&thresh_value); val = (int8_t)thresh_value; if (&bcl_perph->param[BCL_IBAT_LVL0] == bat_data) { switch (bat_data->type) { case BCL_IBAT_LVL0: addr = BCL_IBAT_HIGH; pr_debug("ibat high threshold:%d mA ADC:0x%02x\n", ibat_ua, val); } else if (&bcl_perph->param[BCL_IBAT_LVL1] == bat_data) { break; case BCL_IBAT_LVL1: addr = BCL_IBAT_TOO_HIGH; pr_debug("ibat too high threshold:%d mA ADC:0x%02x\n", ibat_ua, val); } else { break; default: goto set_trip_exit; } ret = bcl_write_register(addr, val); ret = bcl_write_register(bat_data->dev, addr, val); if (ret) goto set_trip_exit; bat_data->trip_thresh = ibat_ua; Loading @@ -225,7 +235,7 @@ static int bcl_read_ibat(void *data, int *adc_value) (struct bcl_peripheral_data *)data; *adc_value = val; ret = bcl_read_register(BCL_IBAT_READ, &val); ret = bcl_read_register(bat_data->dev, BCL_IBAT_READ, &val); if (ret) goto bcl_read_exit; /* IBat ADC reading is in 2's compliment form */ Loading Loading @@ -255,16 +265,21 @@ static int bcl_get_vbat_trip(void *data, int type, int *trip) int16_t addr; *trip = 0; if (&bcl_perph->param[BCL_VBAT_LVL0] == bat_data) switch (bat_data->type) { case BCL_VBAT_LVL0: addr = BCL_VBAT_ADC_LOW; else if (&bcl_perph->param[BCL_VBAT_LVL1] == bat_data) break; case BCL_VBAT_LVL1: addr = BCL_VBAT_COMP_LOW; else if (&bcl_perph->param[BCL_VBAT_LVL2] == bat_data) break; case BCL_VBAT_LVL2: addr = BCL_VBAT_COMP_TLOW; else break; default: return -ENODEV; } ret = bcl_read_register(addr, &val); ret = bcl_read_register(bat_data->dev, addr, &val); if (ret) return ret; Loading Loading @@ -321,7 +336,7 @@ static int bcl_read_vbat(void *data, int *adc_value) (struct bcl_peripheral_data *)data; *adc_value = val; ret = bcl_read_register(BCL_VBAT_READ, &val); ret = bcl_read_register(bat_data->dev, BCL_VBAT_READ, &val); if (ret) goto bcl_read_exit; *adc_value = val; Loading @@ -344,6 +359,7 @@ static irqreturn_t bcl_handle_irq(int irq, void *data) unsigned int irq_status = 0; int ret; bool notify = false; struct bcl_device *bcl_perph; mutex_lock(&perph_data->state_trans_lock); if (!perph_data->irq_enabled) { Loading @@ -354,7 +370,8 @@ static irqreturn_t bcl_handle_irq(int irq, void *data) } mutex_unlock(&perph_data->state_trans_lock); ret = bcl_read_register(BCL_IRQ_STATUS, &irq_status); bcl_perph = perph_data->dev; ret = bcl_read_register(bcl_perph, BCL_IRQ_STATUS, &irq_status); if (ret) { disable_irq_nosync(irq); perph_data->irq_enabled = false; Loading Loading @@ -415,7 +432,8 @@ static irqreturn_t bcl_handle_irq(int irq, void *data) return IRQ_HANDLED; } static int bcl_get_devicetree_data(struct platform_device *pdev) static int bcl_get_devicetree_data(struct platform_device *pdev, struct bcl_device *bcl_perph) { int ret = 0; const __be32 *prop = NULL; Loading Loading @@ -466,13 +484,14 @@ static void bcl_fetch_trip(struct platform_device *pdev, enum bcl_dev_type type, } static void bcl_vbat_init(struct platform_device *pdev, enum bcl_dev_type type) enum bcl_dev_type type, struct bcl_device *bcl_perph) { struct bcl_peripheral_data *vbat = &bcl_perph->param[type]; irqreturn_t (*handle)(int, void *) = bcl_handle_irq; mutex_init(&vbat->state_trans_lock); vbat->type = type; vbat->dev = bcl_perph; bcl_fetch_trip(pdev, type, vbat, handle); vbat->ops.get_temp = bcl_read_vbat; vbat->ops.set_trips = bcl_set_vbat; Loading @@ -489,20 +508,22 @@ static void bcl_vbat_init(struct platform_device *pdev, thermal_zone_device_update(vbat->tz_dev, THERMAL_DEVICE_UP); } static void bcl_probe_vbat(struct platform_device *pdev) static void bcl_probe_vbat(struct platform_device *pdev, struct bcl_device *bcl_perph) { bcl_vbat_init(pdev, BCL_VBAT_LVL0); bcl_vbat_init(pdev, BCL_VBAT_LVL1); bcl_vbat_init(pdev, BCL_VBAT_LVL2); bcl_vbat_init(pdev, BCL_VBAT_LVL0, bcl_perph); bcl_vbat_init(pdev, BCL_VBAT_LVL1, bcl_perph); bcl_vbat_init(pdev, BCL_VBAT_LVL2, bcl_perph); } static void bcl_ibat_init(struct platform_device *pdev, enum bcl_dev_type type) enum bcl_dev_type type, struct bcl_device *bcl_perph) { struct bcl_peripheral_data *ibat = &bcl_perph->param[type]; mutex_init(&ibat->state_trans_lock); ibat->type = type; ibat->dev = bcl_perph; bcl_fetch_trip(pdev, type, ibat, NULL); ibat->ops.get_temp = bcl_read_ibat; ibat->ops.set_trips = bcl_set_ibat; Loading Loading @@ -541,20 +562,23 @@ static void bcl_ibat_init(struct platform_device *pdev, thermal_zone_device_update(ibat->tz_dev, THERMAL_DEVICE_UP); } static void bcl_probe_ibat(struct platform_device *pdev) static void bcl_probe_ibat(struct platform_device *pdev, struct bcl_device *bcl_perph) { bcl_ibat_init(pdev, BCL_IBAT_LVL0); bcl_ibat_init(pdev, BCL_IBAT_LVL1); bcl_ibat_init(pdev, BCL_IBAT_LVL0, bcl_perph); bcl_ibat_init(pdev, BCL_IBAT_LVL1, bcl_perph); } static void bcl_configure_bcl_peripheral(void) static void bcl_configure_bcl_peripheral(struct bcl_device *bcl_perph) { bcl_write_register(BCL_MONITOR_EN, BIT(7)); bcl_write_register(bcl_perph, BCL_MONITOR_EN, BIT(7)); } static int bcl_remove(struct platform_device *pdev) { int i = 0; struct bcl_device *bcl_perph = (struct bcl_device *)dev_get_drvdata(&pdev->dev); for (; i < BCL_TYPE_MAX; i++) { if (!bcl_perph->param[i].tz_dev) Loading @@ -562,16 +586,23 @@ static int bcl_remove(struct platform_device *pdev) thermal_zone_of_sensor_unregister(&pdev->dev, bcl_perph->param[i].tz_dev); } bcl_perph = NULL; return 0; } static int bcl_probe(struct platform_device *pdev) { bcl_perph = devm_kzalloc(&pdev->dev, sizeof(*bcl_perph), GFP_KERNEL); if (!bcl_perph) struct bcl_device *bcl_perph = NULL; if (bcl_device_ct >= MAX_PERPH_COUNT) { dev_err(&pdev->dev, "Max bcl peripheral supported already.\n"); return -EINVAL; } bcl_devices[bcl_device_ct] = devm_kzalloc(&pdev->dev, sizeof(*bcl_devices[0]), GFP_KERNEL); if (!bcl_devices[bcl_device_ct]) return -ENOMEM; bcl_perph = bcl_devices[bcl_device_ct]; bcl_perph->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!bcl_perph->regmap) { Loading @@ -579,10 +610,11 @@ static int bcl_probe(struct platform_device *pdev) return -EINVAL; } bcl_get_devicetree_data(pdev); bcl_probe_vbat(pdev); bcl_probe_ibat(pdev); bcl_configure_bcl_peripheral(); bcl_device_ct++; bcl_get_devicetree_data(pdev, bcl_perph); bcl_probe_vbat(pdev, bcl_perph); bcl_probe_ibat(pdev, bcl_perph); bcl_configure_bcl_peripheral(bcl_perph); dev_set_drvdata(&pdev->dev, bcl_perph); Loading Loading
drivers/thermal/qcom/bcl_pmic5.c +77 −45 Original line number Diff line number Diff line Loading @@ -56,6 +56,8 @@ #define BCL_VBAT_INC_MV 25 #define BCL_VBAT_MAX_MV 3600 #define MAX_PERPH_COUNT 2 enum bcl_dev_type { BCL_IBAT_LVL0, BCL_IBAT_LVL1, Loading @@ -73,6 +75,8 @@ static char bcl_int_names[BCL_TYPE_MAX][25] = { "bcl-vbat-lvl2", }; struct bcl_device; struct bcl_peripheral_data { int irq_num; long int trip_thresh; Loading @@ -82,6 +86,7 @@ struct bcl_peripheral_data { enum bcl_dev_type type; struct thermal_zone_of_device_ops ops; struct thermal_zone_device *tz_dev; struct bcl_device *dev; }; struct bcl_device { Loading @@ -90,9 +95,11 @@ struct bcl_device { struct bcl_peripheral_data param[BCL_TYPE_MAX]; }; static struct bcl_device *bcl_perph; static struct bcl_device *bcl_devices[MAX_PERPH_COUNT]; static int bcl_device_ct; static int bcl_read_register(int16_t reg_offset, unsigned int *data) static int bcl_read_register(struct bcl_device *bcl_perph, int16_t reg_offset, unsigned int *data) { int ret = 0; Loading @@ -104,26 +111,32 @@ static int bcl_read_register(int16_t reg_offset, unsigned int *data) (bcl_perph->fg_bcl_addr + reg_offset), data); if (ret < 0) pr_err("Error reading register %d. err:%d\n", reg_offset, ret); pr_err("Error reading register 0x%04x err:%d\n", bcl_perph->fg_bcl_addr + reg_offset, ret); else pr_debug("Read register:0x%04x value:0x%02x\n", bcl_perph->fg_bcl_addr + reg_offset, *data); return ret; } static int bcl_write_general_register(int16_t reg_offset, uint16_t base, uint8_t data) static int bcl_write_register(struct bcl_device *bcl_perph, int16_t reg_offset, uint8_t data) { int ret = 0; uint8_t *write_buf = &data; uint16_t base; if (!bcl_perph) { pr_err("BCL device not initialized\n"); return -EINVAL; } base = bcl_perph->fg_bcl_addr; ret = regmap_write(bcl_perph->regmap, (base + reg_offset), *write_buf); if (ret < 0) { pr_err("Error reading register %d. err:%d\n", reg_offset, ret); pr_err("Error reading register:0x%04x val:0x%02x err:%d\n", base + reg_offset, data, ret); return ret; } pr_debug("wrote 0x%02x to 0x%04x\n", data, base + reg_offset); Loading @@ -131,12 +144,6 @@ static int bcl_write_general_register(int16_t reg_offset, return ret; } static int bcl_write_register(int16_t reg_offset, uint8_t data) { return bcl_write_general_register(reg_offset, bcl_perph->fg_bcl_addr, data); } static void convert_adc_to_vbat_thresh_val(int *val) { /* Loading Loading @@ -190,18 +197,21 @@ static int bcl_set_ibat(void *data, int low, int high) ibat_ua = thresh_value; convert_ibat_to_adc_val(&thresh_value); val = (int8_t)thresh_value; if (&bcl_perph->param[BCL_IBAT_LVL0] == bat_data) { switch (bat_data->type) { case BCL_IBAT_LVL0: addr = BCL_IBAT_HIGH; pr_debug("ibat high threshold:%d mA ADC:0x%02x\n", ibat_ua, val); } else if (&bcl_perph->param[BCL_IBAT_LVL1] == bat_data) { break; case BCL_IBAT_LVL1: addr = BCL_IBAT_TOO_HIGH; pr_debug("ibat too high threshold:%d mA ADC:0x%02x\n", ibat_ua, val); } else { break; default: goto set_trip_exit; } ret = bcl_write_register(addr, val); ret = bcl_write_register(bat_data->dev, addr, val); if (ret) goto set_trip_exit; bat_data->trip_thresh = ibat_ua; Loading @@ -225,7 +235,7 @@ static int bcl_read_ibat(void *data, int *adc_value) (struct bcl_peripheral_data *)data; *adc_value = val; ret = bcl_read_register(BCL_IBAT_READ, &val); ret = bcl_read_register(bat_data->dev, BCL_IBAT_READ, &val); if (ret) goto bcl_read_exit; /* IBat ADC reading is in 2's compliment form */ Loading Loading @@ -255,16 +265,21 @@ static int bcl_get_vbat_trip(void *data, int type, int *trip) int16_t addr; *trip = 0; if (&bcl_perph->param[BCL_VBAT_LVL0] == bat_data) switch (bat_data->type) { case BCL_VBAT_LVL0: addr = BCL_VBAT_ADC_LOW; else if (&bcl_perph->param[BCL_VBAT_LVL1] == bat_data) break; case BCL_VBAT_LVL1: addr = BCL_VBAT_COMP_LOW; else if (&bcl_perph->param[BCL_VBAT_LVL2] == bat_data) break; case BCL_VBAT_LVL2: addr = BCL_VBAT_COMP_TLOW; else break; default: return -ENODEV; } ret = bcl_read_register(addr, &val); ret = bcl_read_register(bat_data->dev, addr, &val); if (ret) return ret; Loading Loading @@ -321,7 +336,7 @@ static int bcl_read_vbat(void *data, int *adc_value) (struct bcl_peripheral_data *)data; *adc_value = val; ret = bcl_read_register(BCL_VBAT_READ, &val); ret = bcl_read_register(bat_data->dev, BCL_VBAT_READ, &val); if (ret) goto bcl_read_exit; *adc_value = val; Loading @@ -344,6 +359,7 @@ static irqreturn_t bcl_handle_irq(int irq, void *data) unsigned int irq_status = 0; int ret; bool notify = false; struct bcl_device *bcl_perph; mutex_lock(&perph_data->state_trans_lock); if (!perph_data->irq_enabled) { Loading @@ -354,7 +370,8 @@ static irqreturn_t bcl_handle_irq(int irq, void *data) } mutex_unlock(&perph_data->state_trans_lock); ret = bcl_read_register(BCL_IRQ_STATUS, &irq_status); bcl_perph = perph_data->dev; ret = bcl_read_register(bcl_perph, BCL_IRQ_STATUS, &irq_status); if (ret) { disable_irq_nosync(irq); perph_data->irq_enabled = false; Loading Loading @@ -415,7 +432,8 @@ static irqreturn_t bcl_handle_irq(int irq, void *data) return IRQ_HANDLED; } static int bcl_get_devicetree_data(struct platform_device *pdev) static int bcl_get_devicetree_data(struct platform_device *pdev, struct bcl_device *bcl_perph) { int ret = 0; const __be32 *prop = NULL; Loading Loading @@ -466,13 +484,14 @@ static void bcl_fetch_trip(struct platform_device *pdev, enum bcl_dev_type type, } static void bcl_vbat_init(struct platform_device *pdev, enum bcl_dev_type type) enum bcl_dev_type type, struct bcl_device *bcl_perph) { struct bcl_peripheral_data *vbat = &bcl_perph->param[type]; irqreturn_t (*handle)(int, void *) = bcl_handle_irq; mutex_init(&vbat->state_trans_lock); vbat->type = type; vbat->dev = bcl_perph; bcl_fetch_trip(pdev, type, vbat, handle); vbat->ops.get_temp = bcl_read_vbat; vbat->ops.set_trips = bcl_set_vbat; Loading @@ -489,20 +508,22 @@ static void bcl_vbat_init(struct platform_device *pdev, thermal_zone_device_update(vbat->tz_dev, THERMAL_DEVICE_UP); } static void bcl_probe_vbat(struct platform_device *pdev) static void bcl_probe_vbat(struct platform_device *pdev, struct bcl_device *bcl_perph) { bcl_vbat_init(pdev, BCL_VBAT_LVL0); bcl_vbat_init(pdev, BCL_VBAT_LVL1); bcl_vbat_init(pdev, BCL_VBAT_LVL2); bcl_vbat_init(pdev, BCL_VBAT_LVL0, bcl_perph); bcl_vbat_init(pdev, BCL_VBAT_LVL1, bcl_perph); bcl_vbat_init(pdev, BCL_VBAT_LVL2, bcl_perph); } static void bcl_ibat_init(struct platform_device *pdev, enum bcl_dev_type type) enum bcl_dev_type type, struct bcl_device *bcl_perph) { struct bcl_peripheral_data *ibat = &bcl_perph->param[type]; mutex_init(&ibat->state_trans_lock); ibat->type = type; ibat->dev = bcl_perph; bcl_fetch_trip(pdev, type, ibat, NULL); ibat->ops.get_temp = bcl_read_ibat; ibat->ops.set_trips = bcl_set_ibat; Loading Loading @@ -541,20 +562,23 @@ static void bcl_ibat_init(struct platform_device *pdev, thermal_zone_device_update(ibat->tz_dev, THERMAL_DEVICE_UP); } static void bcl_probe_ibat(struct platform_device *pdev) static void bcl_probe_ibat(struct platform_device *pdev, struct bcl_device *bcl_perph) { bcl_ibat_init(pdev, BCL_IBAT_LVL0); bcl_ibat_init(pdev, BCL_IBAT_LVL1); bcl_ibat_init(pdev, BCL_IBAT_LVL0, bcl_perph); bcl_ibat_init(pdev, BCL_IBAT_LVL1, bcl_perph); } static void bcl_configure_bcl_peripheral(void) static void bcl_configure_bcl_peripheral(struct bcl_device *bcl_perph) { bcl_write_register(BCL_MONITOR_EN, BIT(7)); bcl_write_register(bcl_perph, BCL_MONITOR_EN, BIT(7)); } static int bcl_remove(struct platform_device *pdev) { int i = 0; struct bcl_device *bcl_perph = (struct bcl_device *)dev_get_drvdata(&pdev->dev); for (; i < BCL_TYPE_MAX; i++) { if (!bcl_perph->param[i].tz_dev) Loading @@ -562,16 +586,23 @@ static int bcl_remove(struct platform_device *pdev) thermal_zone_of_sensor_unregister(&pdev->dev, bcl_perph->param[i].tz_dev); } bcl_perph = NULL; return 0; } static int bcl_probe(struct platform_device *pdev) { bcl_perph = devm_kzalloc(&pdev->dev, sizeof(*bcl_perph), GFP_KERNEL); if (!bcl_perph) struct bcl_device *bcl_perph = NULL; if (bcl_device_ct >= MAX_PERPH_COUNT) { dev_err(&pdev->dev, "Max bcl peripheral supported already.\n"); return -EINVAL; } bcl_devices[bcl_device_ct] = devm_kzalloc(&pdev->dev, sizeof(*bcl_devices[0]), GFP_KERNEL); if (!bcl_devices[bcl_device_ct]) return -ENOMEM; bcl_perph = bcl_devices[bcl_device_ct]; bcl_perph->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!bcl_perph->regmap) { Loading @@ -579,10 +610,11 @@ static int bcl_probe(struct platform_device *pdev) return -EINVAL; } bcl_get_devicetree_data(pdev); bcl_probe_vbat(pdev); bcl_probe_ibat(pdev); bcl_configure_bcl_peripheral(); bcl_device_ct++; bcl_get_devicetree_data(pdev, bcl_perph); bcl_probe_vbat(pdev, bcl_perph); bcl_probe_ibat(pdev, bcl_perph); bcl_configure_bcl_peripheral(bcl_perph); dev_set_drvdata(&pdev->dev, bcl_perph); Loading