static ssize_t arisc_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 freq = 0; u32 pll = 0; u32 mode = 0; u32 ret = 0; sscanf(buf, "%u %u", &pll, &freq); #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) if ((pll != 1) || (freq < 0) || (freq > 3000000)) { ARISC_WRN("invalid pll [%u] or freq [%u] to set, this platform only support pll1, freq [0, 3000000]KHz\n", pll, freq); ARISC_WRN("pls echo like that: echo pll freq > freq\n"); return size; } #elif (defined CONFIG_ARCH_SUN9IW1P1) || (defined CONFIG_ARCH_SUN8IW6P1) if (((pll != 1) && (pll != 2)) || (freq < 0) || (freq > 3000000)) { ARISC_WRN("invalid pll [%u] or freq [%u] to set, this platform only support pll1 and pll2, freq [0, 3000000]KHz\n", pll, freq); ARISC_WRN("pls echo like that: echo pll freq > freq\n"); return size; } #endif arisc_pll = pll; ret = arisc_dvfs_set_cpufreq(freq, pll, mode, NULL, NULL); if (ret) { ARISC_ERR("pll%u freq set to %u fail\n", pll, freq); } else { ARISC_LOG("pll%u freq set to %u success\n", pll, freq); } return size; }
static ssize_t arisc_p2wi_write_block_data_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 ret; sscanf(buf, "%x %x", (u32 *)®addr, (u32 *)&data); if ((regaddr < 0) || (regaddr > 0xff)) { ARISC_WRN("invalid p2wi paras, regaddr:0x%x, data:0x%x\n", regaddr, data); ARISC_WRN("pls echo like that: echo regaddr data > p2wi_write_block_data\n"); return size; } block_cfg.msgattr = ARISC_MESSAGE_ATTR_SOFTSYN; block_cfg.len = 1; block_cfg.addr = ®addr; block_cfg.data = &data; ret = arisc_p2wi_write_block_data(&block_cfg); if (ret) { ARISC_WRN("p2wi write data:0x%x to regaddr:0x%x fail\n", *block_cfg.data, *block_cfg.addr); } else { ARISC_LOG("p2wi write data:0x%x to regaddr:0x%x success\n", *block_cfg.data, *block_cfg.addr); } return size; }
static ssize_t arisc_rsb_write_block_data_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 ret = 0; sscanf(buf, "%x %x %x %x", &devaddr, (u32 *)®addr, (u32 *)&data, &datatype); if ((devaddr > 0xff) || ((datatype != RSB_DATA_TYPE_BYTE) && (datatype != RSB_DATA_TYPE_HWORD) && (datatype != RSB_DATA_TYPE_WORD))) { ARISC_WRN("invalid rsb paras, devaddr:0x%x, regaddr:0x%x, data:0x%x, datatype:0x%x\n", devaddr, regaddr, data, datatype); ARISC_WRN("pls echo like that: echo devaddr regaddr data datatype > rsb_write_block_data\n"); return size; } block_cfg.msgattr = ARISC_MESSAGE_ATTR_SOFTSYN; block_cfg.datatype = datatype; block_cfg.len = 1; block_cfg.devaddr = devaddr; block_cfg.regaddr = ®addr; block_cfg.data = &data; ret = arisc_rsb_write_block_data(&block_cfg); if (ret) { ARISC_ERR("rsb write data:0x%x to devaddr:0x%x regaddr:0x%x fail\n", *block_cfg.data, block_cfg.devaddr, *block_cfg.regaddr); } else { ARISC_LOG("rsb write data:0x%x to devaddr:0x%x regaddr:0x%x success\n", *block_cfg.data, block_cfg.devaddr, *block_cfg.regaddr); } return size; }
static ssize_t arisc_p2wi_write_block_data_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t size = 0; u32 ret = 0; if ((block_cfg.addr == NULL) || (block_cfg.data == NULL) || (*block_cfg.addr < 0) || (*block_cfg.addr > 0xff)) { ARISC_WRN("invalid p2wi paras, regaddr:0x%x, data:0x%x\n", block_cfg.addr ? *block_cfg.addr : 0, block_cfg.data ? *block_cfg.data : 0); ARISC_LOG("pls echo like that: echo regaddr data > p2wi_write_block_data\n"); return size; } block_cfg.msgattr = ARISC_MESSAGE_ATTR_SOFTSYN; block_cfg.len = 1; block_cfg.addr = ®addr; block_cfg.data = &data; ret = arisc_p2wi_read_block_data(&block_cfg); if (ret) { ARISC_WRN("p2wi read data:0x%x from regaddr:0x%x fail\n", *block_cfg.data, *block_cfg.addr); } else { ARISC_LOG("p2wi read data:0x%x from regaddr:0x%x success\n", *block_cfg.data, *block_cfg.addr); } size = sprintf(buf, "%x\n", data); return size; }
/** * 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; }
static ssize_t arisc_dram_crc_paras_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 dram_crc_en = 0; u32 dram_crc_srcaddr = 0; u32 dram_crc_len = 0; sscanf(buf, "%x %x %x\n", &dram_crc_en, &dram_crc_srcaddr, &dram_crc_len); if ((dram_crc_en != 0) && (dram_crc_en != 1)) { ARISC_WRN("invalid arisc debug dram crc paras [%x] [%x] [%x] to set\n", dram_crc_en, dram_crc_srcaddr, dram_crc_len); return size; } arisc_debug_dram_crc_en = dram_crc_en; arisc_debug_dram_crc_srcaddr = dram_crc_srcaddr; arisc_debug_dram_crc_len = dram_crc_len; arisc_set_dram_crc_paras(arisc_debug_dram_crc_en, arisc_debug_dram_crc_srcaddr, arisc_debug_dram_crc_len); ARISC_LOG("dram_crc_en=0x%x, dram_crc_srcaddr=0x%x, dram_crc_len=0x%x\n", arisc_debug_dram_crc_en, arisc_debug_dram_crc_srcaddr, arisc_debug_dram_crc_len); return size; }
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; }
static ssize_t arisc_rsb_read_block_data_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { sscanf(buf, "%x %x %x", &devaddr, (u32 *)®addr, &datatype); if ((devaddr > 0xff) || ((datatype != RSB_DATA_TYPE_BYTE) && (datatype != RSB_DATA_TYPE_HWORD) && (datatype != RSB_DATA_TYPE_WORD))) { ARISC_WRN("invalid rsb paras to set, devaddr:0x%x, regaddr:0x%x, datatype:0x%x\n", devaddr, regaddr, datatype); ARISC_WRN("pls echo like that: echo devaddr regaddr datatype > rsb_read_block_data\n"); return size; } block_cfg.msgattr = ARISC_MESSAGE_ATTR_SOFTSYN; block_cfg.datatype = datatype; block_cfg.len = 1; block_cfg.devaddr = devaddr; block_cfg.regaddr = ®addr; block_cfg.data = &data; ARISC_LOG("rsb read data from devaddr:0x%x regaddr:0x%x\n", devaddr, regaddr); return size; }
static ssize_t arisc_rsb_write_block_data_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t size = 0; u32 ret = 0; if ((block_cfg.regaddr == NULL) || (block_cfg.data == NULL) || (block_cfg.devaddr > 0xff) || ((block_cfg.datatype != RSB_DATA_TYPE_BYTE) && (block_cfg.datatype != RSB_DATA_TYPE_HWORD) && (block_cfg.datatype != RSB_DATA_TYPE_WORD))) { ARISC_WRN("invalid rsb paras, devaddr:0x%x, regaddr:0x%x, datatype:0x%x\n", block_cfg.devaddr, block_cfg.regaddr ? *block_cfg.regaddr : 0, block_cfg.datatype); ARISC_WRN("pls echo like that: echo devaddr regaddr data datatype > rsb_write_block_data\n"); return size; } ret = arisc_rsb_read_block_data(&block_cfg); if (ret) { ARISC_ERR("rsb read data:0x%x from devaddr:0x%x regaddr:0x%x fail\n", *block_cfg.data, block_cfg.devaddr, *block_cfg.regaddr); } else { ARISC_LOG("rsb read data:0x%x from devaddr:0x%x regaddr:0x%x success\n", *block_cfg.data, block_cfg.devaddr, *block_cfg.regaddr); } size = sprintf(buf, "%x\n", data); return size; }
static ssize_t arisc_debug_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 value = 0; sscanf(buf, "%u", &value); if ((value < 0) || (value > 3)) { ARISC_WRN("invalid arisc debug mask [%d] to set\n", value); return size; } arisc_debug_level = value; arisc_set_debug_level(arisc_debug_level); ARISC_LOG("debug_mask change to %d\n", arisc_debug_level); return size; }
static ssize_t arisc_debug_baudrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 value = 0; sscanf(buf, "%u", &value); if ((value != 115200) && (value != 57600) && (value != 9600)) { ARISC_WRN("invalid arisc uart baudrate [%d] to set\n", value); return size; } arisc_debug_baudrate = value; arisc_set_uart_baudrate(arisc_debug_baudrate); ARISC_LOG("debug_baudrate change to %d\n", arisc_debug_baudrate); return size; }
/** * 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; }
static ssize_t arisc_p2wi_read_block_data_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { sscanf(buf, "%x", (u32 *)®addr); if ((regaddr < 0) || (regaddr > 0xff)) { ARISC_WRN("invalid p2wi paras, regaddr:0x%x\n", regaddr); ARISC_LOG("pls echo like that: echo regaddr > p2wi_read_block_data\n"); return size; } block_cfg.msgattr = ARISC_MESSAGE_ATTR_SOFTSYN; block_cfg.len = 1; block_cfg.addr = ®addr; block_cfg.data = &data; ARISC_LOG("p2wi read regaddr:0x%x\n", *block_cfg.addr); return size; }
/** * 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; }
static ssize_t arisc_dram_crc_result_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { u32 error = 0; u32 total_count = 0; u32 error_count = 0; sscanf(buf, "%u %u %u", &error, &total_count, &error_count); if ((error != 0) && (error != 1)) { ARISC_WRN("invalid arisc dram crc result [%d] [%d] [%d] to set\n", error, total_count, error_count); return size; } arisc_debug_dram_crc_error = error; arisc_debug_dram_crc_total_count = total_count; arisc_debug_dram_crc_error_count = error_count; arisc_set_dram_crc_result((unsigned long)arisc_debug_dram_crc_error, (unsigned long)arisc_debug_dram_crc_total_count, (unsigned long)arisc_debug_dram_crc_error_count); ARISC_LOG("debug_dram_crc_result change to error:%u total count:%u error count:%u\n", arisc_debug_dram_crc_error, arisc_debug_dram_crc_total_count, arisc_debug_dram_crc_error_count); return size; }
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; }
/** * 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 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 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; }