diff options
Diffstat (limited to 'plat/sun50iw1p1/scp/interfaces')
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_axp.c | 402 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c | 137 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c | 57 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c | 81 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_loopback.c | 51 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_rsb.c | 329 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/arisc_standby.c | 286 | ||||
-rw-r--r-- | plat/sun50iw1p1/scp/interfaces/interfaces.mk | 37 |
8 files changed, 1380 insertions, 0 deletions
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_axp.c b/plat/sun50iw1p1/scp/interfaces/arisc_axp.c new file mode 100644 index 0000000..a33cfe2 --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_axp.c @@ -0,0 +1,402 @@ +/* + * drivers/arisc/interfaces/arisc_axp.c + * + * Copyright (c) 2012 Allwinner. + * 2012-10-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +/* nmi isr node, record current nmi interrupt handler and argument */ +nmi_isr_t nmi_isr_node[2]; + +/** + * register call-back function, call-back function is for arisc notify some event to ac327, + * axp/rtc interrupt for external interrupt NMI. + * @type: nmi type, pmu/rtc; + * @func: call-back function; + * @para: parameter for call-back function; + * + * @return: result, 0 - register call-back function successed; + * !0 - register call-back function failed; + * NOTE: the function is like "int callback(void *para)"; + * this function will execute in system ISR. + */ +int arisc_nmi_cb_register(uint32_t type, arisc_cb_t func, void *para) +{ + if (nmi_isr_node[type].handler) { + if(func == nmi_isr_node[type].handler) { + ARISC_WRN("nmi interrupt handler register already\n"); + return 0; + } + /* just output warning message, overlay handler */ + ARISC_WRN("nmi interrupt handler register already\n"); + return -EINVAL; + } + nmi_isr_node[type].handler = func; + nmi_isr_node[type].arg = para; + + return 0; +} + + +/** + * unregister call-back function. + * @type: nmi type, pmu/rtc; + * @func: call-back function which need be unregister; + */ +void arisc_nmi_cb_unregister(uint32_t type, arisc_cb_t func) +{ + if ((nmi_isr_node[type].handler) != (func)) { + /* invalid handler */ + ARISC_WRN("invalid handler for unreg\n\n"); + return ; + } + nmi_isr_node[type].handler = NULL; + nmi_isr_node[type].arg = NULL; +} + +int arisc_disable_nmi_irq(void) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_AXP_DISABLE_IRQ; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_enable_nmi_irq(void) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_AXP_ENABLE_IRQ; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_clear_nmi_status(void) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_CLR_NMI_STATUS; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_set_nmi_trigger(uint32_t type) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_NMI_TRIGGER; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + pmessage->paras[0] = type; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_axp_get_chip_id(unsigned char *chip_id) +{ + int i; + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_AXP_GET_CHIP_ID; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + memset((void *)pmessage->paras, 0, 16); + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* |paras[0] |paras[1] |paras[2] |paras[3] | + * |chip_id[0~3]|chip_id[4~7]|chip_id[8~11]|chip_id[12~15]| + */ + /* copy message readout data to user data buffer */ + for (i = 0; i < 4; i++) { + chip_id[i] = (pmessage->paras[0] >> (i * 8)) & 0xff; + chip_id[4 + i] = (pmessage->paras[1] >> (i * 8)) & 0xff; + chip_id[8 + i] = (pmessage->paras[2] >> (i * 8)) & 0xff; + chip_id[12 + i] = (pmessage->paras[3] >> (i * 8)) & 0xff; + } + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_set_led_bln(uint32_t *paras) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_LED_BLN; + pmessage->paras[0] = paras[0]; + pmessage->paras[1] = paras[1]; + pmessage->paras[2] = paras[2]; + pmessage->paras[3] = paras[3]; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; + +} + +#if (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN50IW1P1) +int arisc_adjust_pmu_chgcur(uint32_t max_chgcur, uint32_t chg_ic_temp, uint32_t flag) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_AXP_SET_PARAS; + pmessage->paras[0] = chg_ic_temp; + pmessage->paras[1] = max_chgcur; + pmessage->paras[2] = flag; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} +#endif + +int arisc_set_pwr_tree(uint32_t *pwr_tree) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_PWR_TREE; + memcpy((void *)pmessage->paras, (void *)pwr_tree, sizeof(int)*DM_MAX); + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_axp_int_notify(struct arisc_message *pmessage) +{ + uint32_t type = pmessage->paras[0]; + uint32_t ret = 0; + + if (type & NMI_INT_TYPE_PMU_OFFSET) { + /* call pmu interrupt handler */ + if (nmi_isr_node[NMI_INT_TYPE_PMU].handler == NULL) { + ARISC_WRN("pmu irq handler not install\n"); + return 1; + } + + ARISC_INF("call pmu interrupt handler\n"); + ret |= (*(nmi_isr_node[NMI_INT_TYPE_PMU].handler))(nmi_isr_node[NMI_INT_TYPE_PMU].arg); + } + if (type & NMI_INT_TYPE_RTC_OFFSET) + { + /* call rtc interrupt handler */ + if (nmi_isr_node[NMI_INT_TYPE_RTC].handler == NULL) { + ARISC_WRN("rtc irq handler not install\n"); + return 1; + } + + ARISC_INF("call rtc interrupt handler\n"); + ret |= (*(nmi_isr_node[NMI_INT_TYPE_RTC].handler))(nmi_isr_node[NMI_INT_TYPE_RTC].arg); + } + + return ret; +} + +int arisc_pmu_set_voltage(uint32_t type, uint32_t voltage) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_PMU_VOLT; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + pmessage->paras[0] = type; + pmessage->paras[1] = voltage; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_pmu_get_voltage(uint32_t type, uint32_t *voltage) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_GET_PMU_VOLT; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + pmessage->paras[0] = type; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + *voltage = pmessage->paras[1]; + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c b/plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c new file mode 100644 index 0000000..e1e5346 --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c @@ -0,0 +1,137 @@ +/* + * drivers/arisc/interfaces/arisc_debug_level.c + * + * Copyright (c) 2012 Allwinner. + * 2012-10-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +/** + * set arisc debug level. + * @level: arisc debug level; + * + * return: 0 - set arisc debug level successed, !0 - set arisc debug level failed; + */ +int arisc_set_debug_level(unsigned int level) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_ERR("allocate message for debug level request failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_DEBUG_LEVEL; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->paras[0] = level; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send set debug level request to arisc */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_set_uart_baudrate(uint32_t baudrate) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_ERR("allocate message for set baudrate request failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_UART_BAUDRATE; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->paras[0] = baudrate; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +int arisc_report_error_info(struct arisc_message *pmessage) +{ + uint32_t id = pmessage->paras[0]; + + switch(id) { + case ERR_NMI_INT_TIMEOUT: { + ARISC_ERR("arisc report error info: nmi int response timeout\n"); + break; + } + default: { + ARISC_ERR("invaid arisc report error infomation id:%u\n", id); + return -EINVAL; + } + } + + return 0; +} + +/** + * set paras. + * + * return: 0 - set paras successed, !0 - set paras failed; + */ +int arisc_set_paras(void) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_ERR("allocate message for set paras request failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_PARAS; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send set debug level request to arisc */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +}
\ No newline at end of file diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c b/plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c new file mode 100644 index 0000000..fd82232 --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c @@ -0,0 +1,57 @@ +/* + * drivers/arisc/interfaces/arisc_dram_crc.c + * + * Copyright (c) 2012 Allwinner. + * 2012-10-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +/** + * set arisc debug dram crc paras. + * @dram_crc_en: arisc debug dram crc enable or disable; + * @dram_crc_srcaddr: source address of dram crc area + * @dram_crc_len: lenght of dram crc area + * + * return: 0 - set arisc debug dram crc paras successed, !0 - set arisc debug dram crc paras failed; + */ +int arisc_set_dram_crc_paras(unsigned int dram_crc_en, unsigned int dram_crc_srcaddr, unsigned int dram_crc_len) +{ + struct arisc_message *pmessage; + + ARISC_INF("en:%x, src:%x len:%x\n", dram_crc_en, dram_crc_srcaddr, dram_crc_len); + + /* allocate a message frame */ + pmessage = arisc_message_allocate(0); + if (pmessage == NULL) { + ARISC_ERR("allocate message for seting dram crc paras request failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SET_DEBUG_DRAM_CRC_PARAS; + pmessage->paras[0] = dram_crc_en; + pmessage->paras[1] = dram_crc_srcaddr; + pmessage->paras[2] = dram_crc_len; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + + /* send set debug level request to arisc */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + return 0; +} + diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c b/plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c new file mode 100644 index 0000000..c7c50cc --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c @@ -0,0 +1,81 @@ +/* + * drivers/arisc/interfaces/arisc_dvfs.c + * + * Copyright (c) 2012 Allwinner. + * 2012-10-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +static int dvfs_err_cb(void *arg) +{ + ARISC_ERR("dvfs error\n"); + + return 0; +} + +/* + * set specific pll target frequency. + * @freq: target frequency to be set, based on KHZ; + * @pll: which pll will be set + * @mode: the attribute of message, whether syn or asyn; + * @cb: callback handler; + * @cb_arg: callback handler arguments; + * + * return: result, 0 - set frequency successed, + * !0 - set frequency failed; + */ +int arisc_dvfs_set_cpufreq(uint32_t freq, uint32_t pll, uint32_t mode) +{ + unsigned int msg_attr = 0; + struct arisc_message *pmessage; + int result = 0; + + if (mode & ARISC_DVFS_SYN) { + msg_attr |= ARISC_MESSAGE_ATTR_HARDSYN; + } + + /* allocate a message frame */ + pmessage = arisc_message_allocate(msg_attr); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message + * + * |paras[0]|paras[1]| + * |freq |pll | + */ + pmessage->type = ARISC_CPUX_DVFS_REQ; + pmessage->paras[0] = freq; + pmessage->paras[1] = pll; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = dvfs_err_cb; + pmessage->cb.arg = NULL; + + ARISC_INF("arisc dvfs request : %d\n", freq); + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* dvfs mode : syn or not */ + if (mode & ARISC_DVFS_SYN) { + result = pmessage->result; + arisc_message_free(pmessage); + } + + return result; +} diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_loopback.c b/plat/sun50iw1p1/scp/interfaces/arisc_loopback.c new file mode 100644 index 0000000..029d4dc --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_loopback.c @@ -0,0 +1,51 @@ +/* + * drivers/arisc/interfaces/arisc_loopback.c + * + * Copyright (c) 2012 Allwinner. + * 2012-10-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +int arisc_message_loopback(void) +{ + int result; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_MESSAGE_LOOPBACK; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->paras[0] = 11; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_rsb.c b/plat/sun50iw1p1/scp/interfaces/arisc_rsb.c new file mode 100644 index 0000000..f3b685b --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_rsb.c @@ -0,0 +1,329 @@ +/* + * drivers/arisc/interfaces/arisc_rsb.c + * + * Copyright (c) 2013 Allwinner. + * 2013-07-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +#if (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN8IW6P1) || \ + (defined CONFIG_ARCH_SUN8IW7P1) || (defined CONFIG_ARCH_SUN8IW9P1) || (defined CONFIG_ARCH_SUN9IW1P1) || \ + (defined CONFIG_ARCH_SUN50IW1P1) + +/* + * used for indicate aduio codec been initialized, + * modules like audio & trc mabye initialize, + * but audio codec only can be initialize once + */ +static int audio_codec_init = 0; + +/** + * rsb read block data. + * @cfg: point of arisc_rsb_block_cfg struct; + * + * return: result, 0 - read register successed, + * !0 - read register failed or the len more then max len; + */ +int arisc_rsb_read_block_data(uint32_t *paras) +{ + int result; + struct arisc_message *pmessage; + + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_RSB_READ_BLOCK_DATA; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + memcpy((void *)pmessage->paras, (const void *)paras, sizeof(pmessage->paras)); + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + memcpy((void *)paras, (const void *)pmessage->paras, sizeof(pmessage->paras)); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + + +/** + * rsb write block data. + * @cfg: point of arisc_rsb_block_cfg struct; + * + * return: result, 0 - write register successed, + * !0 - write register failedor the len more then max len; + */ +int arisc_rsb_write_block_data(uint32_t *paras) +{ + int result; + struct arisc_message *pmessage; + + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + /* initialize message */ + pmessage->type = ARISC_RSB_WRITE_BLOCK_DATA; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + memcpy((void *)pmessage->paras, (const void *)paras, sizeof(pmessage->paras)); + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + + +/** + * rsb read pmu reg. + * @addr: pmu reg addr; + * + * return: if read pmu reg successed, return data of pmu reg; + * if read pmu reg failed, return -1. + */ +uint8_t arisc_rsb_read_pmu_reg(uint32_t addr) +{ + int result; + uint32_t paras[22]; + uint32_t data = 0; + + /* + * package address and data to message->paras, + * message->paras data layout: + * |para[0] |para[1]|para[2] |para[3]|para[4]|para[5]|para[6]| + * |(len|datatype)|devaddr|regaddr0~3|data0 |data1 |data2 |data3 | + */ + memset((void *)paras, 0, sizeof(uint32_t) * 6); + paras[0] = ((1 & 0xffff) | ((RSB_DATA_TYPE_BYTE << 16) & 0xffff0000)); + paras[1] = 0x2d; + paras[2] = addr&0xff; + + result = arisc_rsb_read_block_data(paras); + if (!result) { + data = paras[3]; + } else { + ARISC_ERR("arisc rsb read pmu reg 0x%x err\n", addr); + return -1; + } + + ARISC_INF("read pmu reg 0x%x:0x%x\n", addr, data); + + return data; +} + + +/** + * rsb write pmu reg. + * @addr: pmu reg addr; + * @data: pmu reg data; + * + * return: result, 0 - write register successed, + * !0 - write register failedor the len more then max len; + */ +int arisc_rsb_write_pmu_reg(uint32_t addr, uint32_t data) +{ + int result; + uint32_t paras[22]; + + /* + * package address and data to message->paras, + * message->paras data layout: + * |para[0] |para[1]|para[2] |para[3]|para[4]|para[5]|para[6]| + * |(len|datatype)|devaddr|regaddr0~3|data0 |data1 |data2 |data3 | + */ + memset((void *)paras, 0, sizeof(uint32_t) * 6); + paras[0] = ((1 & 0xffff) | ((RSB_DATA_TYPE_BYTE << 16) & 0xffff0000)); + paras[1] = 0x2d; + paras[2] = addr&0xff; + paras[3] = data&0xff; + + result = arisc_rsb_write_block_data(paras); + if (result) { + ARISC_ERR("arisc rsb write pmu reg 0x%x:0x%x err\n", addr, data); + } + ARISC_INF("write pmu reg 0x%x:0x%x\n", addr, data); + + return result; +} + + +/** + * rsb bits operation sync. + * @cfg: point of arisc_rsb_bits_cfg struct; + * + * return: result, 0 - bits operation successed, + * !0 - bits operation failed, or the len more then max len; + * + * rsb clear bits internal: + * data = rsb_read(regaddr); + * data = data & (~mask); + * rsb_write(regaddr, data); + * + * rsb set bits internal: + * data = rsb_read(addr); + * data = data | mask; + * rsb_write(addr, data); + * + */ +int rsb_bits_ops_sync(uint32_t *paras) +{ + int result; + struct arisc_message *pmessage; + + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + /* initialize message */ + pmessage->type = ARISC_RSB_BITS_OPS_SYNC; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + memcpy((void *)pmessage->paras, (const void *)paras, sizeof(pmessage->paras)); + + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +/** + * rsb set interface mode. + * @devaddr: rsb slave device address; + * @regaddr: register address of rsb slave device; + * @data: data which to init rsb slave device interface mode; + * + * return: result, 0 - set interface mode successed, + * !0 - set interface mode failed; + */ +int arisc_rsb_set_interface_mode(uint32_t devaddr, uint32_t regaddr, uint32_t data) +{ + int result; + struct arisc_message *pmessage; + + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_RSB_SET_INTERFACE_MODE; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* + * package address and data to message->paras, + * message->paras data layout: + * |para[0]|para[1]|para[2]| + * |devaddr|regaddr|data | + */ + pmessage->paras[0] = devaddr; + pmessage->paras[1] = regaddr; + pmessage->paras[2] = data; + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} + +/** + * rsb set runtime slave address. + * @devaddr: rsb slave device address; + * @rtsaddr: rsb slave device's runtime slave address; + * + * return: result, 0 - set rsb runtime address successed, + * !0 - set rsb runtime address failed; + */ +int arisc_rsb_set_rtsaddr(uint32_t devaddr, uint32_t rtsaddr) +{ + int result; + struct arisc_message *pmessage; + + /* check audio codec has been initialized */ + if (devaddr == RSB_DEVICE_SADDR7) { + if (audio_codec_init) + return 0; + else + audio_codec_init = 1; + } + + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_RSB_SET_RTSADDR; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + /* + * package address and data to message->paras, + * message->paras data layout: + * |para[0]|para[1]| + * |devaddr|rtsaddr| + */ + pmessage->paras[0] = devaddr; + pmessage->paras[1] = rtsaddr; + /* send message use hwmsgbox */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* free message */ + result = pmessage->result; + arisc_message_free(pmessage); + + return result; +} +#endif diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_standby.c b/plat/sun50iw1p1/scp/interfaces/arisc_standby.c new file mode 100644 index 0000000..d570ddf --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/arisc_standby.c @@ -0,0 +1,286 @@ +/* + * drivers/arisc/interfaces/arisc_standby.c + * + * Copyright (c) 2012 Allwinner. + * 2012-10-01 Written by superm (superm@allwinnertech.com). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../arisc_i.h" + +/* record super-standby wakeup event */ +static unsigned long wakeup_event = 0; +static unsigned long dram_crc_error = 0; +static unsigned long dram_crc_total_count = 0; +static unsigned long dram_crc_error_count = 0; + +/** + * cpu operations. + * @mpidr: cpu id; + * @entrypoint: cpu resume entrypoint; + * @cpu_state: cpu state; + * @cluster_state: cluster state; + * + * return: result, 0 - cpu operations successed, + * !0 - cpu operations failed; + */ +int arisc_cpu_op(uint32_t mpidr, uint32_t entrypoint, arisc_power_state_t cpu_state, + arisc_power_state_t cluster_state) +{ + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(0); + if (pmessage == NULL) { + ARISC_ERR("allocate message for cpu op request failed\n"); + return -ENOMEM; + } + + pmessage->type = ARISC_CPU_OP_REQ; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + pmessage->paras[0] = mpidr; + pmessage->paras[1] = entrypoint; + pmessage->paras[2] = cpu_state; + pmessage->paras[3] = cluster_state; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + + /* send enter cpu operations request to arisc */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + return 0; +} + + /** + * system operations. + * @state: system state; + * + * return: result, 0 - system operations successed, + * !0 - system operations failed; + */ +int arisc_system_op(arisc_system_state_t state) +{ + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(0); + if (pmessage == NULL) { + ARISC_ERR("allocate message for sys op request failed\n"); + return -ENOMEM; + } + + pmessage->type = ARISC_SYS_OP_REQ; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + pmessage->paras[0] = state; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + + /* send enter sys operations request to arisc */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + return 0; +} + +/* + * enter cpu idle. + * @para: parameter for enter cpu idle. + * para->flag: 0x01-clear pending, 0x10-enter cpuidle + * para->resume_addr: the address cpu0 will run when exit idle + * + * return: result, 0 - super standby successed, + * !0 - super standby failed; + */ +int arisc_enter_cpuidle(arisc_cb_t cb, void *cb_arg, struct sunxi_enter_idle_para *para) +{ + struct arisc_message *pmessage; /* allocate a message frame */ + pmessage = arisc_message_allocate(0); + if (pmessage == NULL) { + ARISC_ERR("allocate message for super-standby request failed\n"); + return -ENOMEM; + } + pmessage->type = ARISC_CPUIDLE_ENTER_REQ; + pmessage->cb.handler = cb; + pmessage->cb.arg = cb_arg; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->paras[0] = para->flags; + pmessage->paras[1] = (unsigned long)para->resume_addr; + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + return 0; +} + +/** + * query super-standby wakeup source. + * @para: point of buffer to store wakeup event informations. + * + * return: result, 0 - query successed, + * !0 - query failed; + */ +int arisc_query_wakeup_source(uint32_t *event) +{ + *event = wakeup_event; + + return 0; +} + +/* + * query super-standby infoation. + * @para: point of array to store power states informations during sst. + * @op: 0:read, 1:set + * + * return: result, 0 - query successed, + * !0 - query failed; + */ +int arisc_query_set_standby_info(struct standby_info_para *para, arisc_rw_type_e op) +{ + struct arisc_message *pmsg; + int result; + + /* allocate a message frame */ + pmsg = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmsg == NULL) { + ARISC_ERR("allocate message for query standby info failed\n"); + return -ENOMEM; + } + + /* check standby_info_para size valid or not */ + if (sizeof(struct standby_info_para) > sizeof(pmsg->paras)) { + ARISC_ERR("standby info parameters number too long\n"); + return -EINVAL; + } + + /* initialize message */ + pmsg->type = ARISC_STANDBY_INFO_REQ; + pmsg->cb.handler = NULL; + pmsg->cb.arg = NULL; + pmsg->private = (void *)op; + if (ARISC_WRITE == op) { + memcpy((void *)pmsg->paras, (const void *)para, sizeof(struct standby_info_para)); + } + pmsg->state = ARISC_MESSAGE_INITIALIZED; + + /* send query sst info request to arisc */ + arisc_hwmsgbox_send_message(pmsg, ARISC_SEND_MSG_TIMEOUT); + if (ARISC_READ == op) + memcpy((void *)para, (void *)pmsg->paras, sizeof(struct standby_info_para)); + + /* free message */ + result = pmsg->result; + arisc_message_free(pmsg); + + return result; +} + +/* + * query super-standby dram crc result. + * @para: point of buffer to store dram crc result informations. + * + * return: result, 0 - query successed, + * !0 - query failed; + */ +int arisc_query_dram_crc_result(unsigned long *perror, unsigned long *ptotal_count, + unsigned long *perror_count) +{ + *perror = dram_crc_error; + *ptotal_count = dram_crc_total_count; + *perror_count = dram_crc_error_count; + + return 0; +} + +int arisc_set_dram_crc_result(unsigned long error, unsigned long total_count, + unsigned long error_count) +{ + dram_crc_error = error; + dram_crc_total_count = total_count; + dram_crc_error_count = error_count; + + return 0; +} + +/** + * notify arisc cpux restored. + * @para: none. + * + * return: result, 0 - notify successed, !0 - notify failed; + */ +int arisc_cpux_ready_notify(void) +{ + struct arisc_message *pmessage; + + /* notify hwspinlock and hwmsgbox resume first */ + arisc_hwmsgbox_standby_resume(); + arisc_hwspinlock_standby_resume(); + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + + /* initialize message */ + pmessage->type = ARISC_SSTANDBY_RESTORE_NOTIFY; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + + /* record wakeup event */ + wakeup_event = pmessage->paras[0]; + if (arisc_debug_dram_crc_en) { + dram_crc_error = pmessage->paras[1]; + dram_crc_total_count++; + dram_crc_error_count += (dram_crc_error ? 1 : 0); + } + + /* free message */ + arisc_message_free(pmessage); + + return 0; +} + +int arisc_config_ir_paras(uint32_t ir_code, uint32_t ir_addr) +{ + int result = 0; + struct arisc_message *pmessage; + + /* allocate a message frame */ + pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN); + if (pmessage == NULL) { + ARISC_WRN("allocate message failed\n"); + return -ENOMEM; + } + /* initialize message */ + pmessage->type = ARISC_SET_IR_PARAS; + pmessage->paras[0] = ir_code; + pmessage->paras[1] = ir_addr; + pmessage->state = ARISC_MESSAGE_INITIALIZED; + pmessage->cb.handler = NULL; + pmessage->cb.arg = NULL; + + ARISC_INF("ir power key:0x%x, addr:0x%x\n", ir_code, ir_addr); + + /* send request message */ + arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); + if (pmessage->result) { + ARISC_WRN("config ir power key code [%d] fail\n", pmessage->paras[0]); + result = -EINVAL; + } + + /* free allocated message */ + arisc_message_free(pmessage); + + return result; +} diff --git a/plat/sun50iw1p1/scp/interfaces/interfaces.mk b/plat/sun50iw1p1/scp/interfaces/interfaces.mk new file mode 100644 index 0000000..1571046 --- /dev/null +++ b/plat/sun50iw1p1/scp/interfaces/interfaces.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +BL31_SOURCES += plat/sun50iw1p1/scp/interfaces/arisc_loopback.c \ + plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c \ + plat/sun50iw1p1/scp/interfaces/arisc_rsb.c\ + plat/sun50iw1p1/scp/interfaces/arisc_axp.c \ + plat/sun50iw1p1/scp/interfaces/arisc_standby.c \ + plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c \ + plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c |