static int __init ar100_init(void)
{
	int ret;
	
	AR100_LOG("sun6i ar100 driver v%s\n", DRV_VERSION);

	ret = platform_driver_register(&sun6i_ar100_driver);
	if (IS_ERR_VALUE(ret)) {
		AR100_ERR("register sun6i ar100 platform driver failed\n");
		goto err_platform_driver_register;
	}
	ret = platform_device_register(&sun6i_ar100_device);
	if (IS_ERR_VALUE(ret)) {
		AR100_ERR("register sun6i ar100 platform device failed\n");
		goto err_platform_device_register;
	}
	
	sun6i_ar100_sysfs(&sun6i_ar100_device);
		
	return 0;
	
err_platform_device_register:
	platform_device_unregister(&sun6i_ar100_device);
err_platform_driver_register:
	platform_driver_unregister(&sun6i_ar100_driver);
	return -EINVAL;
}
Example #2
0
/*
*********************************************************************************************************
*                                        QUERY MESSAGE
*
* Description: 	query message of hwmsgbox by hand, mainly for.
*
* Arguments  : 	none.
*
* Returns    : 	the point of message, NULL if timeout.
*********************************************************************************************************
*/
struct ar100_message *ar100_hwmsgbox_query_message(void)
{
	struct ar100_message *pmessage = NULL;
	
	//query ac327 asyn received channel
	if (readl(IO_ADDRESS(AW_MSGBOX_MSG_STATUS_REG(AR100_HWMSGBOX_AR100_ASYN_TX_CH)))) {
		volatile unsigned long value;
		value = readl(IO_ADDRESS(AW_MSGBOX_MSG_REG(AR100_HWMSGBOX_AR100_ASYN_TX_CH)));
		pmessage = (struct ar100_message *)(value + ar100_sram_a2_vbase);
		if (ar100_message_valid(pmessage)) {
			//message state switch
			if (pmessage->state == AR100_MESSAGE_PROCESSED) {
				//AR100_MESSAGE_PROCESSED->AR100_MESSAGE_FEEDBACKED
				pmessage->state = AR100_MESSAGE_FEEDBACKED;
			} else {
				//AR100_MESSAGE_INITIALIZED->AR100_MESSAGE_RECEIVED
				pmessage->state = AR100_MESSAGE_RECEIVED;
			}
		} else {
			//print_call_info();
			AR100_ERR("invalid message received: 1 pmessage = 0x%x. \n", (__u32)pmessage);
			return NULL;
		}
		//clear pending
		ar100_hwmsgbox_clear_receiver_pending(AR100_HWMSGBOX_AR100_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
		return pmessage;
	}
	//query ac327 syn received channel
	if (readl(IO_ADDRESS(AW_MSGBOX_MSG_STATUS_REG(AR100_HWMSGBOX_AR100_SYN_TX_CH)))) {
		volatile unsigned long value;
		value = readl(IO_ADDRESS(AW_MSGBOX_MSG_REG(AR100_HWMSGBOX_AR100_SYN_TX_CH)));
		pmessage = (struct ar100_message *)(value + ar100_sram_a2_vbase);
		if (ar100_message_valid(pmessage)) {
			//message state switch
			if (pmessage->state == AR100_MESSAGE_PROCESSED) {
				//AR100_MESSAGE_PROCESSED->AR100_MESSAGE_FEEDBACKED
				pmessage->state = AR100_MESSAGE_FEEDBACKED;
			} else {
				//AR100_MESSAGE_INITIALIZED->AR100_MESSAGE_RECEIVED
				pmessage->state = AR100_MESSAGE_RECEIVED;
			}
		} else {
			//print_call_info();
			AR100_ERR("invalid message received: 2 pmessage = 0x%x. \n", (__u32)pmessage);
			return NULL;
		}
		ar100_hwmsgbox_clear_receiver_pending(AR100_HWMSGBOX_AR100_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
		return pmessage;
	}
	//no valid message
	return NULL;
}
Example #3
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 ar100_hwmsgbox_send_message(struct ar100_message *pmessage, unsigned int timeout)
{
	volatile unsigned long value;
	
	if (pmessage == NULL) {
		return -EINVAL;
	}
	if (pmessage->attr & AR100_MESSAGE_ATTR_HARDSYN) {
		//use ac327 hwsyn transmit channel.
		while (readl(IO_ADDRESS(AW_MSGBOX_FIFO_STATUS_REG(AR100_HWMSGBOX_AC327_SYN_TX_CH))) == 1) {
			//message-queue fifo is full, waiting always
			;
		}
		value = ((volatile unsigned long)pmessage) - ar100_sram_a2_vbase; 
		AR100_INF("ac327 send hard syn message : %x\n", (unsigned int)value);
		writel(value, IO_ADDRESS(AW_MSGBOX_MSG_REG(AR100_HWMSGBOX_AC327_SYN_TX_CH)));
		
		//hwsyn messsage must feedback use syn rx channel
		while (readl(IO_ADDRESS(AW_MSGBOX_MSG_STATUS_REG(AR100_HWMSGBOX_AC327_SYN_RX_CH))) == 0) {
			//message not valid
			;
		}
		//check message valid
		if (value != (readl(IO_ADDRESS(AW_MSGBOX_MSG_REG(AR100_HWMSGBOX_AC327_SYN_RX_CH))))) {
			AR100_ERR("hard syn message error\n");
			return -EINVAL;
		}
		AR100_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(AR100_HWMSGBOX_AR100_ASYN_RX_CH))) == 1) {
		//message-queue fifo is full, waiting always
		;
	}
	//write message to message-queue fifo.
	value = ((volatile unsigned long)pmessage) - ar100_sram_a2_vbase; 
	AR100_LOG("ac327 send message : %x\n", (unsigned int)value);
	writel(value, IO_ADDRESS(AW_MSGBOX_MSG_REG(AR100_HWMSGBOX_AR100_ASYN_RX_CH)));
	
