static int smb347_get_property(struct power_supply *ps, enum power_supply_property psp, union power_supply_propval *val) { unsigned char value = 0xff; int err = 0; switch (psp) { case POWER_SUPPLY_PROP_ONLINE: err = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_C, &value); if (err < 0) val->intval = err; else val->intval = value & 0x1; break; case POWER_SUPPLY_PROP_STATUS: err = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_C, &value); if (err < 0) val->intval = err; else val->intval = value & 0x6; break; default: return -EINVAL; } return 0; }
static void summit_smb347_irq_worker(struct work_struct *unused) { unsigned char value = 0xFF; int ret = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_D, &value); printk(KERN_INFO "Status register D: 0x%x\n", value); ret = summit_smb347_i2c_read(SUMMIT_SMB347_INTSTAT_REG_F, &value); printk(KERN_INFO "Interrupt Status register F: 0x%x\n", value); ret = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_C, &value); printk(KERN_INFO "Status register C: 0x%x\n", value); ret = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_B, &value); printk(KERN_INFO "Status register B: 0x%x\n", value); enable_irq(summit_smb347_i2c_client->irq); return; }
static int summit_smb347_usb_valid(void) { unsigned char value = 0xff; summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_E, &value); if (summit_smb347_charger_connected() && (value & 0x80)) return 1; else return 0; }
/* Check to see if charger is connected or not */ static int summit_smb347_charger_connected(void) { unsigned char value = 0xff; summit_smb347_i2c_read(SUMMIT_SMB347_INTERRUPT_STAT, &value); if (value & 0x4) return 1; else return 0; }
static int summit_smb347_read_id(int *id) { int error = 0; unsigned char value = 0xFF; error = summit_smb347_i2c_read(SUMMIT_SMB347_ID, &value); if (!error) { *id = value; } return error; }
static ssize_t smb347_register_show(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { unsigned char value = 0xff; char *curr = buf; summit_smb347_i2c_read(smb347_reg_number, &value); curr += sprintf(curr, "SMB347 Register %d\n", smb347_reg_number); curr += sprintf(curr, "\n"); curr += sprintf(curr, " Value: 0x%x\n", value); curr += sprintf(curr, "\n"); return curr - buf; };
/* Enable/disable charging */ static void summit_smb347_enable_charging(int enable) { unsigned char value = 0xff; summit_smb347_i2c_read(SUMMIT_SMB347_COMMAND_REG_A, &value); if (!enable) { value &= ~(0x2); } else { value |= 0x2; } summit_smb347_i2c_write(SUMMIT_SMB347_COMMAND_REG_A, value); atomic_set(&summit_smb347_charger_state, enable); }
/* AC property */ static int smb347_get_ac_property(struct power_supply *ps, enum power_supply_property psp, union power_supply_propval *val) { unsigned char value = 0xff; switch (psp) { case POWER_SUPPLY_PROP_ONLINE: summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_D, &value); val->intval = value; break; case POWER_SUPPLY_PROP_STATUS: val->intval = summit_smb347_charger_connected(); break; default: return -EINVAL; } return 0; }
static int summit_smb347_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct summit_smb347_info *info; int ret = 0; #ifdef SUMMIT_SMB347_DEBUG int i = 0; #endif int error = 0; unsigned char value = 0xff; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { return -ENOMEM; } client->addr = SUMMIT_SMB347_I2C_ADDRESS; i2c_set_clientdata(client, info); info->client = client; info->charger.name = "summit_smb347"; info->charger.type = POWER_SUPPLY_TYPE_MAINS; info->charger.get_property = smb347_get_property; info->charger.properties = smb347_charger_props; info->charger.num_properties = ARRAY_SIZE(smb347_charger_props); ret = power_supply_register(&client->dev, &info->charger); if (ret) { dev_err(&client->dev, "failed: power supply register\n"); i2c_set_clientdata(client, NULL); kfree(info); return ret; } summit_smb347_i2c_client = info->client; summit_smb347_i2c_client->addr = SUMMIT_SMB347_I2C_ADDRESS; if (summit_smb347_read_id(&summit_smb347_id_reg) < 0) return -ENODEV; printk(KERN_INFO "Summit SMB347 detected, chip_id=0x%x\n", summit_smb347_id_reg); ret = request_irq(summit_smb347_i2c_client->irq, summit_smb347_irq, IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, "summit_smb347", NULL); if (ret != 0) { printk(KERN_ERR "Failed to request IRQ %d: %d\n", summit_smb347_i2c_client->irq, ret); } summit_smb347_init_registers(); #ifdef SUMMIT_SMB347_DEBUG for (i = 0; i <= 0xE; i++) { ret = summit_smb347_i2c_read(i, &value); printk(KERN_INFO "summit_smb347: reg=%d, value=0x%x\n", i, value); } for (i = 0x30; i <= 0x3F; i++) { ret = summit_smb347_i2c_read(i, &value); printk(KERN_INFO "summit_smb347: reg=%d, value=0x%x\n", i, value); } #endif error = sysdev_class_register(&smb347_reg_sysclass); if (!error) error = sysdev_register(&device_smb347_reg); if (!error) error = sysdev_create_file(&device_smb347_reg, &attr_smb347_reg); error = sysdev_class_register(&smb347_register_sysclass); if (!error) error = sysdev_register(&device_smb347_register); if (!error) error = sysdev_create_file(&device_smb347_register, &attr_smb347_register); return 0; }
static int smb347_get_battery_property(struct power_supply *ps, enum power_supply_property psp, union power_supply_propval *val) { unsigned char value = 0xff; int err = 0; switch (psp) { case POWER_SUPPLY_PROP_STATUS: err = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_C, &value); if (err < 0) val->intval = POWER_SUPPLY_STATUS_UNKNOWN; else { if (value & 0x6) val->intval = POWER_SUPPLY_STATUS_CHARGING; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; } break; case POWER_SUPPLY_PROP_CHARGE_TYPE: err = summit_smb347_i2c_read(SUMMIT_SMB347_STATUS_REG_C, &value); if (err < 0) val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; else { if (value & 0x4) val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; if (value & 0x2) val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; } break; case POWER_SUPPLY_PROP_TEMP: val->intval = bq27541_temperature; break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = bq27541_battery_capacity; break; case POWER_SUPPLY_PROP_CAPACITY_LEVEL: val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; if (bq27541_battery_capacity <= 5) val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; if (bq27541_battery_capacity > 80) val->intval = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; if (bq27541_battery_capacity == 100) val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; if (bq27541_battery_capacity <= 20) val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval = bq27541_voltage; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = POWER_SUPPLY_HEALTH_GOOD; if (summit_smb347_temperature_hot) val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; if (summit_smb347_temperature_cold) val->intval = POWER_SUPPLY_HEALTH_COLD; if (summit_smb347_voltage_hi) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; if (summit_smb347_voltage_low) val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; break; default: return -EINVAL; } return 0; }