static int twl4030_madc_battery_probe(struct platform_device *pdev) { struct twl4030_madc_battery *twl4030_madc_bat; struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data; struct power_supply_config psy_cfg = {}; int ret = 0; twl4030_madc_bat = devm_kzalloc(&pdev->dev, sizeof(*twl4030_madc_bat), GFP_KERNEL); if (!twl4030_madc_bat) return -ENOMEM; twl4030_madc_bat->channel_temp = iio_channel_get(&pdev->dev, "temp"); if (IS_ERR(twl4030_madc_bat->channel_temp)) { ret = PTR_ERR(twl4030_madc_bat->channel_temp); goto err; } twl4030_madc_bat->channel_ichg = iio_channel_get(&pdev->dev, "ichg"); if (IS_ERR(twl4030_madc_bat->channel_ichg)) { ret = PTR_ERR(twl4030_madc_bat->channel_ichg); goto err_temp; } twl4030_madc_bat->channel_vbat = iio_channel_get(&pdev->dev, "vbat"); if (IS_ERR(twl4030_madc_bat->channel_vbat)) { ret = PTR_ERR(twl4030_madc_bat->channel_vbat); goto err_ichg; } /* sort charging and discharging calibration data */ sort(pdata->charging, pdata->charging_size, sizeof(struct twl4030_madc_bat_calibration), twl4030_cmp, NULL); sort(pdata->discharging, pdata->discharging_size, sizeof(struct twl4030_madc_bat_calibration), twl4030_cmp, NULL); twl4030_madc_bat->pdata = pdata; platform_set_drvdata(pdev, twl4030_madc_bat); psy_cfg.drv_data = twl4030_madc_bat; twl4030_madc_bat->psy = power_supply_register(&pdev->dev, &twl4030_madc_bat_desc, &psy_cfg); if (IS_ERR(twl4030_madc_bat->psy)) { ret = PTR_ERR(twl4030_madc_bat->psy); goto err_vbat; } return 0; err_vbat: iio_channel_release(twl4030_madc_bat->channel_vbat); err_ichg: iio_channel_release(twl4030_madc_bat->channel_ichg); err_temp: iio_channel_release(twl4030_madc_bat->channel_temp); err: return ret; }
static int rx51_battery_probe(struct platform_device *pdev) { struct power_supply_config psy_cfg = {}; struct rx51_device_info *di; int ret; di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); if (!di) return -ENOMEM; platform_set_drvdata(pdev, di); di->dev = &pdev->dev; di->bat_desc.name = "rx51-battery"; di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; di->bat_desc.properties = rx51_battery_props; di->bat_desc.num_properties = ARRAY_SIZE(rx51_battery_props); di->bat_desc.get_property = rx51_battery_get_property; psy_cfg.drv_data = di; di->channel_temp = iio_channel_get(di->dev, "temp"); if (IS_ERR(di->channel_temp)) { ret = PTR_ERR(di->channel_temp); goto error; } di->channel_bsi = iio_channel_get(di->dev, "bsi"); if (IS_ERR(di->channel_bsi)) { ret = PTR_ERR(di->channel_bsi); goto error_channel_temp; } di->channel_vbat = iio_channel_get(di->dev, "vbat"); if (IS_ERR(di->channel_vbat)) { ret = PTR_ERR(di->channel_vbat); goto error_channel_bsi; } di->bat = power_supply_register(di->dev, &di->bat_desc, &psy_cfg); if (IS_ERR(di->bat)) { ret = PTR_ERR(di->bat); goto error_channel_vbat; } return 0; error_channel_vbat: iio_channel_release(di->channel_vbat); error_channel_bsi: iio_channel_release(di->channel_bsi); error_channel_temp: iio_channel_release(di->channel_temp); error: return ret; }
static void lp8788_setup_adc_channel(struct lp8788_charger *pchg) { struct lp8788_charger_platform_data *pdata = pchg->pdata; struct device *dev = pchg->lp->dev; struct iio_channel *chan; enum lp8788_adc_id id; const char *chan_name[LPADC_MAX] = { [LPADC_VBATT_5P5] = "vbatt-5p5", [LPADC_VBATT_6P0] = "vbatt-6p0", [LPADC_VBATT_5P0] = "vbatt-5p0", [LPADC_ADC1] = "adc1", [LPADC_ADC2] = "adc2", [LPADC_ADC3] = "adc3", [LPADC_ADC4] = "adc4", }; if (!pdata) return; id = pdata->vbatt_adc; switch (id) { case LPADC_VBATT_5P5: case LPADC_VBATT_6P0: case LPADC_VBATT_5P0: chan = iio_channel_get(NULL, chan_name[id]); pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; break; default: dev_err(dev, "invalid ADC id for VBATT: %d\n", id); pchg->chan[LP8788_VBATT] = NULL; break; } id = pdata->batt_temp_adc; switch (id) { case LPADC_ADC1: case LPADC_ADC2: case LPADC_ADC3: case LPADC_ADC4: chan = iio_channel_get(NULL, chan_name[id]); pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; break; default: dev_err(dev, "invalid ADC id for BATT_TEMP : %d\n", id); pchg->chan[LP8788_BATT_TEMP] = NULL; break; } }
/** * pmic_read_adc_val - read ADC value of specified sensors * @channel: channel of the sensor to be sampled * @sensor_val: pointer to the charger property to hold sampled value * @chc : battery info pointer * * Returns 0 if success */ static int pmic_read_adc_val(const char *map, const char *name, int *raw_val, struct pmic_fg_info *info) { int ret, val; struct iio_channel *indio_chan; indio_chan = iio_channel_get(NULL, name); if (IS_ERR_OR_NULL(indio_chan)) { ret = PTR_ERR(indio_chan); goto exit; } ret = iio_read_channel_raw(indio_chan, &val); if (ret) { dev_err(&info->pdev->dev, "IIO channel read error\n"); goto err_exit; } dev_dbg(&info->pdev->dev, "adc raw val=%x\n", val); *raw_val = val; err_exit: iio_channel_release(indio_chan); exit: return ret; }
static void lp8788_setup_adc_channel(struct device *dev, struct lp8788_charger *pchg) { struct lp8788_charger_platform_data *pdata = pchg->pdata; struct iio_channel *chan; if (!pdata) return; /* ADC channel for battery voltage */ chan = iio_channel_get(dev, pdata->adc_vbatt); pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; /* ADC channel for battery temperature */ chan = iio_channel_get(dev, pdata->adc_batt_temp); pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; }
static int gadc_thermal_probe(struct platform_device *pdev) { struct gadc_thermal_info *gti; int ret; if (!pdev->dev.of_node) { dev_err(&pdev->dev, "Only DT based supported\n"); return -ENODEV; } gti = devm_kzalloc(&pdev->dev, sizeof(*gti), GFP_KERNEL); if (!gti) return -ENOMEM; ret = gadc_thermal_read_linear_lookup_table(&pdev->dev, gti); if (ret < 0) return ret; gti->dev = &pdev->dev; platform_set_drvdata(pdev, gti); gti->channel = iio_channel_get(&pdev->dev, "sensor-channel"); if (IS_ERR(gti->channel)) { ret = PTR_ERR(gti->channel); dev_err(&pdev->dev, "IIO channel not found: %d\n", ret); return ret; } gti->tz_dev = thermal_zone_of_sensor_register(&pdev->dev, 0, gti, &gadc_thermal_ops); if (IS_ERR(gti->tz_dev)) { ret = PTR_ERR(gti->tz_dev); dev_err(&pdev->dev, "Thermal zone sensor register failed: %d\n", ret); goto sensor_fail; } return 0; sensor_fail: iio_channel_release(gti->channel); return ret; }
/* * sd_cv_batt_id_resistor - calculate the battery id resistor (Ohm) * return - the resistor value (Ohm) */ int sd_cv_batt_id_resistor() { int ret; int val = 0; int resistor = 0; int adc = 0; int auto_cur_sel = 0; int battid_cursrc = 0; struct iio_channel *indio_chan = NULL; /* Get battid pmic channel */ indio_chan = iio_channel_get(NULL, SDCV_BATTID_CHANNEL_NAME); if (IS_ERR_OR_NULL(indio_chan)) { pr_err("%s: IIO channel get error!!\n", __func__); return -1; } /* Read pmic battid ADC */ #if 0 ret = iio_read_channel_raw(indio_chan, &val); if (ret) { pr_err("%s: unable to read batid", __func__); return -1; } pr_info("%s: IIO channel read Sucess, val=%.3X\n", __func__, val); #endif adc = sd_cv_get_adc_value(SDCV_BATTIDRSLTH_REG, &auto_cur_sel); if (adc < 0 || auto_cur_sel == 0) { pr_err("%s: fail to get batt id result from 0x%X", __func__, SDCV_BATTIDRSLTH_REG); return -1; } pr_info("%s: adc=0x%X, auto_cur_sel=%d\n", __func__, adc, auto_cur_sel); /* The formula for calculating the battery id resistor */ resistor = adc * 293 * 1000 / auto_cur_sel; /* Release adc channel */ iio_channel_release(indio_chan); return resistor; }
int shady_cove_get_id(struct dwc_otg2 *otg) { u8 schgrirq1; struct iio_channel *chan; int ret, rid, id = RID_UNKNOWN; ret = intel_scu_ipc_ioread8(PMIC_SCHGRIRQ1, &schgrirq1); if (ret) { otg_err(otg, "Fail to read id\n"); return id; } /* PMIC_SCHGRIRQ1_SUSBIDDET bit definition: * 0 = RID_A/B/C ; 1 = RID_GND ; 2 = RID_FLOAT */ if (schgrirq1 & PMIC_SCHGRIRQ1_SUSBIDDET(2)) return RID_FLOAT; else if (schgrirq1 & PMIC_SCHGRIRQ1_SUSBIDDET(1)) return RID_GND; chan = iio_channel_get(NULL, "USBID"); if (IS_ERR_OR_NULL(chan)) { otg_err(otg, "%s: Fail to get USBID channel\n", __func__); return id; } ret = iio_read_channel_raw(chan, &rid); if (ret) { otg_err(otg, "%s: Fail to read USBID channel", __func__); goto done; } if ((rid > 11150) && (rid < 13640)) id = RID_A; else if ((rid > 6120) && (rid < 7480)) id = RID_B; else if ((rid > 3285) && (rid < 4015)) id = RID_C; done: iio_channel_release(chan); return id; }
/* * sd_cv_batt_vol - calculate the battery voltage * return - the battery voltage value (mV) */ int sd_cv_batt_vol() { int ret; int val = 0; int volt = 0; int adc = 0; int battid_cursrc = 0; struct iio_channel *indio_chan = NULL; /* Get vbat pmic channel */ indio_chan = iio_channel_get(NULL, SDCV_VBAT_CHANNEL_NAME); if (IS_ERR_OR_NULL(indio_chan)) { pr_err("%s: IIO channel get error!!\n", __func__); return -1; } /* Read pmic vbat ADC */ ret = iio_read_channel_raw(indio_chan, &val); if (ret) { pr_err("%s: unable to read vbat", __func__); return -1; } pr_debug("%s: IIO channel read Sucess, val=%.3X\n", __func__, val); adc = sd_cv_get_adc_value(SDCV_VBATRSLTH_REG, NULL); if (adc < 0) { pr_err("%s: fail to get vbat result from 0x%X", __func__, SDCV_VBATRSLTH_REG); return -1; } pr_debug("%s: adc=0x%X\n", __func__, adc); /* The formula for calculating the battery voltage */ volt = adc * 1250 / 1000; /* Release adc channel */ iio_channel_release(indio_chan); return volt; }
static int gab_probe(struct platform_device *pdev) { struct gab *adc_bat; struct power_supply_desc *psy_desc; struct power_supply_config psy_cfg = {}; struct gab_platform_data *pdata = pdev->dev.platform_data; enum power_supply_property *properties; int ret = 0; int chan; int index = 0; adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL); if (!adc_bat) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } psy_cfg.drv_data = adc_bat; psy_desc = &adc_bat->psy_desc; psy_desc->name = pdata->battery_info.name; /* bootup default values for the battery */ adc_bat->cable_plugged = false; adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING; psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; psy_desc->get_property = gab_get_property; psy_desc->external_power_changed = gab_ext_power_changed; adc_bat->pdata = pdata; /* * copying the static properties and allocating extra memory for holding * the extra configurable properties received from platform data. */ psy_desc->properties = kcalloc(ARRAY_SIZE(gab_props) + ARRAY_SIZE(gab_chan_name), sizeof(*psy_desc->properties), GFP_KERNEL); if (!psy_desc->properties) { ret = -ENOMEM; goto first_mem_fail; } memcpy(psy_desc->properties, gab_props, sizeof(gab_props)); properties = (enum power_supply_property *) ((char *)psy_desc->properties + sizeof(gab_props)); /* * getting channel from iio and copying the battery properties * based on the channel supported by consumer device. */ for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { adc_bat->channel[chan] = iio_channel_get(&pdev->dev, gab_chan_name[chan]); if (IS_ERR(adc_bat->channel[chan])) { ret = PTR_ERR(adc_bat->channel[chan]); adc_bat->channel[chan] = NULL; } else { /* copying properties for supported channels only */ memcpy(properties + sizeof(*(psy_desc->properties)) * index, &gab_dyn_props[chan], sizeof(gab_dyn_props[chan])); index++; } } /* none of the channels are supported so let's bail out */ if (index == 0) { ret = -ENODEV; goto second_mem_fail; } /* * Total number of properties is equal to static properties * plus the dynamic properties.Some properties may not be set * as come channels may be not be supported by the device.So * we need to take care of that. */ psy_desc->num_properties = ARRAY_SIZE(gab_props) + index; adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg); if (IS_ERR(adc_bat->psy)) { ret = PTR_ERR(adc_bat->psy); goto err_reg_fail; } INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work); if (gpio_is_valid(pdata->gpio_charge_finished)) { int irq; ret = gpio_request(pdata->gpio_charge_finished, "charged"); if (ret) goto gpio_req_fail; irq = gpio_to_irq(pdata->gpio_charge_finished); ret = request_any_context_irq(irq, gab_charged, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "battery charged", adc_bat); if (ret < 0) goto err_gpio; } platform_set_drvdata(pdev, adc_bat); /* Schedule timer to check current status */ schedule_delayed_work(&adc_bat->bat_work, msecs_to_jiffies(0)); return 0; err_gpio: gpio_free(pdata->gpio_charge_finished); gpio_req_fail: power_supply_unregister(adc_bat->psy); err_reg_fail: for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { if (adc_bat->channel[chan]) iio_channel_release(adc_bat->channel[chan]); } second_mem_fail: kfree(psy_desc->properties); first_mem_fail: return ret; }