mfd: rn5t618: Make restart handler atomic safe
[linux-2.6-microblaze.git] / drivers / mfd / rn5t618.c
index 232de50..7497edf 100644 (file)
@@ -77,7 +77,7 @@ static const struct regmap_irq_chip rc5t619_irq_chip = {
        .mask_invert = true,
 };
 
-static struct rn5t618 *rn5t618_pm_power_off;
+static struct i2c_client *rn5t618_pm_power_off;
 static struct notifier_block rn5t618_restart_handler;
 
 static int rn5t618_irq_init(struct rn5t618 *rn5t618)
@@ -110,13 +110,38 @@ static int rn5t618_irq_init(struct rn5t618 *rn5t618)
 
 static void rn5t618_trigger_poweroff_sequence(bool repower)
 {
+       int ret;
+
        /* disable automatic repower-on */
-       regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_REPCNT,
-                          RN5T618_REPCNT_REPWRON,
-                          repower ? RN5T618_REPCNT_REPWRON : 0);
+       ret = i2c_smbus_read_byte_data(rn5t618_pm_power_off, RN5T618_REPCNT);
+       if (ret < 0)
+               goto err;
+
+       ret &= ~RN5T618_REPCNT_REPWRON;
+       if (repower)
+               ret |= RN5T618_REPCNT_REPWRON;
+
+       ret = i2c_smbus_write_byte_data(rn5t618_pm_power_off,
+                                       RN5T618_REPCNT, (u8)ret);
+       if (ret < 0)
+               goto err;
+
        /* start power-off sequence */
-       regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_SLPCNT,
-                          RN5T618_SLPCNT_SWPWROFF, RN5T618_SLPCNT_SWPWROFF);
+       ret = i2c_smbus_read_byte_data(rn5t618_pm_power_off, RN5T618_SLPCNT);
+       if (ret < 0)
+               goto err;
+
+       ret |= RN5T618_SLPCNT_SWPWROFF;
+
+       ret = i2c_smbus_write_byte_data(rn5t618_pm_power_off,
+                                       RN5T618_SLPCNT, (u8)ret);
+       if (ret < 0)
+               goto err;
+
+       return;
+
+err:
+       dev_alert(&rn5t618_pm_power_off->dev, "Failed to shutdown (err = %d)\n", ret);
 }
 
 static void rn5t618_power_off(void)
@@ -189,7 +214,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c)
                return ret;
        }
 
-       rn5t618_pm_power_off = priv;
+       rn5t618_pm_power_off = i2c;
        if (of_device_is_system_power_controller(i2c->dev.of_node)) {
                if (!pm_power_off)
                        pm_power_off = rn5t618_power_off;
@@ -211,9 +236,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c)
 
 static int rn5t618_i2c_remove(struct i2c_client *i2c)
 {
-       struct rn5t618 *priv = i2c_get_clientdata(i2c);
-
-       if (priv == rn5t618_pm_power_off) {
+       if (i2c == rn5t618_pm_power_off) {
                rn5t618_pm_power_off = NULL;
                pm_power_off = NULL;
        }