summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/rtc/rtc-ds1307.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index f03d5ba96db1..bb43cf703efc 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -126,9 +126,14 @@ struct chip_desc {
u16 nvram_offset;
u16 nvram_size;
u16 trickle_charger_reg;
+ u8 trickle_charger_setup;
+ u8 (*do_trickle_setup)(struct i2c_client *, uint32_t, bool);
};
-static const struct chip_desc chips[last_ds_type] = {
+static u8 do_trickle_setup_ds1339(struct i2c_client *,
+ uint32_t ohms, bool diode);
+
+static struct chip_desc chips[last_ds_type] = {
[ds_1307] = {
.nvram_offset = 8,
.nvram_size = 56,
@@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = {
[ds_1339] = {
.alarm = 1,
.trickle_charger_reg = 0x10,
+ .do_trickle_setup = &do_trickle_setup_ds1339,
},
[ds_1340] = {
.trickle_charger_reg = 0x08,
@@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
return count;
}
+
/*----------------------------------------------------------------------*/
+static u8 do_trickle_setup_ds1339(struct i2c_client *client,
+ uint32_t ohms, bool diode)
+{
+ u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
+ DS1307_TRICKLE_CHARGER_NO_DIODE;
+
+ switch (ohms) {
+ case 250:
+ setup |= DS1307_TRICKLE_CHARGER_250_OHM;
+ break;
+ case 2000:
+ setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
+ break;
+ case 4000:
+ setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
+ break;
+ default:
+ dev_warn(&client->dev,
+ "Unsupported ohm value %u in dt\n", ohms);
+ return 0;
+ }
+ return setup;
+}
+
+static void ds1307_trickle_of_init(struct i2c_client *client,
+ struct chip_desc *chip)
+{
+ uint32_t ohms = 0;
+ bool diode = true;
+
+ if (!chip->do_trickle_setup)
+ goto out;
+ if (of_property_read_u32(client->dev.of_node, "trickle-resistor-ohms" , &ohms))
+ goto out;
+ if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
+ diode = false;
+ chip->trickle_charger_setup = chip->do_trickle_setup(client,
+ ohms, diode);
+out:
+ return;
+}
+
static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ds1307 *ds1307;
int err = -ENODEV;
int tmp;
- const struct chip_desc *chip = &chips[id->driver_data];
+ struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
unsigned char *buf;
@@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->client = client;
ds1307->type = id->driver_data;
- if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg)
+ if (!pdata && client->dev.of_node)
+ ds1307_trickle_of_init(client, chip);
+ else if (pdata && pdata->trickle_charger_setup)
+ chip->trickle_charger_setup = pdata->trickle_charger_setup;
+
+ if (chip->trickle_charger_setup && chip->trickle_charger_reg) {
+ dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n",
+ DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup,
+ chip->trickle_charger_reg);
i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
- DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup);
+ DS13XX_TRICKLE_CHARGER_MAGIC |
+ chip->trickle_charger_setup);
+ }
buf = ds1307->regs;
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {