[ERD][APR-103] [COMMON]chub : support multi-os for various sensors
authorBoyoung <eric.by.kim@samsung.com>
Tue, 23 Oct 2018 10:54:46 +0000 (19:54 +0900)
committerhskang <hs1218.kang@samsung.com>
Sun, 21 Apr 2019 09:08:29 +0000 (18:08 +0900)
Change-Id: I0768a2ba0d87fed58ce7e18877e60d5583f53529
Signed-off-by: Boyoung <eric.by.kim@samsung.com>
drivers/staging/nanohub/chub.c
drivers/staging/nanohub/chub.h
drivers/staging/nanohub/chub_dbg.c
drivers/staging/nanohub/chub_ipc.h
drivers/staging/nanohub/chub_log.c
drivers/staging/nanohub/chub_log.h
drivers/staging/nanohub/main.c

index 6c3e4feab7d31adc01f26ab42760899c3e25e609..bb51e5328e9bd730b147abd3168a6f32bf2ac468 100644 (file)
 #include "chub_dbg.h"
 #include "../../soc/samsung/cal-if/pmucal_shub.h"
 
+#define SENSOR_VARIATION 10
+
 #define WAIT_TIMEOUT_MS (1000)
+
 enum { CHUB_ON, CHUB_OFF };
 enum { C2A_ON, C2A_OFF };
 
+const char *os_image[SENSOR_VARIATION] = {
+       "os.checked_0.bin",
+       "os.checked_1.bin",
+       "os.checked_2.bin",
+       "os.checked_3.bin",
+       "os.checked_4.bin",
+       "os.checked_5.bin",
+       "os.checked_6.bin",
+       "os.checked_7.bin",
+       "os.checked_8.bin",
+};
+
 static DEFINE_MUTEX(reset_mutex);
 static DEFINE_MUTEX(pmu_shutdown_mutex);
-
-static int contexthub_get_token(struct contexthub_ipc_info *ipc)
+static inline int contexthub_get_token(struct contexthub_ipc_info *ipc, enum access_type acc)
 {
-       if (atomic_read(&ipc->in_reset))
-               return -EINVAL;
-
-       atomic_inc(&ipc->in_use_ipc);
-       return 0;
+       if (acc == HW_ACCESS) {
+               mutex_lock(&pmu_shutdown_mutex);
+               dev_info(ipc->dev, "%s: enter shutdown\n", __func__);
+       }
+       else if (acc == IPC_ACCESS)
+               return (atomic_read(&ipc->chub_status) == CHUB_ST_RUN) && !atomic_read(&ipc->in_reset);
+       return true;
 }
 
-static void contexthub_put_token(struct contexthub_ipc_info *ipc)
+static inline void contexthub_put_token(struct contexthub_ipc_info *ipc, enum access_type acc)
 {
-       atomic_dec(&ipc->in_use_ipc);
+       if (acc == HW_ACCESS) {
+               dev_info(ipc->dev, "%s: out shutdown\n", __func__);
+               mutex_unlock(&pmu_shutdown_mutex);
+       }
 }
 
 /* host interface functions */
@@ -80,9 +99,16 @@ int contexthub_is_run(struct contexthub_ipc_info *ipc)
 }
 
 /* request contexthub to host driver */
-int contexthub_request(struct contexthub_ipc_info *ipc)
+int contexthub_request(struct contexthub_ipc_info *ipc, enum access_type acc)
 {
-       if (!ipc->powermode)
+       if (!contexthub_get_token(ipc, acc)) {
+               dev_info(ipc->dev, "%s: %s isn't accesable: chub_status: %d, in_reset:%d\n",
+                       __func__, (acc == HW_ACCESS) ? "hw" : "ipc",
+                       atomic_read(&ipc->chub_status), atomic_read(&ipc->in_reset));
+               return -EINVAL;
+       }
+
+       if ((acc == HW_ACCESS) || !ipc->powermode)
                return 0;
 
 #ifdef CONFIG_CHRE_SENSORHUB_HAL
@@ -93,9 +119,11 @@ int contexthub_request(struct contexthub_ipc_info *ipc)
 }
 
 /* rlease contexthub to host driver */
-void contexthub_release(struct contexthub_ipc_info *ipc)
+void contexthub_release(struct contexthub_ipc_info *ipc, enum access_type acc)
 {
-       if (!ipc->powermode)
+       contexthub_put_token(ipc, acc);
+
+       if ((acc == HW_ACCESS) || !ipc->powermode)
                return;
 
 #ifdef CONFIG_CHRE_SENSORHUB_HAL
@@ -218,7 +246,7 @@ static int contexthub_ipc_drv_init(struct contexthub_ipc_info *chub)
 #endif
        ret = chub_dbg_init(chub_dev);
        if (ret)
-               dev_err(chub_dev, "%s: fails. ret:%d\n", __func__, ret);
+               dev_err(chub_dev, "%s: failed. ret:%d\n", __func__, ret);
 
        return ret;
 }
@@ -284,19 +312,43 @@ static bool contexthub_lowlevel_alive(struct contexthub_ipc_info *ipc)
        return ipc->chub_alive_lock.flag;
 }
 
