コード例 #1
0
ファイル: arisc_hwmsgbox.c プロジェクト: 925outer/BPI-M2P-bsp
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;
}
コード例 #2
0
ファイル: arisc.c プロジェクト: dmitry-shavyrin/a64_lichee
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;
}
コード例 #3
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 {
コード例 #4
0
ファイル: arisc.c プロジェクト: dmitry-shavyrin/a64_lichee
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;
}
コード例 #5
0
ファイル: arisc_hwmsgbox.c プロジェクト: 925outer/BPI-M2P-bsp
/*
*********************************************************************************************************
*                                       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;
}
コード例 #6
0
ファイル: arisc.c プロジェクト: dmitry-shavyrin/a64_lichee
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 *)&para->vf, (void *)dts_cfg.vf, sizeof(para->vf));
	memcpy((void *)&para->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;
}
コード例 #7
0
ファイル: arisc.c プロジェクト: dmitry-shavyrin/a64_lichee
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(&para);

	/* load arisc */
	sunxi_load_arisc(dts_cfg.image.base, dts_cfg.image.size,
	                 (void *)(&para), 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;
}
コード例 #8
0
ファイル: arisc.c プロジェクト: dmitry-shavyrin/a64_lichee
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;
}
コード例 #9
0
ファイル: arisc.c プロジェクト: dmitry-shavyrin/a64_lichee
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;
}
コード例 #10
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;
}
コード例 #11
0
ファイル: arisc.c プロジェクト: alex-deng/a33_linux
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;
}
コード例 #12
0
ファイル: arisc.c プロジェクト: alex-deng/a33_linux
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;
}
コード例 #13
0
ファイル: arisc.c プロジェクト: alex-deng/a33_linux
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;
}
コード例 #14
0
ファイル: arisc.c プロジェクト: alex-deng/a33_linux
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;
}