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; }
/** * 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(struct arisc_rsb_block_cfg *cfg) { int i; int result; struct arisc_message *pmessage; if ((cfg == NULL) || (cfg->devaddr == 0) || (cfg->regaddr == NULL) || (cfg->data == NULL) || (cfg->len > RSB_TRANS_BYTE_MAX) || ((cfg->datatype != RSB_DATA_TYPE_BYTE) && (cfg->datatype != RSB_DATA_TYPE_HWORD) && (cfg->datatype != RSB_DATA_TYPE_WORD)) || ((cfg->msgattr != ARISC_MESSAGE_ATTR_HARDSYN) && (cfg->msgattr != ARISC_MESSAGE_ATTR_SOFTSYN))) { ARISC_WRN("rsb write reg paras error\n"); return -EINVAL; } pmessage = arisc_message_allocate(cfg->msgattr); 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; /* * 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 | */ pmessage->paras[0] = 0; pmessage->paras[1] = 0; pmessage->paras[2] = 0; pmessage->paras[3] = 0; pmessage->paras[5] = 0; pmessage->paras[6] = 0; //memset(pmessage->paras, 0, sizeof(pmessage->paras)); //memset(pmessage->paras, 0, sizeof(unsigned int) * 4); pmessage->paras[0] = ((cfg->len & 0xffff) | ((cfg->datatype << 16) & 0xffff0000)); pmessage->paras[1] = cfg->devaddr; for (i = 0; i < cfg->len; i++) { /* pack 8bit regaddr0~regaddr3 into 32bit paras[1] */ pmessage->paras[2] |= (cfg->regaddr[i] << (i * 8)); /* pack 32bit data0~data3 into 32bit paras[2]~paras[5] */ pmessage->paras[3 + i] = cfg->data[i]; } /* 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(u32 devaddr, u32 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; }
/** * 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(u32 devaddr, u32 regaddr, u32 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 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(struct arisc_rsb_bits_cfg *cfg) { int i; int result; struct arisc_message *pmessage; if ((cfg == NULL) || (cfg->devaddr == 0) || (cfg->regaddr == NULL) || (cfg->mask == NULL) || (cfg->delay == NULL) || (cfg->len > RSB_TRANS_BYTE_MAX) || ((cfg->datatype != RSB_DATA_TYPE_BYTE) && (cfg->datatype != RSB_DATA_TYPE_HWORD) && (cfg->datatype != RSB_DATA_TYPE_WORD)) || ((cfg->msgattr != ARISC_MESSAGE_ATTR_HARDSYN) && (cfg->msgattr != ARISC_MESSAGE_ATTR_SOFTSYN))) { ARISC_WRN("rsb clear bits sync paras error\n"); return -EINVAL; } pmessage = arisc_message_allocate(cfg->msgattr); 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; /* * 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]|para[7] |para[8]| * |(len|datatype)|devaddr|regaddr0~3|mask0 |mask1 |mask2 |mask3 |delay0~3|ops | */ pmessage->paras[0] = 0; pmessage->paras[1] = 0; pmessage->paras[2] = 0; pmessage->paras[3] = 0; pmessage->paras[4] = 0; pmessage->paras[5] = 0; pmessage->paras[6] = 0; pmessage->paras[7] = 0; pmessage->paras[8] = 0; //memset(pmessage->paras, 0, sizeof(pmessage->paras)); //memset(pmessage->paras, 0, sizeof(unsigned int) * 4); pmessage->paras[0] = ((cfg->len & 0xffff) | ((cfg->datatype << 16) & 0xffff0000)); pmessage->paras[1] = cfg->devaddr; pmessage->paras[8] = cfg->ops; for (i = 0; i < cfg->len; i++) { /* pack 8bit regaddr0~regaddr3 into 32bit paras[1] */ pmessage->paras[2] |= (cfg->regaddr[i] << (i * 8)); /* pack 32bit mask0~mask3 into 32bit paras[2] */ pmessage->paras[3 + i] = cfg->mask[i]; /* pack 8bit delay0~delay3 into 32bit paras[6] */ pmessage->paras[7] |= (cfg->delay[i] << (i * 8)); } /* send message use hwmsgbox */ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); /* free message */ result = pmessage->result; arisc_message_free(pmessage); return result; }
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; }