static int max17047_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct max17047_fuelgauge_data *fg_data = container_of(psy, struct max17047_fuelgauge_data, fuelgauge); #ifdef USE_TRIM_ERROR_DETECTION if (fg_data->trim_err == true) { switch (psp) { case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_VOLTAGE_AVG: val->intval = 4200000; break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = 99; break; case POWER_SUPPLY_PROP_TEMP: val->intval = 300; break; default: return -EINVAL; } return 0; } #endif switch (psp) { case POWER_SUPPLY_PROP_VOLTAGE_NOW: switch (val->intval) { case VOLTAGE_TYPE_VCELL: val->intval = max17047_get_vcell(fg_data->client); break; case VOLTAGE_TYPE_VFOCV: val->intval = max17047_get_vfocv(fg_data->client); break; default: val->intval = max17047_get_vcell(fg_data->client); break; } break; case POWER_SUPPLY_PROP_VOLTAGE_AVG: val->intval = max17047_get_avgvcell(fg_data->client); break; case POWER_SUPPLY_PROP_CAPACITY: switch (val->intval) { case SOC_TYPE_ADJUSTED: val->intval = max17047_get_soc(fg_data->client); break; case SOC_TYPE_RAW: val->intval = max17047_get_rawsoc(fg_data->client); break; case SOC_TYPE_FULL: val->intval = fg_data->full_soc; break; default: val->intval = max17047_get_soc(fg_data->client); break; } break; case POWER_SUPPLY_PROP_TEMP: val->intval = max17047_get_temperature(fg_data->client); break; default: return -EINVAL; } return 0; }
static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct max17047_fuelgauge_data *fg_data; struct max17047_platform_data *pdata = client->dev.platform_data; int ret = -ENODEV; int rawsoc, firstsoc; pr_info("%s: fuelgauge init\n", __func__); if (!pdata) { pr_err("%s: no platform data\n", __func__); return -ENODEV; } if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) return -EIO; fg_data = kzalloc(sizeof(struct max17047_fuelgauge_data), GFP_KERNEL); if (!fg_data) return -ENOMEM; fg_data->client = client; fg_data->pdata = pdata; i2c_set_clientdata(client, fg_data); mutex_init(&fg_data->irq_lock); wake_lock_init(&fg_data->update_wake_lock, WAKE_LOCK_SUSPEND, "fuel-update"); #ifdef USE_TRIM_ERROR_DETECTION /* trim error detect */ fg_data->trim_err = max17047_detect_trim_error(fg_data); #endif /* Initialize full_soc, set this before fisrt SOC reading */ fg_data->full_soc = FULL_SOC_DEFAULT; /* first full_soc update */ rawsoc = max17047_get_rawsoc(fg_data->client); if (rawsoc > FULL_SOC_DEFAULT) max17047_adjust_fullsoc(client); firstsoc = max17047_get_soc(client); pr_info("%s: rsoc=%d, fsoc=%d, soc=%d\n", __func__, rawsoc, fg_data->full_soc, firstsoc); if (fg_data->pdata->psy_name) fg_data->fuelgauge.name = fg_data->pdata->psy_name; else fg_data->fuelgauge.name = "max17047-fuelgauge"; #if defined(CONFIG_MACH_GC1) fg_data->prev_status = POWER_SUPPLY_STATUS_DISCHARGING; #endif fg_data->fuelgauge.type = POWER_SUPPLY_TYPE_BATTERY; fg_data->fuelgauge.properties = max17047_fuelgauge_props; fg_data->fuelgauge.num_properties = ARRAY_SIZE(max17047_fuelgauge_props); fg_data->fuelgauge.get_property = max17047_get_property; fg_data->fuelgauge.set_property = max17047_set_property; ret = power_supply_register(&client->dev, &fg_data->fuelgauge); if (ret) { pr_err("%s: failed power supply register\n", __func__); goto err_psy_reg_fg; } /* Initialize fuelgauge registers */ max17047_reg_init(fg_data); /* Initialize fuelgauge alert */ max17047_alert_init(fg_data); INIT_DELAYED_WORK_DEFERRABLE(&fg_data->update_work, max17047_update_work); /* Request IRQ */ fg_data->irq = gpio_to_irq(fg_data->pdata->irq_gpio); ret = gpio_request(fg_data->pdata->irq_gpio, "fuelgauge-irq"); if (ret) { pr_err("%s: failed requesting gpio %d\n", __func__, fg_data->pdata->irq_gpio); goto err_irq; } gpio_direction_input(fg_data->pdata->irq_gpio); gpio_free(fg_data->pdata->irq_gpio); ret = request_threaded_irq(fg_data->irq, NULL, max17047_fuelgauge_isr, IRQF_TRIGGER_FALLING, "max17047-alert", fg_data); if (ret < 0) { pr_err("%s: fail to request max17047 irq: %d: %d\n", __func__, fg_data->irq, ret); goto err_irq; } ret = enable_irq_wake(fg_data->irq); if (ret < 0) { pr_err("%s: failed enable irq wake %d\n", __func__, fg_data->irq); goto err_enable_irq; } #ifdef DEBUG_FUELGAUGE_POLLING INIT_DELAYED_WORK_DEFERRABLE(&fg_data->polling_work, max17047_polling_work); schedule_delayed_work(&fg_data->polling_work, 0); #else max17047_test_read(fg_data); #endif pr_info("%s: probe complete\n", __func__); #if defined(CONFIG_TARGET_LOCALE_KOR) #ifdef CONFIG_DEBUG_FS fg_data->fg_debugfs_dir = debugfs_create_dir("fg_debug", NULL); if (fg_data->fg_debugfs_dir) { if (!debugfs_create_file("max17047_regs", 0644, fg_data->fg_debugfs_dir, fg_data, &max17047_debugfs_fops)) pr_err("%s : debugfs_create_file, error\n", __func__); if (!debugfs_create_file("default_data", 0644, fg_data->fg_debugfs_dir, fg_data, &max17047_debugfs_fops2)) pr_err("%s : debugfs_create_file2, error\n", __func__); } else pr_err("%s : debugfs_create_dir, error\n", __func__); #endif #endif return 0; err_enable_irq: free_irq(fg_data->irq, fg_data); err_irq: power_supply_unregister(&fg_data->fuelgauge); err_psy_reg_fg: wake_lock_destroy(&fg_data->update_wake_lock); mutex_destroy(&fg_data->irq_lock); kfree(fg_data); return ret; }