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; }
static ssize_t ar100_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)) || ((dram_crc_srcaddr < 0x40000000) || (dram_crc_srcaddr > 0xc0000000)) || ((dram_crc_len < 0) || (dram_crc_len > (0x80000000)))) { AR100_WRN("invalid ar100 debug dram crc paras [%x] [%x] [%x] to set\n", dram_crc_en, dram_crc_srcaddr, dram_crc_len); return size; } ar100_debug_dram_crc_en = dram_crc_en; ar100_debug_dram_crc_srcaddr = dram_crc_srcaddr; ar100_debug_dram_crc_len = dram_crc_len; ar100_set_dram_crc_paras(ar100_debug_dram_crc_en, ar100_debug_dram_crc_srcaddr, ar100_debug_dram_crc_len); AR100_LOG("dram_crc_en=0x%x, dram_crc_srcaddr=0x%x, dram_crc_len=0x%x\n", ar100_debug_dram_crc_en, ar100_debug_dram_crc_srcaddr, ar100_debug_dram_crc_len); return size; }
/* * set target frequency. * @freq: target frequency to be set, based on KHZ; * @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 ar100_dvfs_set_cpufreq(unsigned int freq, unsigned long mode, ar100_cb_t cb, void *cb_arg) { unsigned int msg_attr = 0; struct ar100_message *pmessage; int result = 0; if (mode & AR100_DVFS_SYN) { msg_attr |= AR100_MESSAGE_ATTR_HARDSYN; } /* allocate a message frame */ pmessage = ar100_message_allocate(msg_attr); if (pmessage == NULL) { AR100_WRN("allocate message failed\n"); return -ENOMEM; } /* initialize message */ pmessage->type = AR100_CPUX_DVFS_REQ; pmessage->paras[0] = freq; pmessage->state = AR100_MESSAGE_INITIALIZED; pmessage->cb.handler = cb; pmessage->cb.arg = cb_arg; AR100_INF("ar100 dvfs request : %d\n", freq); ar100_hwmsgbox_send_message(pmessage, AR100_SEND_MSG_TIMEOUT); /* dvfs mode : syn or not */ if (mode & AR100_DVFS_SYN) { result = pmessage->result; ar100_message_free(pmessage); } return result; }
static ssize_t ar100_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 != 57600) && (value != 9600)) { AR100_WRN("invalid ar100 uart baudrate [%d] to set\n", value); return size; } ar100_debug_baudrate = value; ar100_set_uart_baudrate(ar100_debug_baudrate); AR100_LOG("debug_baudrate change to %d\n", ar100_debug_baudrate); return size; }
static ssize_t ar100_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)) { AR100_WRN("invalid ar100 debug mask [%d] to set\n", value); return size; } ar100_debug_level = value; ar100_set_debug_level(ar100_debug_level); AR100_LOG("debug_mask change to %d\n", ar100_debug_level); return size; }
static ssize_t ar100_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)) || (total_count < 0) || (error_count < 0)) { AR100_WRN("invalid ar100 dram crc result [%d] [%d] [%d] to set\n", error, total_count, error_count); return size; } ar100_debug_dram_crc_error = error; ar100_debug_dram_crc_total_count = total_count; ar100_debug_dram_crc_error_count = error_count; ar100_set_dram_crc_result((unsigned long)ar100_debug_dram_crc_error, (unsigned long)ar100_debug_dram_crc_total_count, (unsigned long)ar100_debug_dram_crc_error_count); AR100_LOG("debug_dram_crc_result change to error:%u total count:%u error count:%u\n", ar100_debug_dram_crc_error, ar100_debug_dram_crc_total_count, ar100_debug_dram_crc_error_count); return size; }
static int sun6i_ar100_probe(struct platform_device *pdev) { int binary_len; script_item_u script_val; script_item_value_type_e type; AR100_INF("ar100 initialize\n"); /* * request ar100 resources: * p2wi/uart gpio... */ sw_gpio_setcfg(GPIOL(0), 3); /* p2wi sck */ sw_gpio_setcfg(GPIOL(1), 3); /* p2wi sda */ type = script_get_item("cpus_config_paras", "cpus_uart_debug_used", &script_val); if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { AR100_WRN("ar100 uart debug config type err!"); script_val.val = 1; } if (script_val.val) { sw_gpio_setcfg(GPIOL(2), 2); /* uart tx */ sw_gpio_setcfg(GPIOL(3), 2); /* uart rx */ } AR100_INF("ar100 uart debug config [%s] [%s] : %d\n", "cpus_config_paras", "cpus_uart_debug_used", script_val.val); AR100_INF("sram_a2 vaddr(%x)\n", (unsigned int)ar100_sram_a2_vbase); /* clear sram_a2 area */ memset((void *)ar100_sram_a2_vbase, 0, AW_SRAM_A2_SIZE); /* load ar100 system binary data to sram_a2 */ binary_len = 0x13000; memcpy((void *)ar100_sram_a2_vbase, (void *)(&ar100_binary_start), binary_len); printk("move ar100 binary data [addr = %x, len = %x] to sram_a2 finished\n", (unsigned int)(&ar100_binary_start), (unsigned int)binary_len); /* initialize hwspinlock */ AR100_INF("hwspinlock initialize\n"); ar100_hwspinlock_init(); /* initialize hwmsgbox */ AR100_INF("hwmsgbox initialize\n"); ar100_hwmsgbox_init(); /* initialize message manager */ AR100_INF("message manager initialize\n"); ar100_message_manager_init(); /* set ar100 cpu reset to de-assert state */ AR100_INF("set ar100 reset to de-assert state\n"); { volatile unsigned long value; value = readl((IO_ADDRESS(AW_R_CPUCFG_BASE) + 0x0)); value |= 1; writel(value, (IO_ADDRESS(AW_R_CPUCFG_BASE) + 0x0)); } /* wait ar100 ready */ AR100_INF("wait ar100 ready....\n"); if (ar100_wait_ready(10000)) { AR100_LOG("ar100 startup failed\n"); } /* enable ar100 asyn tx interrupt */ ar100_hwmsgbox_enable_receiver_int(AR100_HWMSGBOX_AR100_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327); /* enable ar100 syn tx interrupt */ ar100_hwmsgbox_enable_receiver_int(AR100_HWMSGBOX_AR100_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327); /* config dvfs v-f table */ if (ar100_dvfs_cfg_vf_table()) { AR100_WRN("config dvfs v-f table failed\n"); } /* config dram config paras */ if (ar100_config_dram_paras()) { AR100_WRN("config dram paras failed\n"); } /* config ir config paras */ if (ar100_config_ir_paras()) { AR100_WRN("config ir paras failed\n"); } /* config pmu config paras */ if (ar100_config_pmu_paras()) { AR100_WRN("config pmu paras failed\n"); } #ifdef CONFIG_PM atomic_set(&ar100_suspend_flag, 0); #endif /* ar100 initialize succeeded */ AR100_INF("ar100 startup succeeded, driver version : %d\n", AR100_VERSIONS); return 0; }
int ar100_dvfs_cfg_vf_table(void) { u32 value = 0; int index = 0; int result = 0; int vf_table_size = 0; char vf_table_key[256]; struct ar100_message *pmessage; /* parse system config v-f table information */ if (ar100_dvfs_get_cfg("dvfs_table", "LV_count", &vf_table_size)) { AR100_WRN("parse system config dvfs_table size fail\n"); } for (index = 0; index < vf_table_size; index++) { sprintf(vf_table_key, "LV%d_freq", index + 1); if (ar100_dvfs_get_cfg("dvfs_table", vf_table_key, &value) == 0) { ar100_vf_table[index].freq = value; } sprintf(vf_table_key, "LV%d_volt", index + 1); if (ar100_dvfs_get_cfg("dvfs_table", vf_table_key, &value) == 0) { if (value > 1400) { /* cpu_vdd must < 1.4V */ AR100_WRN("v-f table voltage [%d] > 1400mV\n", value); value = 1400; } ar100_vf_table[index].voltage = value; } } /* allocate a message frame */ pmessage = ar100_message_allocate(AR100_MESSAGE_ATTR_HARDSYN); if (pmessage == NULL) { AR100_WRN("allocate message failed\n"); return -ENOMEM; } for (index = 0; index < AR100_DVFS_VF_TABLE_MAX; index++) { /* initialize message */ pmessage->type = AR100_CPUX_DVFS_CFG_VF_REQ; pmessage->paras[0] = index; pmessage->paras[1] = ar100_vf_table[index].freq; pmessage->paras[2] = ar100_vf_table[index].voltage; pmessage->paras[3] = ar100_vf_table[index].axi_div; pmessage->state = AR100_MESSAGE_INITIALIZED; pmessage->cb.handler = NULL; pmessage->cb.arg = NULL; AR100_INF("v-f table: index %d freq %d vol %d axi_div %d\n", pmessage->paras[0], pmessage->paras[1], pmessage->paras[2], pmessage->paras[3]); /* send request message */ ar100_hwmsgbox_send_message(pmessage, AR100_SEND_MSG_TIMEOUT); //check config fail or not if (pmessage->result) { AR100_WRN("config dvfs v-f table [%d] fail\n", index); result = -EINVAL; break; } } /* free allocated message */ ar100_message_free(pmessage); return result; }