#include #include #include #include #include #include #include "ar7240_soc.h" extern void ar7240_ddr_initial_config(uint32_t refresh); extern int ar7240_ddr_find_size(void); void ar7240_usb_initial_config(void) { #ifndef CONFIG_HORNET_EMU ar7240_reg_wr_nf(AR7240_USB_PLL_CONFIG, 0x0a04081e); ar7240_reg_wr_nf(AR7240_USB_PLL_CONFIG, 0x0804081e); #endif } #ifdef CONFIG_SHOW_BOOT_PROGRESS int ar7240_boot_status = 0; // Global variable to indicate if boot is succesful // negative values show failure #endif typedef struct reg_conf{ unsigned int addr; unsigned int set_mask; unsigned int clear_mask; }; // Carambola2 GPIO LED definition typedef struct gpio_led_desc { int id; int bit; //GPIO bit int polarity; //1 - high active; 0 - low active int disable; //1 - disable led, 0 - enable }; int led_count=5; struct gpio_led_desc leds[]={ {// WLAN LED .id=0, .bit=0, .polarity=0, .disable=0 }, {// ETH0_LED .id=1, .bit=13, .polarity=1, .disable=0 }, {// ETH1_LED .id=2, .bit=14, .polarity=1, .disable=0 }, {// USB recovery indication .id=3, .bit=0, .polarity=0, .disable=0 }, {// Nothing .id=4, .bit=0, .polarity=0, .disable=1 } }; struct gpio_led_desc buttons[]={ {// USB Boot .id=0, .bit=11, .polarity=0, .disable=0 }, {// Nothing .id=1, .bit=0, .polarity=0, .disable=1 }, {// Nothing .id=2, .bit=0, .polarity=0, .disable=1 }, {// Nothing .id=3, .bit=0, .polarity=0, .disable=1 }, {// Nothing .id=4, .bit=0, .polarity=0, .disable=1 } }; void ar7240_usb_otp_config(void) { unsigned int addr, reg_val, reg_usb; int time_out, status, usb_valid; for (addr = 0xb8114014; ;addr -= 0x10) { status = 0; time_out = 20; reg_val = ar7240_reg_rd(addr); while ((time_out > 0) && (~status)) { if ((( ar7240_reg_rd(0xb8115f18)) & 0x7) == 0x4) { status = 1; } else { status = 0; } time_out--; } reg_val = ar7240_reg_rd(0xb8115f1c); if ((reg_val & 0x80) == 0x80){ usb_valid = 1; reg_usb = reg_val & 0x000000ff; } if (addr == 0xb8114004) { break; } } if (usb_valid) { reg_val = ar7240_reg_rd(0xb8116c88); reg_val &= ~0x03f00000; reg_val |= (reg_usb & 0xf) << 22; ar7240_reg_wr(0xb8116c88, reg_val); } } void assign_gpio(void *data, int item_count1, int* tmp_item) { struct reg_conf *regs; regs = (struct reg_conf*)data; regs[item_count1].addr = tmp_item[0]; regs[item_count1].set_mask = tmp_item[1]; regs[item_count1].clear_mask = tmp_item[2]; return; } void assign_leds(void *data, int item_count1, int* tmp_item) { if (tmp_item[0]<5 && tmp_item[0]>=0){ int id=tmp_item[0]; leds[id].id = id; leds[id].bit = tmp_item[1]; leds[id].polarity = tmp_item[2]; leds[id].disable = tmp_item[3]; } return; } void assign_buttons(void *data, int item_count1, int* tmp_item) { if (tmp_item[0]<5 && tmp_item[0]>=0){ int id=tmp_item[0]; buttons[id].id = id; buttons[id].bit = tmp_item[1]; buttons[id].polarity = tmp_item[2]; buttons[id].disable = tmp_item[3]; } return; } int convert_hex(char* str, int item_nr) { return (simple_strtol(str, NULL, 16)); } int convert_dec(char* str, int item_nr) { return (simple_strtol(str, NULL, 10)); } int count_args(char* env) { char* pos; pos = strchr(env,'/'); unsigned int reg_count=1; while (pos != NULL){ reg_count++; pos = strchr(pos+1,'/'); } return reg_count; } int parse_config(char* env, int max_args, void *regs, int *reg_count, void (*assign)(void*, int, int*), int (*convert)(char*, int) ) { char *tmp_str1, *tmp_str2, *tok1, *tok2; int item_count1=0; int item_count2; int* tmp_item = malloc((sizeof(int))*max_args); if (tmp_item == NULL){ return (-1); } tmp_str1 = strdup(env); tok1=strsep(&tmp_str1, "/"); while (tok1 != NULL){ item_count2=0; tmp_str2 = strdup(tok1); tok2=strsep(&tmp_str2, ":"); while (tok2 != NULL){ item_count2++; if (item_count2 > max_args) break; tmp_item[item_count2-1] = convert(tok2,item_count2); tok2=strsep(&tmp_str2, ":"); } if (item_count2 == max_args){ assign(regs, item_count1, tmp_item); item_count1++; } tok1 = strsep(&tmp_str1, "/"); } *reg_count = item_count1; free(tmp_item); return (0); } void apply_config(struct reg_conf *regs, int reg_count) { int i; for (i=0; i=0x18040000) && (regs[i].addr<=0x18040044)){ ar7240_reg_wr(regs[i].addr, ((ar7240_reg_rd(regs[i].addr)|regs[i].set_mask)&(~regs[i].clear_mask))); } else{ printf("Reg: %x is not in valid GPIO range\n", regs[i].addr); } } return; } void gpio_env_init(int mode) { int max_args; void (*assign)(struct reg_conf*, int, int*); int (*convert)(char* ,int); char* gpio_env; int ret; struct reg_conf *regs; int reg_count; int i; if (mode==0){ assign = &assign_gpio; convert = &convert_hex; max_args = 3; gpio_env = getenv("gpio_config"); } else{ convert = &convert_dec; max_args = 4; if (mode==1){ assign = &assign_leds; gpio_env = getenv("led_config"); } else if(mode == 2){ assign = &assign_buttons; gpio_env = getenv("button_config"); } } if (gpio_env == NULL){ if (mode==0){ //Default init //set output enable ar7240_reg_wr (AR7240_GPIO_OE, (ar7240_reg_rd(AR7240_GPIO_OE) | (1<<13)|(1<<14)|(1<<0) )); //set ETH0 ETH1 LED output to high ar7240_reg_wr (AR7240_GPIO_SET, (1<<13)|(1<<14)); //set WLAN LED output to low (reverse polarity LED) ar7240_reg_wr (AR7240_GPIO_CLEAR, (1<<0)); //Enable USB boot sense GPIO as input ar7240_reg_wr (AR7240_GPIO_OE, (ar7240_reg_rd(AR7240_GPIO_OE) & ~(1<<11))); } return; } reg_count = count_args(gpio_env); if (mode==0){ regs = malloc(sizeof(struct reg_conf)*reg_count); if (regs == NULL) return; } else regs = NULL; ret = parse_config(gpio_env, max_args, (void*)regs, ®_count, assign, convert); if (ret<0) return; if (mode==0) apply_config(regs, reg_count); free(regs); return; } void ar7240_gpio_config(void) { /* Disable clock obs * clk_obs1(gpio13/bit8), clk_obs2(gpio14/bit9), clk_obs3(gpio15/bit10), * clk_obs4(gpio16/bit11), clk_obs5(gpio17/bit12) * clk_obs0(gpio1/bit19), 6(gpio11/bit20) */ ar7240_reg_wr (AR7240_GPIO_FUNC, (ar7240_reg_rd(AR7240_GPIO_FUNC) & ~((0x1f<<8)|(0x3<<19)))); /* Enable eth Switch LEDs */ //ar7240_reg_wr (AR7240_GPIO_FUNC, (ar7240_reg_rd(AR7240_GPIO_FUNC) | (0x1f<<3))); /* Clear AR7240_GPIO_FUNC BIT2 to ensure that software can control LED5(GPIO16) and LED6(GPIO17) */ ar7240_reg_wr (AR7240_GPIO_FUNC, (ar7240_reg_rd(AR7240_GPIO_FUNC) & ~(0x1<<2))); /* Set HORNET_BOOTSTRAP_STATUS BIT18 to ensure that software can control GPIO26 and GPIO27 */ //ar7240_reg_wr (HORNET_BOOTSTRAP_STATUS, (ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) | (0x1<<18))); } int button_read(int button_id){ if (buttons[button_id].disable != 1){ if (((ar7240_reg_rd(AR7240_GPIO_IN)>>buttons[button_id].bit)&0x01) == buttons[button_id].polarity) return 1; else return 0; } else return -1; } #ifdef CONFIG_SHOW_ACTIVITY void ar7240_gpio_led_switch(int led_id, int state) //switch LED (led_id is defined in struct[] leds) to state (0 - off, 1 -on) { int i; for (i=0; i 2) led = 0; ar7240_gpio_led_switch(led ,(time>>24)&0x01); } return; } #endif #ifdef CONFIG_SHOW_BOOT_PROGRESS void show_boot_progress(int arg) { ar7240_boot_status = arg; return; } #endif int ar7240_mem_config(void) { #ifndef COMPRESSED_UBOOT unsigned int tap_val1, tap_val2; #endif ar7240_gpio_config(); // init GPIO ar7240_ddr_initial_config(CFG_DDR_REFRESH_VAL); /* Default tap values for starting the tap_init*/ ar7240_reg_wr (AR7240_DDR_TAP_CONTROL0, CFG_DDR_TAP0_VAL); ar7240_reg_wr (AR7240_DDR_TAP_CONTROL1, CFG_DDR_TAP1_VAL); #ifndef COMPRESSED_UBOOT ar7240_ddr_tap_init(); tap_val1 = ar7240_reg_rd(0xb800001c); tap_val2 = ar7240_reg_rd(0xb8000020); debug("#### TAP VALUE 1 = %x, 2 = %x\n",tap_val1, tap_val2); #endif ar7240_usb_initial_config(); ar7240_usb_otp_config(); //hornet_ddr_tap_init(); return (ar7240_ddr_find_size()); } long int initdram(int board_type) { return (ar7240_mem_config()); } #ifdef COMPRESSED_UBOOT int checkboard (char *board_string) { strcpy(board_string, "sysmocom "CARABOOT_RELEASE" (AR9331) U-boot"); return 0; } #else int checkboard (void) { printf("sysmcom "CARABOOT_RELEASE" (AR9331) U-boot\n"); return 0; } #endif /* #ifdef COMPRESSED_UBOOT */