* @ver: information of the version
  * @cap: the capture mode attributes
  * @power: current sensor's power status
- * @ctrl_sync: true means all controls of the sensor are initialized
- * @int_capture: true means the capture interrupt is issued once
+ * @isp_ready: 1 when the ISP controller has completed booting
+ * @ctrl_sync: 1 when the control handler state is restored in H/W
  * @lock_ae: true means the Auto Exposure is locked
  * @lock_awb: true means the Aut WhiteBalance is locked
  * @resolution:        register value for current resolution
 
        struct m5mols_version ver;
        struct m5mols_capture cap;
-       bool power;
-       bool ctrl_sync;
+
+       unsigned int isp_ready:1;
+       unsigned int power:1;
+       unsigned int ctrl_sync:1;
+
        bool lock_ae;
        bool lock_awb;
        u8 resolution;
        int (*set_power)(struct device *dev, int on);
 };
 
-#define is_powered(__info) (__info->power)
 #define is_ctrl_synced(__info) (__info->ctrl_sync)
 #define is_available_af(__info)        (__info->ver.af)
 #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
 
  * @reg: combination of size, category and command for the I2C packet
  * @size: desired size of I2C packet
  * @val: read value
+ *
+ * Returns 0 on success, or else negative errno.
  */
 static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct m5mols_info *info = to_m5mols(sd);
        u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
        u8 category = I2C_CATEGORY(reg);
        u8 cmd = I2C_COMMAND(reg);
        usleep_range(200, 200);
 
        ret = i2c_transfer(client->adapter, msg, 2);
-       if (ret < 0) {
-               v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
-                        size, category, cmd, ret);
-               return ret;
+
+       if (ret == 2) {
+               *val = m5mols_swap_byte(&rbuf[1], size);
+               return 0;
        }
 
-       *val = m5mols_swap_byte(&rbuf[1], size);
+       if (info->isp_ready)
+               v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
+                        size, category, cmd, ret);
 
-       return 0;
+       return ret < 0 ? ret : -EIO;
 }
 
 int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
  * m5mols_write - I2C command write function
  * @reg: combination of size, category and command for the I2C packet
  * @val: value to write
+ *
+ * Returns 0 on success, or else negative errno.
  */
 int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct m5mols_info *info = to_m5mols(sd);
        u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
        u8 category = I2C_CATEGORY(reg);
        u8 cmd = I2C_COMMAND(reg);
        usleep_range(200, 200);
 
        ret = i2c_transfer(client->adapter, msg, 1);
-       if (ret < 0) {
-               v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n",
-                       size, category, cmd, ret);
-               return ret;
-       }
+       if (ret == 1)
+               return 0;
 
-       return 0;
+       if (info->isp_ready)
+               v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
+                        category, cmd, ret);
+
+       return ret < 0 ? ret : -EIO;
 }
 
 /**
                        return ret;
 
                v4l2_ctrl_handler_setup(&info->handle);
-               info->ctrl_sync = true;
+               info->ctrl_sync = 1;
        }
 
        return ret;
        const struct m5mols_platform_data *pdata = info->pdata;
        int ret;
 
-       if (enable) {
-               if (is_powered(info))
-                       return 0;
+       if (info->power == enable)
+               return 0;
 
+       if (enable) {
                if (info->set_power) {
                        ret = info->set_power(&client->dev, 1);
                        if (ret)
                }
 
                gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity);
-               usleep_range(1000, 1000);
-               info->power = true;
+               info->power = 1;
 
                return ret;
        }
 
-       if (!is_powered(info))
-               return 0;
-
        ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
        if (ret)
                return ret;
                info->set_power(&client->dev, 0);
 
        gpio_set_value(pdata->gpio_reset, pdata->reset_polarity);
-       usleep_range(1000, 1000);
-       info->power = false;
+
+       info->isp_ready = 0;
+       info->power = 0;
 
        return ret;
 }
 }
 
 /**
- * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core.
+ * m5mols_fw_start - M-5MOLS internal ARM controller initialization
  *
- * Booting internal ARM core makes the M-5MOLS is ready for getting commands
- * with I2C. It's the first thing to be done after it powered up. It must wait
- * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting.
+ * Execute the M-5MOLS internal ARM controller initialization sequence.
+ * This function should be called after the supply voltage has been
+ * applied and before any requests to the device are made.
  */
-static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
+static int m5mols_fw_start(struct v4l2_subdev *sd)
 {
+       struct m5mols_info *info = to_m5mols(sd);
        int ret;
 
-       ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+       atomic_set(&info->irq_done, 0);
+       /* Wait until I2C slave is initialized in Flash Writer mode */
+       ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
+                              M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
+       if (!ret)
+               ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+       if (!ret)
+               ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
        if (ret < 0)
                return ret;
 
-       msleep(520);
+       info->isp_ready = 1;
 
        ret = m5mols_get_version(sd);
        if (!ret)
        if (on) {
                ret = m5mols_sensor_power(info, true);
                if (!ret)
-                       ret = m5mols_sensor_armboot(sd);
+                       ret = m5mols_fw_start(sd);
                if (!ret)
                        ret = m5mols_init_controls(info);
                if (ret)
        ret = m5mols_sensor_power(info, false);
        if (!ret) {
                v4l2_ctrl_handler_free(&info->handle);
-               info->ctrl_sync = false;
+               info->ctrl_sync = 0;
        }
 
        return ret;