0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/kernel.h>
0014 #include <linux/err.h>
0015 #include <linux/power_supply.h>
0016 #include <linux/i2c.h>
0017 #include <linux/slab.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/regmap.h>
0020 #include <linux/bitops.h>
0021 #include <linux/devm-helpers.h>
0022
0023 #define SBS_CHARGER_REG_SPEC_INFO 0x11
0024 #define SBS_CHARGER_REG_STATUS 0x13
0025 #define SBS_CHARGER_REG_ALARM_WARNING 0x16
0026
0027 #define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(1)
0028 #define SBS_CHARGER_STATUS_RES_COLD BIT(9)
0029 #define SBS_CHARGER_STATUS_RES_HOT BIT(10)
0030 #define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14)
0031 #define SBS_CHARGER_STATUS_AC_PRESENT BIT(15)
0032
0033 #define SBS_CHARGER_POLL_TIME 500
0034
0035 struct sbs_info {
0036 struct i2c_client *client;
0037 struct power_supply *power_supply;
0038 struct regmap *regmap;
0039 struct delayed_work work;
0040 unsigned int last_state;
0041 };
0042
0043 static int sbs_get_property(struct power_supply *psy,
0044 enum power_supply_property psp,
0045 union power_supply_propval *val)
0046 {
0047 struct sbs_info *chip = power_supply_get_drvdata(psy);
0048 unsigned int reg;
0049
0050 reg = chip->last_state;
0051
0052 switch (psp) {
0053 case POWER_SUPPLY_PROP_PRESENT:
0054 val->intval = !!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT);
0055 break;
0056
0057 case POWER_SUPPLY_PROP_ONLINE:
0058 val->intval = !!(reg & SBS_CHARGER_STATUS_AC_PRESENT);
0059 break;
0060
0061 case POWER_SUPPLY_PROP_STATUS:
0062 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
0063
0064 if (!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT))
0065 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
0066 else if (reg & SBS_CHARGER_STATUS_AC_PRESENT &&
0067 !(reg & SBS_CHARGER_STATUS_CHARGE_INHIBITED))
0068 val->intval = POWER_SUPPLY_STATUS_CHARGING;
0069 else
0070 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
0071
0072 break;
0073
0074 case POWER_SUPPLY_PROP_HEALTH:
0075 if (reg & SBS_CHARGER_STATUS_RES_COLD)
0076 val->intval = POWER_SUPPLY_HEALTH_COLD;
0077 if (reg & SBS_CHARGER_STATUS_RES_HOT)
0078 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
0079 else
0080 val->intval = POWER_SUPPLY_HEALTH_GOOD;
0081
0082 break;
0083
0084 default:
0085 return -EINVAL;
0086 }
0087
0088 return 0;
0089 }
0090
0091 static int sbs_check_state(struct sbs_info *chip)
0092 {
0093 unsigned int reg;
0094 int ret;
0095
0096 ret = regmap_read(chip->regmap, SBS_CHARGER_REG_STATUS, ®);
0097 if (!ret && reg != chip->last_state) {
0098 chip->last_state = reg;
0099 power_supply_changed(chip->power_supply);
0100 return 1;
0101 }
0102
0103 return 0;
0104 }
0105
0106 static void sbs_delayed_work(struct work_struct *work)
0107 {
0108 struct sbs_info *chip = container_of(work, struct sbs_info, work.work);
0109
0110 sbs_check_state(chip);
0111
0112 schedule_delayed_work(&chip->work,
0113 msecs_to_jiffies(SBS_CHARGER_POLL_TIME));
0114 }
0115
0116 static irqreturn_t sbs_irq_thread(int irq, void *data)
0117 {
0118 struct sbs_info *chip = data;
0119 int ret;
0120
0121 ret = sbs_check_state(chip);
0122
0123 return ret ? IRQ_HANDLED : IRQ_NONE;
0124 }
0125
0126 static enum power_supply_property sbs_properties[] = {
0127 POWER_SUPPLY_PROP_STATUS,
0128 POWER_SUPPLY_PROP_PRESENT,
0129 POWER_SUPPLY_PROP_ONLINE,
0130 POWER_SUPPLY_PROP_HEALTH,
0131 };
0132
0133 static bool sbs_readable_reg(struct device *dev, unsigned int reg)
0134 {
0135 return reg >= SBS_CHARGER_REG_SPEC_INFO;
0136 }
0137
0138 static bool sbs_volatile_reg(struct device *dev, unsigned int reg)
0139 {
0140 switch (reg) {
0141 case SBS_CHARGER_REG_STATUS:
0142 return true;
0143 }
0144
0145 return false;
0146 }
0147
0148 static const struct regmap_config sbs_regmap = {
0149 .reg_bits = 8,
0150 .val_bits = 16,
0151 .max_register = SBS_CHARGER_REG_ALARM_WARNING,
0152 .readable_reg = sbs_readable_reg,
0153 .volatile_reg = sbs_volatile_reg,
0154 .val_format_endian = REGMAP_ENDIAN_LITTLE,
0155 };
0156
0157 static const struct power_supply_desc sbs_desc = {
0158 .name = "sbs-charger",
0159 .type = POWER_SUPPLY_TYPE_MAINS,
0160 .properties = sbs_properties,
0161 .num_properties = ARRAY_SIZE(sbs_properties),
0162 .get_property = sbs_get_property,
0163 };
0164
0165 static int sbs_probe(struct i2c_client *client,
0166 const struct i2c_device_id *id)
0167 {
0168 struct power_supply_config psy_cfg = {};
0169 struct sbs_info *chip;
0170 int ret, val;
0171
0172 chip = devm_kzalloc(&client->dev, sizeof(struct sbs_info), GFP_KERNEL);
0173 if (!chip)
0174 return -ENOMEM;
0175
0176 chip->client = client;
0177 psy_cfg.of_node = client->dev.of_node;
0178 psy_cfg.drv_data = chip;
0179
0180 i2c_set_clientdata(client, chip);
0181
0182 chip->regmap = devm_regmap_init_i2c(client, &sbs_regmap);
0183 if (IS_ERR(chip->regmap))
0184 return PTR_ERR(chip->regmap);
0185
0186
0187
0188
0189
0190 ret = regmap_read(chip->regmap, SBS_CHARGER_REG_STATUS, &val);
0191 if (ret)
0192 return dev_err_probe(&client->dev, ret, "Failed to get device status\n");
0193 chip->last_state = val;
0194
0195 chip->power_supply = devm_power_supply_register(&client->dev, &sbs_desc, &psy_cfg);
0196 if (IS_ERR(chip->power_supply))
0197 return dev_err_probe(&client->dev, PTR_ERR(chip->power_supply),
0198 "Failed to register power supply\n");
0199
0200
0201
0202
0203
0204
0205 if (client->irq) {
0206 ret = devm_request_threaded_irq(&client->dev, client->irq,
0207 NULL, sbs_irq_thread,
0208 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
0209 dev_name(&client->dev), chip);
0210 if (ret)
0211 return dev_err_probe(&client->dev, ret, "Failed to request irq\n");
0212 } else {
0213 ret = devm_delayed_work_autocancel(&client->dev, &chip->work,
0214 sbs_delayed_work);
0215 if (ret)
0216 return dev_err_probe(&client->dev, ret,
0217 "Failed to init work for polling\n");
0218
0219 schedule_delayed_work(&chip->work,
0220 msecs_to_jiffies(SBS_CHARGER_POLL_TIME));
0221 }
0222
0223 dev_info(&client->dev,
0224 "%s: smart charger device registered\n", client->name);
0225
0226 return 0;
0227 }
0228
0229 #ifdef CONFIG_OF
0230 static const struct of_device_id sbs_dt_ids[] = {
0231 { .compatible = "sbs,sbs-charger" },
0232 { },
0233 };
0234 MODULE_DEVICE_TABLE(of, sbs_dt_ids);
0235 #endif
0236
0237 static const struct i2c_device_id sbs_id[] = {
0238 { "sbs-charger", 0 },
0239 { }
0240 };
0241 MODULE_DEVICE_TABLE(i2c, sbs_id);
0242
0243 static struct i2c_driver sbs_driver = {
0244 .probe = sbs_probe,
0245 .id_table = sbs_id,
0246 .driver = {
0247 .name = "sbs-charger",
0248 .of_match_table = of_match_ptr(sbs_dt_ids),
0249 },
0250 };
0251 module_i2c_driver(sbs_driver);
0252
0253 MODULE_AUTHOR("Nicolas Saenz Julienne <nicolassaenzj@gmail.com>");
0254 MODULE_DESCRIPTION("SBS smart charger driver");
0255 MODULE_LICENSE("GPL v2");