int arisc_hwmsgbox_feedback_message(struct arisc_message *pmessage, unsigned int timeout) { volatile unsigned long value; if (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN) { //use ac327 hard syn receiver channel. while (readl(IO_ADDRESS(AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_ARISC_SYN_RX_CH))) == 1) { //message-queue fifo is full, waiting. ; } value = ((volatile unsigned long)pmessage) - arisc_sram_a2_vbase; ARISC_INF("arisc feedback hard syn message : %x\n", (unsigned int)value); writel(value, IO_ADDRESS(AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_SYN_RX_CH))); return 0; } //soft syn use asyn tx channel if (pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) { while (readl(IO_ADDRESS(AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_ARISC_ASYN_RX_CH))) == 1) { //fifo is full, wait ; } //write message to message-queue fifo. value = ((volatile unsigned long)pmessage) - arisc_sram_a2_vbase; ARISC_INF("arisc send asyn or soft syn message : %x\n", (unsigned int)value); writel(value, IO_ADDRESS(AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_ASYN_RX_CH))); return 0; } //invalid syn message return -EINVAL; }
static int arisc_wait_ready(unsigned int timeout) { /* wait arisc startup ready */ while (1) { /* * linux cpu interrupt is disable now, * we should query message by hand. */ struct arisc_message *pmessage = arisc_hwmsgbox_query_message(); if (pmessage == NULL) { /* try to query again */ continue; } /* query valid message */ if (pmessage->type == ARISC_STARTUP_NOTIFY) { /* check arisc software and driver version match or not */ if (pmessage->paras[0] != ARISC_VERSIONS) { ARISC_ERR("arisc firmware:%d and driver version:%u not matched\n", pmessage->paras[0], ARISC_VERSIONS); return -EINVAL; } else { /* printf the main and sub version string */ memcpy((void *)arisc_version, (const void*)(&(pmessage->paras[1])), 40); ARISC_LOG("arisc version: [%s]\n", arisc_version); } /* received arisc startup ready message */ ARISC_INF("arisc startup ready\n"); if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ ARISC_INF("arisc startup notify message feedback\n"); pmessage->paras[0] = (uint32_t)dts_cfg.image.base; arisc_hwmsgbox_feedback_message(pmessage, ARISC_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ ARISC_INF("arisc startup notify message free directly\n"); arisc_message_free(pmessage); } break; } /* * invalid message detected, ignore it. * by superm at 2012-7-6 18:34:38. */ ARISC_WRN("arisc startup waiting ignore message\n"); if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ arisc_message_free(pmessage); } /* we need waiting continue */ } return 0; }
/** * allocate one message frame. mainly use for send message by message-box, * the message frame allocate form messages pool shared memory area. * @para: none. * * returns: the pointer of allocated message frame, NULL if failed; */ struct arisc_message *arisc_message_allocate(unsigned int msg_attr) { struct arisc_message *pmessage = NULL; struct arisc_message *palloc = NULL; if (arisc_suspend_flag_query() && (msg_attr == ARISC_MESSAGE_ATTR_SOFTSYN)) { msg_attr = ARISC_MESSAGE_ATTR_HARDSYN; } /* first find in message_cache */ spin_lock_irqsave(&(msg_mgr_lock), msg_mgr_flag); if (atomic_read(&(message_cache.number))) { ARISC_INF("arisc message_cache.number = 0x%x.\n", atomic_read(&(message_cache.number))); atomic_dec(&(message_cache.number)); palloc = message_cache.cache[atomic_read(&(message_cache.number))]; ARISC_INF("message [%x] allocate from message_cache\n", (u32)palloc); if (arisc_message_invalid(palloc)) { ARISC_ERR("allocate cache message [%x] invalid\n", (u32)palloc); } } spin_unlock_irqrestore(&(msg_mgr_lock), msg_mgr_flag); if (arisc_message_invalid(palloc)) { /* * cached message_cache finded fail, * use spinlock 0 to exclusive with arisc. */ arisc_hwspin_lock_timeout(AW_MSG_HWSPINLOCK, ARISC_SPINLOCK_TIMEOUT); /* search from the start of message pool every time. */ pmessage = message_start; while (pmessage < message_end) { if (pmessage->state == ARISC_MESSAGE_FREED) { /* find free message in message pool, allocate it */ palloc = pmessage; palloc->state = ARISC_MESSAGE_ALLOCATED; ARISC_INF("message [%x] allocate from message pool\n", (u32)palloc); break; } /* next message frame */ pmessage++; } /* unlock hwspinlock 0 */ arisc_hwspin_unlock(AW_MSG_HWSPINLOCK); } if (arisc_message_invalid(palloc)) { ARISC_ERR("allocate message [%x] frame is invalid\n", (u32)palloc); return NULL; } /* initialize messgae frame */ palloc->next = NULL; palloc->attr = msg_attr; if (msg_attr & ARISC_MESSAGE_ATTR_SOFTSYN) { /* syn message,allocate one semaphore for private */ palloc->private = arisc_semaphore_allocate(); } else {
uint32_t sunxi_load_arisc(uintptr_t image_addr, size_t image_size, void *para, size_t para_size) { void *dst; void *src; size_t size; #if 0 /* * phys addr to virt addr * io space: ioremap * kernel space: phys_to_virt */ /* sram code space */ dst = (void *)dts_cfg.space.sram_dst; src = (void *)((ptrdiff_t)image_addr + (ptrdiff_t)dts_cfg.space.sram_offset); size = dts_cfg.space.sram_size; memset(dst, 0, size); memcpy(dst, src, size); flush_dcache_range((uint64_t)dst, (uint64_t)size); /* dram code space */ dst = (void *)dts_cfg.space.dram_dst; src = (void *)((ptrdiff_t)image_addr + (ptrdiff_t)dts_cfg.space.dram_offset); size = dts_cfg.space.dram_size; memset(dst, 0, size); memcpy(dst, src, size); flush_dcache_range((uint64_t)dst, (uint64_t)size); ARISC_INF("load arisc image finish\n"); #endif /* para space */ dst = (void *)dts_cfg.space.para_dst; src = para; size = dts_cfg.space.para_size; memset(dst, 0, size); memcpy(dst, src, size); ARISC_INF("setup arisc para finish\n"); //dcsw_op_all(DCCISW); flush_dcache_range((uint64_t)dst, (uint64_t)size); isb(); #if 0 /* relese arisc reset */ sunxi_deassert_arisc(); ARISC_INF("release arisc reset finish\n"); ARISC_INF("load arisc finish\n"); #endif return 0; }
/* ********************************************************************************************************* * SEND MESSAGE BY HWMSGBOX * * Description: send one message to another processor by hwmsgbox. * * Arguments : pmessage : the pointer of sended message frame. * timeout : the wait time limit when message fifo is full, * it is valid only when parameter mode = HWMSG_SEND_WAIT_TIMEOUT. * * Returns : 0 if send message succeeded, other if failed. ********************************************************************************************************* */ int arisc_hwmsgbox_send_message(struct arisc_message *pmessage, unsigned int timeout) { volatile unsigned long value; if (pmessage == (struct arisc_message *)(NULL)) { return -EINVAL; } if (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN) { //use ac327 hwsyn transmit channel. while (readl(IO_ADDRESS(AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_AC327_SYN_TX_CH))) == 1) { //message-queue fifo is full, waiting always ; } value = ((volatile unsigned long)pmessage) - arisc_sram_a2_vbase; ARISC_INF("ac327 send hard syn message : %x\n", (unsigned int)value); writel(value, IO_ADDRESS(AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_AC327_SYN_TX_CH))); //hwsyn messsage must feedback use syn rx channel while (readl(IO_ADDRESS(AW_MSGBOX_MSG_STATUS_REG(ARISC_HWMSGBOX_AC327_SYN_RX_CH))) == 0) { //message not valid ; } //check message valid if (value != (readl(IO_ADDRESS(AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_AC327_SYN_RX_CH))))) { ARISC_ERR("hard syn message error\n"); return -EINVAL; } ARISC_INF("ac327 hard syn message [%x, %x] feedback\n", (unsigned int)value, (unsigned int)pmessage->type); return 0; } //use ac327 asyn transmit channel. while (readl(IO_ADDRESS(AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_ARISC_ASYN_RX_CH))) == 1) { //message-queue fifo is full, waiting always ; } //write message to message-queue fifo. value = ((volatile unsigned long)pmessage) - arisc_sram_a2_vbase; ARISC_LOG("ac327 send soft syn or asyn message : %x\n", (unsigned int)value); writel(value, IO_ADDRESS(AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_ASYN_RX_CH))); //syn messsage must wait message feedback if (pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) { ARISC_ERR("standby arisc driver not support soft syn message transfer\n"); return -EINVAL; } return 0; }
static int sunxi_arisc_para_init(struct arisc_para *para) { /* init para */ memset(para, 0, sizeof(struct arisc_para)); para->message_pool_phys = (uint32_t)dts_cfg.space.msgpool_dst; para->message_pool_size = (uint32_t)dts_cfg.space.msgpool_size; para->standby_base = (uint32_t)dts_cfg.space.standby_dst; para->standby_size = (uint32_t)dts_cfg.space.standby_size; memcpy((void *)¶->vf, (void *)dts_cfg.vf, sizeof(para->vf)); memcpy((void *)¶->dram_para, (void *)&dts_cfg.dram_para, sizeof(para->dram_para)); para->power_key_code = dts_cfg.s_cir.power_key_code; para->addr_code = dts_cfg.s_cir.addr_code; para->suart_status = dts_cfg.s_uart.status; para->pmu_bat_shutdown_ltf = dts_cfg.pmu.pmu_bat_shutdown_ltf; para->pmu_bat_shutdown_htf = dts_cfg.pmu.pmu_bat_shutdown_htf; para->pmu_pwroff_vol = dts_cfg.pmu.pmu_pwroff_vol; para->power_start = dts_cfg.pmu.power_start; para->powchk_used = dts_cfg.power.powchk_used; para->power_reg = dts_cfg.power.power_reg; para->system_power = dts_cfg.power.system_power; ARISC_LOG("arisc_para size:%llx\n", sizeof(struct arisc_para)); ARISC_INF("msgpool base:%x, size:%u\n", para->message_pool_phys, para->message_pool_size); return 0; }
int sunxi_arisc_probe(void *cfg) { struct arisc_para para; ARISC_LOG("sunxi-arisc driver begin startup %d\n", arisc_debug_level); memcpy((void *)&dts_cfg, (const void *)cfg, sizeof(struct dts_cfg)); /* init arisc parameter */ sunxi_arisc_para_init(¶); /* load arisc */ sunxi_load_arisc(dts_cfg.image.base, dts_cfg.image.size, (void *)(¶), sizeof(struct arisc_para)); /* initialize hwspinlock */ ARISC_INF("hwspinlock initialize\n"); arisc_hwspinlock_init(); /* initialize hwmsgbox */ ARISC_INF("hwmsgbox initialize\n"); arisc_hwmsgbox_init(); /* initialize message manager */ ARISC_INF("message manager initialize start:0x%llx, size:0x%llx\n", dts_cfg.space.msgpool_dst, dts_cfg.space.msgpool_size); arisc_message_manager_init((void *)dts_cfg.space.msgpool_dst, dts_cfg.space.msgpool_size); /* wait arisc ready */ ARISC_INF("wait arisc ready....\n"); if (arisc_wait_ready(10000)) { ARISC_LOG("arisc startup failed\n"); } arisc_set_paras(); /* enable arisc asyn tx interrupt */ //arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327); /* enable arisc syn tx interrupt */ //arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327); /* arisc initialize succeeded */ ARISC_LOG("sunxi-arisc driver v%s is starting\n", DRV_VERSION); return 0; }
int sunxi_arisc_wait_ready(void) { ARISC_INF("wait arisc ready....\n"); if (arisc_wait_ready(10000)) { ARISC_LOG("arisc startup failed\n"); } arisc_set_paras(); ARISC_LOG("sunxi-arisc driver v%s startup ok\n", DRV_VERSION); return 0; }
int sunxi_deassert_arisc(void) { ARISC_INF("set arisc reset to de-assert state\n"); { volatile unsigned long value; value = readl(dts_cfg.cpuscfg.base + 0x0); value &= ~1; writel(value, dts_cfg.cpuscfg.base + 0x0); value = readl(dts_cfg.cpuscfg.base + 0x0); value |= 1; writel(value, dts_cfg.cpuscfg.base + 0x0); } return 0; }
/* ********************************************************************************************************* * ALLOCATE MESSAGE FRAME * * Description: allocate one message frame. mainly use for send message by message-box, * the message frame allocate form messages pool shared memory area. * * Arguments : none. * * Returns : the pointer of allocated message frame, NULL if failed; ********************************************************************************************************* */ struct arisc_message *arisc_message_allocate(unsigned int msg_attr) { struct arisc_message *pmessage = (struct arisc_message *)(NULL); struct arisc_message *palloc = (struct arisc_message *)(NULL); //use spinlock 0 to exclusive with arisc. arisc_hwspin_lock_timeout(0, ARISC_SPINLOCK_TIMEOUT); //seach from the start of message pool every time. //maybe have other more good choice. //by sunny at 2012-5-13 10:36:50. pmessage = message_start; while (pmessage < message_end) { if (pmessage->state == ARISC_MESSAGE_FREED) { //find free message in message pool, allocate it. palloc = pmessage; palloc->state = ARISC_MESSAGE_ALLOCATED; ARISC_INF("message allocate from message pool\n"); break; } //next message frame pmessage++; } //unlock hwspinlock 0 arisc_hwspin_unlock(0); if (palloc == (struct arisc_message *)(NULL)) { ARISC_ERR("allocate message frame fail\n"); return palloc; } /* initialize messgae frame */ palloc->next = (struct arisc_message *)(NULL); palloc->attr = msg_attr; return palloc; }
static int sunxi_arisc_clk_cfg(struct platform_device *pdev) { #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) struct clk *pll5 = NULL; struct clk *pll6 = NULL; struct clk *hosc = NULL; struct clk *losc = NULL; ARISC_INF("device [%s] clk resource request enter\n", dev_name(&pdev->dev)); /* config PLL5 for dram clk */ pll5 = clk_get(NULL, PLL5_CLK); if(!pll5 || IS_ERR(pll5)){ ARISC_ERR("try to get pll5 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pll5)) { ARISC_ERR("try to enable pll5 output failed!\n"); return -EINVAL; } /* config PLL6 for cpus clk */ pll6 = clk_get(NULL, PLL6_CLK); if(!pll6 || IS_ERR(pll6)){ ARISC_ERR("try to get pll6 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pll6)) { ARISC_ERR("try to enable pll6 output failed!\n"); return -EINVAL; } #elif (defined CONFIG_ARCH_SUN8IW5P1) struct clk *pllddr0 = NULL; struct clk *pllddr1 = NULL; struct clk *pllperiph = NULL; struct clk *hosc = NULL; struct clk *losc = NULL; ARISC_INF("device [%s] clk resource request enter\n", dev_name(&pdev->dev)); /* config PLL5 for dram clk */ pllddr0 = clk_get(NULL, PLL_DDR0_CLK); if(!pllddr0 || IS_ERR(pllddr0)){ ARISC_ERR("try to get pll_ddr0 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pllddr0)) { ARISC_ERR("try to enable pll_ddr0 output failed!\n"); return -EINVAL; } pllddr1 = clk_get(NULL, PLL_DDR1_CLK); if(!pllddr1 || IS_ERR(pllddr1)){ ARISC_ERR("try to get pll_ddr1 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pllddr1)) { ARISC_ERR("try to enable pll_ddr1 output failed!\n"); return -EINVAL; } /* config PLL6 for cpus clk */ pllperiph = clk_get(NULL, PLL_PERIPH_CLK); if(!pllperiph || IS_ERR(pllperiph)){ ARISC_ERR("try to get pll_periph failed!\n"); return -EINVAL; } if(clk_prepare_enable(pllperiph)) { ARISC_ERR("try to enable pll_periph output failed!\n"); return -EINVAL; } #elif (defined CONFIG_ARCH_SUN8IW6P1) struct clk *pllddr = NULL; struct clk *pllperiph = NULL; struct clk *hosc = NULL; struct clk *losc = NULL; ARISC_INF("device [%s] clk resource request enter\n", dev_name(&pdev->dev)); /* config PLL_DDR for dram clk */ pllddr = clk_get(NULL, PLL_DDR_CLK); if(!pllddr || IS_ERR(pllddr)){ ARISC_ERR("try to get pll_ddr failed!\n"); return -EINVAL; } if(clk_prepare_enable(pllddr)) { ARISC_ERR("try to enable pll_ddr output failed!\n"); return -EINVAL; } /* config PLL_PERIPH for cpus clk */ pllperiph = clk_get(NULL, PLL_PERIPH_CLK); if(!pllperiph || IS_ERR(pllperiph)){ ARISC_ERR("try to get pll_periph failed!\n"); return -EINVAL; } if(clk_prepare_enable(pllperiph)) { ARISC_ERR("try to enable pll_periph output failed!\n"); return -EINVAL; } #elif defined CONFIG_ARCH_SUN9IW1P1 struct clk *pll3 = NULL; struct clk *pll4 = NULL; struct clk *pll6 = NULL; struct clk *hosc = NULL; struct clk *losc = NULL; ARISC_INF("device [%s] clk resource request enter\n", dev_name(&pdev->dev)); /* config PLL6 for dram clk */ pll6 = clk_get(NULL, PLL6_CLK); if(!pll6 || IS_ERR(pll6)){ ARISC_ERR("try to get pll6 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pll6)) { ARISC_ERR("try to enable pll6 output failed!\n"); return -EINVAL; } /* config PLL3 for cpus clk */ pll3 = clk_get(NULL, PLL3_CLK); if(!pll3 || IS_ERR(pll3)){ ARISC_ERR("try to get pll3 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pll3)) { ARISC_ERR("try to enable pll3 output failed!\n"); return -EINVAL; } /* config PLL4 for cpus clk */ pll4 = clk_get(NULL, PLL4_CLK); if(!pll4 || IS_ERR(pll4)){ ARISC_ERR("try to get pll4 failed!\n"); return -EINVAL; } if(clk_prepare_enable(pll4)) { ARISC_ERR("try to enable pll4 output failed!\n"); return -EINVAL; } #endif /* config HOSC for cpus clk */ hosc = clk_get(NULL, HOSC_CLK); if(!hosc || IS_ERR(hosc)){ ARISC_ERR("try to get hosc failed!\n"); return -EINVAL; } if(clk_prepare_enable(hosc)) { ARISC_ERR("try to enable hosc output failed!\n"); return -EINVAL; } /* config LOSC for cpus clk */ losc = clk_get(NULL, LOSC_CLK); if(!losc || IS_ERR(losc)){ ARISC_ERR("try to get losc failed!\n"); return -EINVAL; } if(clk_prepare_enable(losc)) { ARISC_ERR("try to enable losc output failed!\n"); return -EINVAL; } ARISC_INF("device [%s] clk resource request ok\n", dev_name(&pdev->dev)); return 0; }
static int arisc_wait_ready(unsigned int timeout) { unsigned long expire; #ifdef CONFIG_SUNXI_MODULE struct sunxi_module_info arisc_module_info; #endif expire = msecs_to_jiffies(timeout) + jiffies; /* wait arisc startup ready */ while (1) { /* * linux cpu interrupt is disable now, * we should query message by hand. */ struct arisc_message *pmessage = arisc_hwmsgbox_query_message(); if (pmessage == NULL) { if (time_is_before_eq_jiffies(expire)) { return -ETIMEDOUT; } /* try to query again */ continue; } /* query valid message */ if (pmessage->type == ARISC_STARTUP_NOTIFY) { /* check arisc software and driver version match or not */ if (pmessage->paras[0] != ARISC_VERSIONS) { ARISC_ERR("arisc firmware:%d and driver version:%d not matched\n", pmessage->paras[0], ARISC_VERSIONS); return -EINVAL; } else { /* printf the main and sub version string */ memcpy((void *)arisc_version, (const void*)(&(pmessage->paras[1])), 40); ARISC_LOG("arisc version: [%s]\n", arisc_version); #ifdef CONFIG_SUNXI_MODULE strncpy((char *)arisc_module_info.module, (const char *)"arisc", 16); strncpy((char *)arisc_module_info.version, (const char *)arisc_version, 16); sunxi_module_info_register(&arisc_module_info); #endif } /* received arisc startup ready message */ ARISC_INF("arisc startup ready\n"); if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ ARISC_INF("arisc startup notify message feedback\n"); pmessage->paras[0] = virt_to_phys((void *)&arisc_binary_start); arisc_hwmsgbox_feedback_message(pmessage, ARISC_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ ARISC_INF("arisc startup notify message free directly\n"); arisc_message_free(pmessage); } break; } /* * invalid message detected, ignore it. * by sunny at 2012-7-6 18:34:38. */ ARISC_WRN("arisc startup waiting ignore message\n"); if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ arisc_message_free(pmessage); } /* we need waiting continue */ } return 0; }
static int sunxi_arisc_probe(struct platform_device *pdev) { int binary_len; int ret; ARISC_INF("arisc initialize\n"); /* cfg sunxi arisc clk */ ret = sunxi_arisc_clk_cfg(pdev); if (ret) { ARISC_ERR("sunxi-arisc clk cfg failed\n"); return -EINVAL; } /* cfg sunxi arisc pin */ ret = sunxi_arisc_pin_cfg(pdev); if (ret) { ARISC_ERR("sunxi-arisc pin cfg failed\n"); return -EINVAL; } ARISC_INF("sram_a2 vaddr(%x)\n", (unsigned int)arisc_sram_a2_vbase); #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN8IW6P1) binary_len = 0x13000; #elif defined CONFIG_ARCH_SUN9IW1P1 binary_len = (int)(&arisc_binary_end) - (int)(&arisc_binary_start); #endif /* clear sram_a2 area */ memset((void *)arisc_sram_a2_vbase, 0, SUNXI_SRAM_A2_SIZE); /* load arisc system binary data to sram_a2 */ memcpy((void *)arisc_sram_a2_vbase, (void *)(&arisc_binary_start), binary_len); ARISC_INF("move arisc binary data [addr = %x, len = %x] to sram_a2 finished\n", (unsigned int)(&arisc_binary_start), (unsigned int)binary_len); /* initialize hwspinlock */ ARISC_INF("hwspinlock initialize\n"); arisc_hwspinlock_init(); /* initialize hwmsgbox */ ARISC_INF("hwmsgbox initialize\n"); arisc_hwmsgbox_init(); /* initialize message manager */ ARISC_INF("message manager initialize\n"); arisc_message_manager_init(); /* set arisc cpu reset to de-assert state */ ARISC_INF("set arisc reset to de-assert state\n"); #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN8IW6P1) { volatile unsigned long value; value = readl((IO_ADDRESS(SUNXI_R_CPUCFG_PBASE) + 0x0)); value &= ~1; writel(value, (IO_ADDRESS(SUNXI_R_CPUCFG_PBASE) + 0x0)); value = readl((IO_ADDRESS(SUNXI_R_CPUCFG_PBASE) + 0x0)); value |= 1; writel(value, (IO_ADDRESS(SUNXI_R_CPUCFG_PBASE) + 0x0)); } #elif defined CONFIG_ARCH_SUN9IW1P1 { volatile unsigned long value; value = readl((IO_ADDRESS(SUNXI_R_PRCM_PBASE) + 0x0)); value &= ~1; writel(value, (IO_ADDRESS(SUNXI_R_PRCM_PBASE) + 0x0)); value = readl((IO_ADDRESS(SUNXI_R_PRCM_PBASE) + 0x0)); value |= 1; writel(value, (IO_ADDRESS(SUNXI_R_PRCM_PBASE) + 0x0)); } #endif /* wait arisc ready */ ARISC_INF("wait arisc ready....\n"); if (arisc_wait_ready(10000)) { ARISC_LOG("arisc startup failed\n"); } /* enable arisc asyn tx interrupt */ arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327); /* enable arisc syn tx interrupt */ arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327); /* config dvfs v-f table */ if (arisc_dvfs_cfg_vf_table()) { ARISC_WRN("config dvfs v-f table failed\n"); } #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW6P1) || (defined CONFIG_ARCH_SUN9IW1P1) /* config ir config paras */ if (arisc_config_ir_paras()) { ARISC_WRN("config ir paras failed\n"); } #endif #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) /* config pmu config paras */ if (arisc_config_pmu_paras()) { ARISC_WRN("config pmu paras failed\n"); } #endif /* config dram config paras */ if (arisc_config_dram_paras()) { ARISC_WRN("config dram paras failed\n"); } #if (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN9IW1P1) /* config standby power paras */ if (arisc_sysconfig_sstpower_paras()) { ARISC_WRN("config sst power paras failed\n"); } #endif atomic_set(&arisc_suspend_flag, 0); /* * detect sunxi chip id * include soc chip id, pmu chip id and serial. */ sunxi_chip_id_init(); /* arisc initialize succeeded */ ARISC_LOG("sunxi-arisc driver v%s startup succeeded\n", DRV_VERSION); return 0; }
static int sunxi_arisc_pin_cfg(struct platform_device *pdev) { script_item_u script_val; script_item_value_type_e type; script_item_u *pin_list; int pin_count = 0; int pin_index = 0; struct gpio_config *pin_cfg; char pin_name[SUNXI_PIN_NAME_MAX_LEN]; unsigned long config; ARISC_INF("device [%s] pin resource request enter\n", dev_name(&pdev->dev)); /* * request arisc resources: * p2wi/rsb gpio... */ /* get pin sys_config info */ #if defined CONFIG_ARCH_SUN8IW1P1 pin_count = script_get_pio_list ("s_p2twi0", &pin_list); #elif (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN8IW6P1) pin_count = script_get_pio_list ("s_rsb0", &pin_list); #elif defined CONFIG_ARCH_SUN9IW1P1 pin_count = script_get_pio_list ("s_rsb0", &pin_list); #else #error "please select a platform\n" #endif if (pin_count == 0) { /* "s_p2twi0" or "s_rsb0" have no pin configuration */ ARISC_WRN("arisc s_p2twi0/s_rsb0 have no pin configuration\n"); return -EINVAL; } /* request pin individually */ for (pin_index = 0; pin_index < pin_count; pin_index++) { pin_cfg = &(pin_list[pin_index].gpio); /* valid pin of sunxi-pinctrl, config pin attributes individually.*/ sunxi_gpio_to_name(pin_cfg->gpio, pin_name); config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg->mul_sel); pin_config_set(SUNXI_PINCTRL, pin_name, config); if (pin_cfg->pull != GPIO_PULL_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pin_cfg->pull); pin_config_set (SUNXI_PINCTRL, pin_name, config); } if (pin_cfg->drv_level != GPIO_DRVLVL_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, pin_cfg->drv_level); pin_config_set (SUNXI_PINCTRL, pin_name, config); } if (pin_cfg->data != GPIO_DATA_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg->data); pin_config_set (SUNXI_PINCTRL, pin_name, config); } } /* * request arisc resources: * uart gpio... */ type = script_get_item("s_uart0", "s_uart_used", &script_val); if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { ARISC_WRN("sys_config.fex have no arisc s_uart0 config!"); script_val.val = 0; } if (script_val.val) { pin_count = script_get_pio_list ("s_uart0", &pin_list); if (pin_count == 0) { /* "s_uart0" have no pin configuration */ ARISC_WRN("arisc s_uart0 have no pin configuration\n"); return -EINVAL; } /* request pin individually */ for (pin_index = 0; pin_index < pin_count; pin_index++) { pin_cfg = &(pin_list[pin_index].gpio); /* valid pin of sunxi-pinctrl, config pin attributes individually.*/ sunxi_gpio_to_name(pin_cfg->gpio, pin_name); config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg->mul_sel); pin_config_set(SUNXI_PINCTRL, pin_name, config); if (pin_cfg->pull != GPIO_PULL_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pin_cfg->pull); pin_config_set (SUNXI_PINCTRL, pin_name, config); } if (pin_cfg->drv_level != GPIO_DRVLVL_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, pin_cfg->drv_level); pin_config_set (SUNXI_PINCTRL, pin_name, config); } if (pin_cfg->data != GPIO_DATA_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg->data); pin_config_set (SUNXI_PINCTRL, pin_name, config); } } } ARISC_INF("arisc uart debug config [%s] [%s] : %d\n", "s_uart0", "s_uart_used", script_val.val); /* * request arisc resources: * jtag gpio... */ type = script_get_item("s_jtag0", "s_jtag_used", &script_val); if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { ARISC_WRN("sys_config.fex have no arisc s_jtag0 config!"); script_val.val = 0; } if (script_val.val) { pin_count = script_get_pio_list ("s_jtag0", &pin_list); if (pin_count == 0) { /* "s_jtag0" have no pin configuration */ ARISC_WRN("arisc s_jtag0 have no pin configuration\n"); return -EINVAL; } /* request pin individually */ for (pin_index = 0; pin_index < pin_count; pin_index++) { pin_cfg = &(pin_list[pin_index].gpio); /* valid pin of sunxi-pinctrl, config pin attributes individually.*/ sunxi_gpio_to_name(pin_cfg->gpio, pin_name); config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg->mul_sel); pin_config_set(SUNXI_PINCTRL, pin_name, config); if (pin_cfg->pull != GPIO_PULL_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pin_cfg->pull); pin_config_set (SUNXI_PINCTRL, pin_name, config); } if (pin_cfg->drv_level != GPIO_DRVLVL_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, pin_cfg->drv_level); pin_config_set (SUNXI_PINCTRL, pin_name, config); } if (pin_cfg->data != GPIO_DATA_DEFAULT) { config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg->data); pin_config_set (SUNXI_PINCTRL, pin_name, config); } } } ARISC_INF("arisc jtag debug config [%s] [%s] : %d\n", "s_jtag0", "s_jtag_used", script_val.val); ARISC_INF("device [%s] pin resource request ok\n", dev_name(&pdev->dev)); return 0; }