	//syn messsage must wait message feedback
	if (pmessage->attr & AR100_MESSAGE_ATTR_SOFTSYN) {
		AR100_ERR("standby ar100 driver not support soft syn message transfer\n");
		return -EINVAL;
	}
	
	return 0;
}
static int ar100_wait_ready(unsigned int timeout)
{
	unsigned long          expire;
	
	expire = msecs_to_jiffies(timeout) + jiffies;
	
	/* wait ar100 startup ready */
	while (1) {
		/*
		 * linux cpu interrupt is disable now, 
		 * we should query message by hand.
		 */
		struct ar100_message *pmessage = ar100_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 == AR100_STARTUP_NOTIFY) {
			/* check ar100 software and driver version match or not */
			if (pmessage->paras[0] != AR100_VERSIONS) {
				AR100_ERR("ar100 firmware and driver version not matched\n");
				return -EINVAL;
			}
			/* received ar100 startup ready message */
			AR100_INF("ar100 startup ready\n");
			if ((pmessage->attr & AR100_MESSAGE_ATTR_SOFTSYN) ||
				(pmessage->attr & AR100_MESSAGE_ATTR_HARDSYN)) {
				/* synchronous message, just feedback it */
				AR100_INF("ar100 startup notify message feedback\n");
				pmessage->paras[0] = virt_to_phys((void *)&ar100_binary_start);
				ar100_hwmsgbox_feedback_message(pmessage, AR100_SEND_MSG_TIMEOUT);
			} else {
				/* asyn message, free message directly */
				AR100_INF("ar100 startup notify message free directly\n");
				ar100_message_free(pmessage);
			}
			break;
		}
		/* 
		 * invalid message detected, ignore it.
		 * by sunny at 2012-7-6 18:34:38.
		 */
		AR100_WRN("ar100 startup waiting ignore message\n");
		if ((pmessage->attr & AR100_MESSAGE_ATTR_SOFTSYN) ||
			(pmessage->attr & AR100_MESSAGE_ATTR_HARDSYN)) {
			/* synchronous message, just feedback it */
			ar100_hwmsgbox_send_message(pmessage, AR100_SEND_MSG_TIMEOUT);
		} else {
			/* asyn message, free message directly */
			ar100_message_free(pmessage);
		}
		/* we need waiting continue */
	}
	
	return 0;
}
int ar100_dvfs_get_cfg(char *main, char *sub, u32 *val)
{
	script_item_u script_val;
	script_item_value_type_e type;
	type = script_get_item(main, sub, &script_val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
		AR100_ERR("ar100 dvfs config type err!");
		return -EINVAL;
	}
	*val = script_val.val;
	AR100_INF("ar100 dvfs config [%s] [%s] : %d\n", main, sub, *val);
	return 0;
}