-#define CHUB_RESET_THOLD (5)
 /* handle errors of chub driver and fw  */
 static void handle_debug_work(struct contexthub_ipc_info *ipc, enum chub_err_type err)
 {
        int need_reset;
        int alive = contexthub_lowlevel_alive(ipc);
 
+       /* handle fw dbg */
+       if (err == CHUB_ERR_NANOHUB) {
+               enum ipc_debug_event event = ipc_read_debug_event(AP);
+
+               dev_info(ipc->dev, "%s: fw dbg event:%d\n", __func__, event);
+               switch (event) {
+               case IPC_DEBUG_CHUB_PRINT_LOG:
+                       log_flush(ipc->fw_log);
+                       break;
+               default:
+                       dev_warn(ipc->dev, "Contexthub request invalid event:%d\n", event);
+                       break;
+               };
+
+               ipc_write_debug_event(AP, 0);
+               return;
+       }
+
+       /* handle err */
+       ipc->err_cnt[err]++;
+
        dev_info(ipc->dev, "%s: err:%d, alive:%d, status:%d, in-reset:%d\n",
                __func__, err, alive, __raw_readl(&ipc->chub_status),
                __raw_readl(&ipc->in_reset));
+
        if ((atomic_read(&ipc->chub_status) == CHUB_ST_ERR) || !alive)
                need_reset = 1;
 
+       /* dump hw & sram into file */
+       chub_dbg_dump_hw(ipc, err);
+
        /* reset */
        if (need_reset) {
 #if defined(CHUB_RESET_ENABLE)
@@ -305,11 +357,13 @@ static void handle_debug_work(struct contexthub_ipc_info *ipc, enum chub_err_typ
                dev_info(ipc->dev, "%s: request silent reset. err:%d, alive:%d, status:%d, in-reset:%d\n",
                        __func__, err, alive, __raw_readl(&ipc->chub_status),
                        __raw_readl(&ipc->in_reset));
-               ret = contexthub_reset(ipc, 0, err);
+
+               ret = contexthub_reset(ipc, 0);
                if (ret)
-                       dev_warn(ipc->dev, "%s: fails to reset:%d. status:%d\n",
+                       dev_warn(ipc->dev, "%s: failed to reset:%d. status:%d\n",
                                __func__, ret, __raw_readl(&ipc->chub_status));
                else
+                       /* TODO: recovery */
                        dev_info(ipc->dev, "%s: chub reset! should be recovery\n",
                                __func__);
 #else
@@ -322,48 +376,36 @@ static void handle_debug_work(struct contexthub_ipc_info *ipc, enum chub_err_typ
        }
 }
 
+#define CHUB_RESET_THOLD (5)
 static void request_debug_work(struct contexthub_ipc_info *ipc,
        enum chub_err_type err, bool enable_wq)
 {
        dev_info(ipc->dev, "%s: err:%d(cnt:%d), enable_wq:%d\n",
                __func__, err, ipc->err_cnt[err], enable_wq);
 
-       if (err < CHUB_ERR_NEED_RESET) {
-               if (ipc->err_cnt[err] > CHUB_RESET_THOLD) {
-                       atomic_set(&ipc->chub_status, CHUB_ST_ERR);
-                       ipc->err_cnt[err] = 0;
-                       dev_info(ipc->dev, "%s: err:%d(cnt:%d), enter error status\n",
-                               __func__, err, ipc->err_cnt[err]);
-               } else {
-                       ipc->err_cnt[err]++;
-                       return;
-               }
-       }
-
-       /* get chub-fw err */
+       /* get fw err */
        if (err == CHUB_ERR_NANOHUB) {
-               enum ipc_debug_event fw_evt;
-
-               if (contexthub_get_token(ipc)) {
-                       dev_warn(ipc->dev, "%s: get token\n", __func__);
-                       return;
-               }
-               fw_evt = ipc_read_debug_event(AP);
-               if (fw_evt == IPC_DEBUG_CHUB_FAULT)
+               enum ipc_debug_event fw_evt = ipc_read_debug_event(AP);
+               if (fw_evt == IPC_DEBUG_CHUB_FAULT) {
                        err = CHUB_ERR_FW_FAULT;
-               else if ((fw_evt == IPC_DEBUG_CHUB_ASSERT) || (fw_evt == IPC_DEBUG_CHUB_ERROR))
+                       ipc_write_debug_event(AP, 0);
+               }
+               else if ((fw_evt == IPC_DEBUG_CHUB_ASSERT) || (fw_evt == IPC_DEBUG_CHUB_ERROR)) {
                        err = CHUB_ERR_FW_ERROR;
-               else
-                       dev_warn(ipc->dev, "%s: unsupported fw_evt: %d\n", fw_evt);
-
-               ipc_write_debug_event(AP, 0);
-               contexthub_put_token(ipc);
+                       ipc_write_debug_event(AP, 0);
+               }
        }
 
        /* set status in CHUB_ST_ERR */
        if ((err == CHUB_ERR_ITMON) || (err == CHUB_ERR_FW_WDT) || (err == CHUB_ERR_FW_FAULT))
                atomic_set(&ipc->chub_status, CHUB_ST_ERR);
 
+       if (err < CHUB_ERR_NEED_RESET)
+               if (ipc->err_cnt[err] > CHUB_RESET_THOLD) {
+                       atomic_set(&ipc->chub_status, CHUB_ST_ERR);
+                       ipc->err_cnt[err] = 0;
+               }
+
        /* handle err */
        if (enable_wq) {
                ipc->cur_err |= (1 << err);
@@ -373,6 +415,39 @@ static void request_debug_work(struct contexthub_ipc_info *ipc,
        }
 }
 
+static void contexthub_select_os(struct contexthub_ipc_info *ipc)
+{
+       int trycnt = 0;
+       u8 val = (u8) ipc_read_val(AP);
+       if(!val){
+               dev_warn(ipc->dev, "%s os number is invalid\n");
+               val = 1;
+       }
+       ipc->sel_os = true;
+
+       strcpy(ipc->os_name, os_image[val]);
+       dev_info(ipc->dev, "%s selected os_name = %s\n", __func__, ipc->os_name);
+
+       log_flush_all();
+
+       contexthub_download_image(ipc, IPC_REG_OS);
+       ipc_hw_write_shared_reg(AP, ipc->os_load, SR_BOOT_MODE);
+       ipc_write_val(AP, 99);
+       do {
+               msleep(WAIT_CHUB_MS);
+               contexthub_ipc_write_event(ipc, MAILBOX_EVT_CHUB_ALIVE);
+               if (++trycnt > WAIT_TRY_CNT)
+                       break;
+       } while ((atomic_read(&ipc->chub_status) != CHUB_ST_RUN));
+
+       if (atomic_read(&ipc->chub_status) == CHUB_ST_RUN)
+               dev_info(ipc->dev, "%s done. contexthub status is %d\n",
+                               __func__, atomic_read(&ipc->chub_status));
+       else
+               dev_warn(ipc->dev, "%s failed. contexthub status is %d\n",
+                               __func__, atomic_read(&ipc->chub_status));
+}
+
 static DEFINE_MUTEX(dbg_mutex);
 static void handle_debug_work_func(struct work_struct *work)
 {
@@ -380,6 +455,12 @@ static void handle_debug_work_func(struct work_struct *work)
            container_of(work, struct contexthub_ipc_info, debug_work);
        int i;
 
+       if (atomic_read(&ipc->chub_status) == CHUB_ST_POWER_ON && ipc->sel_os == false) {
+               contexthub_select_os(ipc);
+               return;
+       }
+
+       mutex_lock(&dbg_mutex);
        dev_info(ipc->dev, "%s: cur_err:0x%x\n", __func__, ipc->cur_err);
        for (i = 0; i < CHUB_ERR_MAX; i++) {
                if (ipc->cur_err & (1 << i)) {
@@ -388,12 +469,7 @@ static void handle_debug_work_func(struct work_struct *work)
                        ipc->cur_err &= ~(1 << i);
                }
        }
-}
-
-static inline void clear_err_cnt(struct contexthub_ipc_info *ipc, enum chub_err_type err)
-{
-       if (ipc->err_cnt[err])
-               ipc->err_cnt[err] = 0;
+       mutex_unlock(&dbg_mutex);
 }
 
 int contexthub_ipc_read(struct contexthub_ipc_info *ipc, uint8_t *rx, int max_length,
@@ -404,6 +480,11 @@ int contexthub_ipc_read(struct contexthub_ipc_info *ipc, uint8_t *rx, int max_le
        int ret;
        void *rxbuf;
 
+       if (!contexthub_get_token(ipc, IPC_ACCESS)) {
+               dev_warn(ipc->dev, "no-active: read failed\n");
+               return 0;
+       }
+
        if (!ipc->read_lock.flag) {
                spin_lock_irqsave(&ipc->read_lock.event.lock, flag);
                read_get_locked(ipc);
@@ -415,7 +496,7 @@ int contexthub_ipc_read(struct contexthub_ipc_info *ipc, uint8_t *rx, int max_le
                spin_unlock_irqrestore(&ipc->read_lock.event.lock, flag);
                if (ret < 0)
                        dev_warn(ipc->dev,
-                                "fails to get read ret:%d timeout:%d, flag:0x%x",
+                                "failed to get read ret:%d timeout:%d, flag:0x%x",
                                 ret, timeout, ipc->read_lock.flag);
 
                if (!ipc->read_lock.flag)
@@ -424,11 +505,6 @@ int contexthub_ipc_read(struct contexthub_ipc_info *ipc, uint8_t *rx, int max_le
 
        ipc->read_lock.flag--;
 
-       if (contexthub_get_token(ipc)) {
-               dev_warn(ipc->dev, "no-active: read fails\n");
-               return 0;
-       }
-
 #ifdef USE_IPC_BUF
        rxbuf = ipc->rxbuf;
        size = ipc_read_data(IPC_DATA_C2A, rxbuf);
@@ -437,13 +513,12 @@ int contexthub_ipc_read(struct contexthub_ipc_info *ipc, uint8_t *rx, int max_le
 #endif
 
        if (size > 0) {
-               clear_err_cnt(ipc, CHUB_ERR_READ_FAIL);
-               ret = contexthub_read_process(rx, rxbuf, size);
+               contexthub_put_token(ipc, IPC_ACCESS);
+               return contexthub_read_process(rx, rxbuf, size);
        }
-       contexthub_put_token(ipc);
-       return ret;
 
 fail_get_channel:
+       contexthub_put_token(ipc, IPC_ACCESS);
        request_debug_work(ipc, CHUB_ERR_READ_FAIL, 0);
        return -EINVAL;
 }
@@ -453,21 +528,19 @@ int contexthub_ipc_write(struct contexthub_ipc_info *ipc,
 {
        int ret;
 
-       if (contexthub_get_token(ipc)) {
-               dev_warn(ipc->dev, "no-active: write fails\n");
+       if (!contexthub_get_token(ipc, IPC_ACCESS)) {
+               dev_warn(ipc->dev, "no-active: write failed\n");
                return 0;
        }
 
        ret = ipc_write_data(IPC_DATA_A2C, tx, (u16)length);
-       contexthub_put_token(ipc);
        if (ret) {
-               pr_err("%s: fails to write data: ret:%d, len:%d errcnt:%d\n",
+               pr_err("%s: failed to write data: ret:%d, len:%d errcnt:%d\n",
                        __func__, ret, length, ipc->err_cnt[CHUB_ERR_WRITE_FAIL]);
                request_debug_work(ipc, CHUB_ERR_WRITE_FAIL, 0);
                length = 0;
-       } else {
-               clear_err_cnt(ipc, CHUB_ERR_WRITE_FAIL);
        }
+       contexthub_put_token(ipc, IPC_ACCESS);
        return length;
 }
 
@@ -578,7 +651,7 @@ static int contexthub_hw_reset(struct contexthub_ipc_info *ipc,
                } else {
                        ret = -EINVAL;
                        dev_warn(ipc->dev,
-                                "fails to contexthub power on. Status is %d\n",
+                                "failed to contexthub power on. Status is %d\n",
                                 atomic_read(&ipc->chub_status));
                }
                break;
@@ -589,6 +662,11 @@ static int contexthub_hw_reset(struct contexthub_ipc_info *ipc,
                break;
        }
 
+       if (ipc->sel_os == false) {
+               dev_info(ipc->dev, "%s os select\n", __func__);
+               return 0;
+       }
+
        if (ret)
                return ret;
        else {
@@ -606,7 +684,7 @@ static int contexthub_hw_reset(struct contexthub_ipc_info *ipc,
                                 __func__, atomic_read(&ipc->chub_status));
                        return 0;
                } else {
-                       dev_warn(ipc->dev, "%s fails. contexthub status is %d\n",
+                       dev_warn(ipc->dev, "%s failed. contexthub status is %d\n",
                                 __func__, atomic_read(&ipc->chub_status));
                        return -ETIMEDOUT;
                }
@@ -652,7 +730,7 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
                        ret = contexthub_hw_reset(ipc, event);
                } else {
                        dev_err(ipc->dev,
-                               "contexthub status isn't shutdown. fails to reset\n");
+                               "contexthub status isn't shutdown. failed to reset\n");
                        ret = -EINVAL;
                }
                break;
@@ -696,7 +774,7 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
                                                 REG_CHUB_RESET_CHUB_CONFIGURATION);
                        } else {
                                dev_err(ipc->dev,
-                                       "fails to shutdown contexthub. cpu_status: 0x%x\n",
+                                       "failed to shutdown contexthub. cpu_status: 0x%x\n",
                                        val);
                                return -EINVAL;
                        }
@@ -707,12 +785,11 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
                val = contexthub_lowlevel_alive(ipc);
                if (val) {
                        atomic_set(&ipc->chub_status, CHUB_ST_RUN);
-                       dev_info(ipc->dev, "chub is alive");
-                       clear_err_cnt(ipc, CHUB_ERR_CHUB_NO_RESPONSE);
-               } else {
+                       dev_info(ipc->dev, "%s : chub is alive", __func__);
+               } else if (ipc->sel_os == true) {
                        dev_err(ipc->dev,
-                               "chub isn't alive, should be reset. status:%d\n",
-                               atomic_read(&ipc->chub_status));
+                               "%s : chub isn't alive, should be reset. status:%d\n",
+                               __func__, atomic_read(&ipc->chub_status));
                        atomic_set(&ipc->chub_status, CHUB_ST_NO_RESPONSE);
                        request_debug_work(ipc, CHUB_ERR_CHUB_NO_RESPONSE, 0);
                        ret = -EINVAL;
@@ -727,6 +804,9 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
                ipc_hw_mask_irq(AP, IRQ_EVT_C2A_INT);
                ipc_hw_mask_irq(AP, IRQ_EVT_C2A_INTCLR);
                break;
+       case MAILBOX_EVT_ERASE_SHARED:
+               memset(ipc_get_base(IPC_REG_SHARED), 0, ipc_get_offset(IPC_REG_SHARED));
+               break;
        default:
                need_ipc = 1;
                break;
@@ -735,17 +815,14 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
        if (!need_ipc)
                return ret;
 
-       if (contexthub_get_token(ipc)) {
-               dev_warn(ipc->dev, "%s event:%d/%d fails chub isn't active, status:%d, inreset:%d\n",
-                       __func__, event, MAILBOX_EVT_MAX, atomic_read(&ipc->chub_status), atomic_read(&ipc->in_reset));
+       if (!contexthub_get_token(ipc, IPC_ACCESS)) {
+               dev_warn(ipc->dev, "%s event:%d/%d failed chub isn't active\n",
+                       __func__, event, MAILBOX_EVT_MAX);
                return -EINVAL;
        }
 
        /* handle ipc */
        switch (event) {
-       case MAILBOX_EVT_ERASE_SHARED:
-               memset(ipc_get_base(IPC_REG_SHARED), 0, ipc_get_offset(IPC_REG_SHARED));
-               break;
        case MAILBOX_EVT_DUMP_STATUS:
                /* dump nanohub kernel status */
                dev_info(ipc->dev, "Request to dump chub fw status\n");
@@ -772,11 +849,12 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
                                check_rtc_time();
                        ipc_write_debug_event(AP, (u32)event);
                        ipc_add_evt(IPC_EVT_A2C, IRQ_EVT_A2C_DEBUG);
-                       ret = 0;
+                       return 0;
                }
                break;
        }
-       contexthub_put_token(ipc);
+
+       contexthub_put_token(ipc, IPC_ACCESS);
        return ret;
 }
 
@@ -784,35 +862,39 @@ int contexthub_poweron(struct contexthub_ipc_info *ipc)
 {
        int ret = 0;
        struct device *dev = ipc->dev;
+       struct chub_bootargs *map;
 
        if (!atomic_read(&ipc->chub_status)) {
                ret = contexthub_download_image(ipc, IPC_REG_BL);
                if (ret) {
-                       dev_warn(dev, "fails to download bootloader\n");
+                       dev_warn(dev, "failed to download bootloader\n");
                        return ret;
                }
 
                ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_INIT_IPC);
                if (ret) {
-                       dev_warn(dev, "fails to init ipc\n");
+                       dev_warn(dev, "failed to init ipc\n");
                        return ret;
                }
 
+               map = ipc_get_base(IPC_REG_BL_MAP);
+               ipc->sel_os = !(map->bootmode);
+
                ret = contexthub_download_image(ipc, IPC_REG_OS);
                if (ret) {
-                       dev_warn(dev, "fails to download kernel\n");
+                       dev_warn(dev, "failed to download kernel\n");
                        return ret;
                }
                ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_POWER_ON);
                if (ret) {
-                       dev_warn(dev, "fails to poweron\n");
+                       dev_warn(dev, "failed to poweron\n");
                        return ret;
                }
 
                if (atomic_read(&ipc->chub_status) == CHUB_ST_RUN)
                        dev_info(dev, "contexthub power-on");
-               else
-                       dev_warn(dev, "contexthub fails to power-on");
+               else if (ipc->sel_os == true)
+                       dev_warn(dev, "contexthub failed to power-on");
        } else {
                ret = -EINVAL;
        }
@@ -831,7 +913,7 @@ static int contexthub_download_and_check_image(struct contexthub_ipc_info *ipc,
        memcpy_fromio(fw, ipc_get_base(reg), ipc_get_offset(reg));
        ret = contexthub_download_image(ipc, reg);
        if (ret) {
-               dev_err(ipc->dev, "%s: download bl(%d) fails\n", __func__, reg == IPC_REG_BL);
+               dev_err(ipc->dev, "%s: download bl(%d) failed\n", __func__, reg == IPC_REG_BL);
                goto out;
        }
 
@@ -840,7 +922,7 @@ static int contexthub_download_and_check_image(struct contexthub_ipc_info *ipc,
                int i;
                u32 *fw_image = (u32 *)ipc_get_base(reg);
 
-               dev_err(ipc->dev, "%s: fw(%lx) doens't match with size %d\n",
+               dev_err(ipc->dev, "%s: fw(%lx) doesn't match with size %d\n",
                        __func__, (unsigned long)ipc_get_base(reg), ipc_get_offset(reg));
                for (i = 0; i < ipc_get_offset(reg) / 4; i++)
                        if (fw[i] != fw_image[i]) {
@@ -857,13 +939,12 @@ out:
        return ret;
 }
 
-int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump)
+int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load)
 {
        int ret;
-       int trycnt;
 
-       dev_info(ipc->dev, "%s: force:%d, status:%d, in-reset:%d, user:%d\n",
-               __func__, force_load, atomic_read(&ipc->chub_status), atomic_read(&ipc->in_reset), atomic_read(&ipc->in_use_ipc));
+       dev_info(ipc->dev, "%s: force:%d, status:%d, in-reset:%d\n",
+               __func__, force_load, atomic_read(&ipc->chub_status), atomic_read(&ipc->in_reset));
        mutex_lock(&reset_mutex);
        if (!force_load && (atomic_read(&ipc->chub_status) == CHUB_ST_RUN)) {
                mutex_unlock(&reset_mutex);
@@ -871,19 +952,9 @@ int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump)
                return 0;
        }
        atomic_inc(&ipc->in_reset);
-
-       do {
-               msleep(WAIT_CHUB_MS);
-               if (++trycnt > RESET_WAIT_TRY_CNT) {
-                       dev_info(ipc->dev, "%s: cann't get lock. force reset: %d\n", __func__, atomic_read(&ipc->in_use_ipc));
-                       break;
-               }
-               dev_info(ipc->dev, "%s: wait for ipc user free: %d\n", __func__, atomic_read(&ipc->in_use_ipc));
-       } while (atomic_read(&ipc->in_use_ipc));
-
-       if (dump)
-               chub_dbg_dump_hw(ipc, dump);
-
+#ifndef CONFIG_CHRE_SENSORHUB_HAL /* retry exam */
+retry:
+#endif
        dev_info(ipc->dev, "%s: start reset status:%d\n", __func__, atomic_read(&ipc->chub_status));
        if (!ipc->block_reset) {
                /* core reset */
@@ -895,7 +966,7 @@ int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump)
        dev_info(ipc->dev, "%s: enter shutdown\n", __func__);
        ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_SHUTDOWN);
        if (ret) {
-               dev_err(ipc->dev, "%s: shutdonw fails, ret:%d\n", __func__, ret);
+               dev_err(ipc->dev, "%s: shutdown failed, ret:%d\n", __func__, ret);
                goto out;
        }
        dev_info(ipc->dev, "%s: out shutdown\n", __func__);
@@ -910,26 +981,51 @@ int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump)
                                ret = contexthub_download_and_check_image(ipc, IPC_REG_OS);
 
                        if (ret) {
-                               dev_err(ipc->dev, "%s: download os fails\n", __func__);
+                               dev_err(ipc->dev, "%s: os download failed\n", __func__);
                                goto out;
                        }
                } else {
-                               dev_err(ipc->dev, "%s: download bl fails\n", __func__);
+                               dev_err(ipc->dev, "%s: bl download failed\n", __func__);
                                goto out;
                }
        }
 
        ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_RESET);
        if (ret)
-               dev_err(ipc->dev, "%s: reset fails, ret:%d\n", __func__, ret);
+               dev_err(ipc->dev, "%s: reset failed, ret:%d\n", __func__, ret);
        else {
-               dev_info(ipc->dev, "%s: chub reseted! (cnt:%d)\n",
+               dev_info(ipc->dev, "%s: chub was reset! (cnt:%d)\n",
                        __func__, ipc->err_cnt[CHUB_ERR_RESET_CNT]);
                ipc->err_cnt[CHUB_ERR_RESET_CNT]++;
-               atomic_set(&ipc->in_use_ipc, 0);
                atomic_dec(&ipc->in_reset);
+#ifndef CONFIG_CHRE_SENSORHUB_HAL
+               ret = request_wakeup(ipc->data);
+               if (ret)
+                       dev_err(ipc->dev, "%s: failed to wakeup after reset, ret:%d\n", __func__, ret);
+               else
+                       release_wakeup(ipc->data);
+               if (ipc->irq_wdt && ipc->irq_wdt_disabled) {
+                       enable_irq(ipc->irq_wdt);
+                       ipc->irq_wdt_disabled = 0;
+               }
+#endif
        }
+
 out:
+       if (!ret) {
+               dev_info(ipc->dev, "%s: chub reseted and work (cnt:%d)\n",
+                       __func__, ipc->err_cnt[CHUB_ERR_RESET_CNT]);
+               ipc->err_cnt[CHUB_ERR_RESET_CNT] = 0;
+       } else {
+#ifndef CONFIG_CHRE_SENSORHUB_HAL
+               atomic_inc(&ipc->in_reset);
+               if (ipc->err_cnt[CHUB_ERR_RESET_CNT] > CHUB_RESET_THOLD)
+                       msleep(WAIT_TIMEOUT_MS * CHUB_RESET_THOLD);
+               else
+                       msleep(WAIT_TIMEOUT_MS);
+               goto retry;
+#endif
+       }
        mutex_unlock(&reset_mutex);
 
        return ret;
@@ -953,6 +1049,7 @@ int contexthub_download_image(struct contexthub_ipc_info *ipc, enum ipc_region r
                return ret;
        }
        memcpy(ipc_get_base(reg), entry->data, entry->size);
+       dev_info(ipc->dev, "image name : %s\n", ipc->os_name);
        dev_info(ipc->dev, "%s: bl:%d, bin(size:%d) on %lx\n",
                 __func__, reg == IPC_REG_BL, (int)entry->size, (unsigned long)ipc_get_base(reg));
        release_firmware(entry);
@@ -1008,6 +1105,11 @@ static irqreturn_t contexthub_irq_handler(int irq, void *data)
        if (status & (1 << irq_num)) {
                status &= ~(1 << irq_num);
                ipc_hw_clear_int_pend_reg(AP, irq_num);
+               if (atomic_read(&ipc->chub_status) == CHUB_ST_POWER_ON && ipc->sel_os == false) {
+                       schedule_work(&ipc->debug_work);
+                       return IRQ_HANDLED;
+               }
+
                /* set wakeup flag for chub_alive_lock */
                ipc->chub_alive_lock.flag = 1;
                wake_up(&ipc->chub_alive_lock.event);
@@ -1041,11 +1143,10 @@ static irqreturn_t contexthub_irq_handler(int irq, void *data)
                       err, start_index, cur_evt, evt, irq_num,
                       status, ipc_hw_read_int_status_reg(AP),
                       ipc_hw_read_int_gen_reg(AP));
+               ipc->err_cnt[err]++;
                ipc_hw_clear_all_int_pend_reg(AP);
-               request_debug_work(ipc, err, 1);
-       } else {
-               clear_err_cnt(ipc, CHUB_ERR_EVTQ_EMTPY);
-               clear_err_cnt(ipc, CHUB_ERR_EVTQ_NO_HW_TRIGGER);
+               if (ipc->err_cnt[err] > CHUB_RESET_THOLD)
+                       request_debug_work(ipc, err, 1);
        }
        return IRQ_HANDLED;
 }
@@ -1055,7 +1156,7 @@ static irqreturn_t contexthub_irq_wdt_handler(int irq, void *data)
 {
        struct contexthub_ipc_info *ipc = data;
 
-       dev_info(ipc->dev, "%s calledn", __func__);
+       dev_info(ipc->dev, "%s called\n", __func__);
        disable_irq_nosync(ipc->irq_wdt);
        ipc->irq_wdt_disabled = 1;
        request_debug_work(ipc, CHUB_ERR_FW_WDT, 1);
@@ -1173,7 +1274,7 @@ static __init int contexthub_ipc_hw_init(struct platform_device *pdev,
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mailbox");
        chub->mailbox = devm_ioremap_resource(dev, res);
        if (IS_ERR(chub->mailbox)) {
-               dev_err(dev, "fails to get mailbox sfr\n");
+               dev_err(dev, "failed to get mailbox sfr\n");
                return PTR_ERR(chub->mailbox);
        }
 
@@ -1181,7 +1282,7 @@ static __init int contexthub_ipc_hw_init(struct platform_device *pdev,
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram");
        chub->sram = devm_ioremap_resource(dev, res);
        if (IS_ERR(chub->sram)) {
-               dev_err(dev, "fails to get sram\n");
+               dev_err(dev, "failed to get sram\n");
                return PTR_ERR(chub->sram);
        }
 
@@ -1189,7 +1290,7 @@ static __init int contexthub_ipc_hw_init(struct platform_device *pdev,
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dumpgpr");
        chub->chub_dumpgrp = devm_ioremap_resource(dev, res);
        if (IS_ERR(chub->chub_dumpgrp)) {
-               dev_err(dev, "fails to get dumpgrp\n");
+               dev_err(dev, "failed to get dumpgrp\n");
                return PTR_ERR(chub->chub_dumpgrp);
        }
 
@@ -1197,7 +1298,7 @@ static __init int contexthub_ipc_hw_init(struct platform_device *pdev,
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "chub_reset");
        chub->pmu_chub_reset = devm_ioremap_resource(dev, res);
        if (IS_ERR(chub->pmu_chub_reset)) {
-               dev_err(dev, "fails to get dumpgrp\n");
+               dev_err(dev, "failed to get dumpgrp\n");
                return PTR_ERR(chub->pmu_chub_reset);
        }
 
@@ -1276,7 +1377,7 @@ static __init int contexthub_ipc_hw_init(struct platform_device *pdev,
 
        chub_clk_len = of_property_count_strings(node, "clock-names");
        of_property_read_string_array(node, "clock-names", string_array, chub_clk_len);
-       for (i = 0; i < chub_clk_len; i++) {
+       for (i = 0 ; i < chub_clk_len; i++){
                clk = devm_clk_get_and_prepare(dev, string_array[i]);
                if (!clk)
                        return -ENODEV;
@@ -1301,7 +1402,7 @@ static ssize_t chub_reset(struct device *dev,
                                const char *buf, size_t count)
 {
        struct contexthub_ipc_info *ipc = dev_get_drvdata(dev);
-       int ret = contexthub_reset(ipc, 1, 0);
+       int ret = contexthub_reset(ipc, 1);
 
        return ret < 0 ? ret : count;
 }
@@ -1376,7 +1477,7 @@ static int contexthub_ipc_probe(struct platform_device *pdev)
        chub->data->irq1 = IRQ_EVT_A2C_WAKEUP;
        chub->data->irq2 = 0;
 #endif
-       atomic_set(&chub->in_use_ipc, 0);
+
        atomic_set(&chub->chub_status, CHUB_ST_NO_POWER);
        atomic_set(&chub->in_reset, 0);
        chub->powermode = 0; /* updated by fw bl */
@@ -1419,24 +1520,6 @@ static int contexthub_ipc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int contexthub_suspend(struct device *dev)
-{
-       struct contexthub_ipc_info *ipc = dev_get_drvdata(dev);
-       struct nanohub_data *data = ipc->data;
-
-       return nanohub_suspend(data->iio_dev);
-}
-
-static int contexthub_resume(struct device *dev)
-{
-       struct contexthub_ipc_info *ipc = dev_get_drvdata(dev);
-       struct nanohub_data *data = ipc->data;
-
-       return nanohub_resume(data->iio_dev);
-}
-
-static SIMPLE_DEV_PM_OPS(contexthub_pm_ops, contexthub_suspend, contexthub_resume);
-
 static const struct of_device_id contexthub_ipc_match[] = {
        {.compatible = "samsung,exynos-nanohub"},
        {},
@@ -1449,8 +1532,7 @@ static struct platform_driver samsung_contexthub_ipc_driver = {
                   .name = "nanohub-ipc",
                   .owner = THIS_MODULE,
                   .of_match_table = contexthub_ipc_match,
-                  .pm = &contexthub_pm_ops,
-       },
+                  },
 };
 
 int nanohub_mailbox_init(void)
index c2c974b5fe170136d0aa244d7534afe21bd25e06..75aee40d02b457dd0afc45b59c3a0e54af22f1f3 100644 (file)
@@ -29,7 +29,6 @@
 #include "chub_log.h"
 
 #define WAIT_TRY_CNT (3)
-#define RESET_WAIT_TRY_CNT (10)
 #define WAIT_CHUB_MS (100)
 
 /* utils for nanohub main */
@@ -178,7 +177,6 @@ struct contexthub_ipc_info {
        atomic_t in_reset;
        atomic_t irq1_apInt;
        atomic_t wakeup_chub;
-       atomic_t in_use_ipc;
        int irq_mailbox;
        int irq_wdt;
        bool irq_wdt_disabled;
@@ -187,6 +185,7 @@ struct contexthub_ipc_info {
        int utc_run;
        int powermode;
        int block_reset;
+       bool sel_os;
        bool os_load;
        char os_name[MAX_FILE_LEN];
        struct notifier_block itmon_nb;
@@ -286,6 +285,8 @@ struct contexthub_ipc_info {
 #define IPC_HW_WRITE_BAAW_CHUB3(base, val) \
        __raw_writel((val), (base) + REG_BAAW_D_CHUB3)
 
+enum access_type { HW_ACCESS, IPC_ACCESS };
+
 int contexthub_ipc_write_event(struct contexthub_ipc_info *data,
                                enum mailbox_event event);
 int contexthub_ipc_read(struct contexthub_ipc_info *ipc,
@@ -294,8 +295,10 @@ int contexthub_ipc_write(struct contexthub_ipc_info *ipc,
                                uint8_t *tx, int length, int timeout);
 int contexthub_poweron(struct contexthub_ipc_info *data);
 int contexthub_download_image(struct contexthub_ipc_info *data, enum ipc_region reg);
-int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump_id);
+int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load);
 int contexthub_wakeup(struct contexthub_ipc_info *data, int evt);
-int contexthub_request(struct contexthub_ipc_info *ipc);
-void contexthub_release(struct contexthub_ipc_info *ipc);
+
+int contexthub_is_run(struct contexthub_ipc_info *ipc);
+int contexthub_request(struct contexthub_ipc_info *ipc, enum access_type acc);
+void contexthub_release(struct contexthub_ipc_info *ipc, enum access_type acc);
 #endif
index cf3f4b47c5b25efb09a14e33187fd7f91d6cb696..880446d592df1d0ddb7a0dc8e4aa3ed565629c07 100644 (file)
@@ -450,9 +450,9 @@ static ssize_t chub_wakeup_store(struct device *dev,
                return ret;
 
        if (event)
-               ret = contexthub_request(ipc);
+               ret = contexthub_request(ipc, IPC_ACCESS);
        else
-               contexthub_release(ipc);
+               contexthub_release(ipc, IPC_ACCESS);
 
        return ret ? ret : count;
 }
index 31ee562ec26172106eeea6386abd366dc187ede3..1d3973301f4e6f703c1ff4498098bc1a3b45ee74 100644 (file)
@@ -81,6 +81,8 @@
 #define BOOTMODE_COLD       (0x77773333)
 #define BOOTMODE_PWRGATING  (0x11118888)
 
+#define READY_TO_GO 99
+
 struct chub_bootargs {
        char magic[16];
        u32 ipc_version;
index 3fbbd864b85ab08dc08c943d76bde63daacfc0c7..8acc05bc6a2c1bb081c5d1dba0e84be33710dd83 100644 (file)
@@ -153,7 +153,7 @@ void log_flush(struct log_buffer_info *info)
 static void log_flush_all_work_func(struct work_struct *work);
 static DECLARE_DEFERRABLE_WORK(log_flush_all_work, log_flush_all_work_func);
 
-static void log_flush_all(void)
+void log_flush_all(void)
 {
        struct log_buffer_info *info;
 
index cd8090a866f1d356cc8ab052d4faac0254ab9688..32e6f206db06d9b854bc0012bee400f6c1087a10 100644 (file)
@@ -49,6 +49,7 @@ struct LOG_BUFFER {
 
 void log_flush(struct log_buffer_info *info);
 void log_schedule_flush_all(void);
+void log_flush_all(void);
 struct log_buffer_info *log_register_buffer(struct device *dev, int id,
                                            struct LOG_BUFFER *buffer,
                                            char *name, bool sram);
index bbc95877e7f8892cc240aa0c85ee65a373b67cce..d86b8825bf3d75c7e05eaf6018be7d10a49f2c28 100644 (file)
@@ -743,7 +743,7 @@ static int nanohub_hw_reset(struct nanohub_data *data)
        }
 #elif defined(CONFIG_NANOHUB_MAILBOX)
 #ifdef CHUB_RESET_ENABLE
-       ret = contexthub_reset(data->pdata->mailbox_client, 0, CHUB_ERR_COMMS);
+       ret = contexthub_reset(data->pdata->mailbox_client, 0);
 #else
        ret = -EINVAL;
 #endif
@@ -858,7 +858,7 @@ static ssize_t nanohub_download_bl(struct device *dev,
 
        return ret < 0 ? ret : count;
 #elif defined(CONFIG_NANOHUB_MAILBOX)
-       ret = contexthub_reset(data->pdata->mailbox_client, 1, 0);
+       ret = contexthub_reset(data->pdata->mailbox_client, 1);
 
        return ret < 0 ? ret : count;
 #endif