Merge tag 'icc-5.10-rc2' of https://git.linaro.org/people/georgi.djakov/linux into...
[linux-2.6-microblaze.git] / drivers / rtc / rtc-ds1307.c
index 54c85cd..9f5f54c 100644 (file)
@@ -122,6 +122,9 @@ enum ds_type {
 #define RX8130_REG_FLAG_AF             BIT(3)
 #define RX8130_REG_CONTROL0            0x1e
 #define RX8130_REG_CONTROL0_AIE                BIT(3)
+#define RX8130_REG_CONTROL1            0x1f
+#define RX8130_REG_CONTROL1_INIEN      BIT(4)
+#define RX8130_REG_CONTROL1_CHGEN      BIT(5)
 
 #define MCP794XX_REG_CONTROL           0x07
 #      define MCP794XX_BIT_ALM0_EN     0x10
@@ -153,6 +156,7 @@ enum ds_type {
 #define DS1388_REG_CONTROL             0x0c
 #      define DS1388_BIT_RST           BIT(0)
 #      define DS1388_BIT_WDE           BIT(1)
+#      define DS1388_BIT_nEOSC         BIT(7)
 
 /* negative offset step is -2.034ppm */
 #define M41TXX_NEG_OFFSET_STEP_PPB     2034
@@ -190,6 +194,15 @@ struct chip_desc {
        u16                     trickle_charger_reg;
        u8                      (*do_trickle_setup)(struct ds1307 *, u32,
                                                    bool);
+       /* Does the RTC require trickle-resistor-ohms to select the value of
+        * the resistor between Vcc and Vbackup?
+        */
+       bool                    requires_trickle_resistor;
+       /* Some RTC's batteries and supercaps were charged by default, others
+        * allow charging but were not configured previously to do so.
+        * Remember this behavior to stay backwards compatible.
+        */
+       bool                    charge_default;
 };
 
 static const struct chip_desc chips[last_ds_type];
@@ -352,6 +365,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
                regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
                                   DS1340_BIT_OSF, 0);
                break;
+       case ds_1388:
+               regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,
+                                  DS1388_BIT_OSF, 0);
+               break;
        case mcp794xx:
                /*
                 * these bits were cleared when preparing the date/time
@@ -507,6 +524,8 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
        u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
                DS1307_TRICKLE_CHARGER_NO_DIODE;
 
+       setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
+
        switch (ohms) {
        case 250:
                setup |= DS1307_TRICKLE_CHARGER_250_OHM;
@@ -525,6 +544,16 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
        return setup;
 }
 
+static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
+{
+       /* make sure that the backup battery is enabled */
+       u8 setup = RX8130_REG_CONTROL1_INIEN;
+       if (diode)
+               setup |= RX8130_REG_CONTROL1_CHGEN;
+
+       return setup;
+}
+
 static irqreturn_t rx8130_irq(int irq, void *dev_id)
 {
        struct ds1307           *ds1307 = dev_id;
@@ -979,6 +1008,8 @@ static const struct chip_desc chips[last_ds_type] = {
                .bbsqi_bit      = DS1339_BIT_BBSQI,
                .trickle_charger_reg = 0x10,
                .do_trickle_setup = &do_trickle_setup_ds1339,
+               .requires_trickle_resistor = true,
+               .charge_default = true,
        },
        [ds_1340] = {
                .century_reg    = DS1307_REG_HOUR,
@@ -986,6 +1017,8 @@ static const struct chip_desc chips[last_ds_type] = {
                .century_bit    = DS1340_BIT_CENTURY,
                .do_trickle_setup = &do_trickle_setup_ds1339,
                .trickle_charger_reg = 0x08,
+               .requires_trickle_resistor = true,
+               .charge_default = true,
        },
        [ds_1341] = {
                .century_reg    = DS1307_REG_MONTH,
@@ -1009,6 +1042,8 @@ static const struct chip_desc chips[last_ds_type] = {
                .offset         = 0x10,
                .irq_handler = rx8130_irq,
                .rtc_ops = &rx8130_rtc_ops,
+               .trickle_charger_reg = RX8130_REG_CONTROL1,
+               .do_trickle_setup = &do_trickle_setup_rx8130,
        },
        [m41t0] = {
                .rtc_ops        = &m41txx_rtc_ops,
@@ -1293,18 +1328,37 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
 static u8 ds1307_trickle_init(struct ds1307 *ds1307,
                              const struct chip_desc *chip)
 {
-       u32 ohms;
-       bool diode = true;
+       u32 ohms, chargeable;
+       bool diode = chip->charge_default;
 
        if (!chip->do_trickle_setup)
                return 0;
 
        if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms",
-                                    &ohms))
+                                    &ohms) && chip->requires_trickle_resistor)
                return 0;
 
-       if (device_property_read_bool(ds1307->dev, "trickle-diode-disable"))
+       /* aux-voltage-chargeable takes precedence over the deprecated
+        * trickle-diode-disable
+        */
+       if (!device_property_read_u32(ds1307->dev, "aux-voltage-chargeable",
+                                    &chargeable)) {
+               switch (chargeable) {
+               case 0:
+                       diode = false;
+                       break;
+               case 1:
+                       diode = true;
+                       break;
+               default:
+                       dev_warn(ds1307->dev,
+                                "unsupported aux-voltage-chargeable value\n");
+                       break;
+               }
+       } else if (device_property_read_bool(ds1307->dev,
+                                            "trickle-diode-disable")) {
                diode = false;
+       }
 
        return chip->do_trickle_setup(ds1307, ohms, diode);
 }
@@ -1758,7 +1812,6 @@ static int ds1307_probe(struct i2c_client *client,
                trickle_charger_setup = pdata->trickle_charger_setup;
 
        if (trickle_charger_setup && chip->trickle_charger_reg) {
-               trickle_charger_setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
                dev_dbg(ds1307->dev,
                        "writing trickle charger info 0x%x to 0x%x\n",
                        trickle_charger_setup, chip->trickle_charger_reg);
@@ -1881,6 +1934,19 @@ static int ds1307_probe(struct i2c_client *client,
                                     DS1307_REG_HOUR << 4 | 0x08, hour);
                }
                break;
+       case ds_1388:
+               err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
+               if (err) {
+                       dev_dbg(ds1307->dev, "read error %d\n", err);
+                       goto exit;
+               }
+
+               /* oscillator off?  turn it on, so clock can tick. */
+               if (tmp & DS1388_BIT_nEOSC) {
+                       tmp &= ~DS1388_BIT_nEOSC;
+                       regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
+               }
+               break;
        default:
                break;
        }