/******************************************************************** DHL_SYS_Impl.c PHOENIX Driver HAL library System init/gpio/pinconfig implementation Copyright 2006 Digital STREAM Technology, Inc. All Rights Reserved $Id: DHL_SYS.c v1.00 2006/04 cafrii Exp $ ********************************************************************/ #include "DHL_SYS_Impl.h" //#include "DHL_IR_Impl.h" #include "DHL_DBG.h" #include "DHL_Timer.h" //#include "DHL_Timer_Impl.h" #include "DHL_SYS.h" // for GPIO number //#include "DHL_OSAL.h" //#include "DHL_SYS.h" //#include "DHL_Debug.h" //#include "DHL_FE.h" // FE version //#include "DHL_Version.h" //#include "projinc.h" //#include "ministd.h" #include "bsettop.h" #include "bsettop_gpio.h" #include "gist.h" #include "bstd.h" #include "bint.h" #include "bgio.h" #include "bcm_mips_defs.h" #include "bchp_kbd1.h" #include "bchp_gio.h" #include "bchp_irq0.h" #include "bchp_sun_l2.h" #include "bchp_hif_cpu_intr1.h" #include "bchp_aio_misc.h" #include "bchp_timer.h" #include "bchp_misc.h" // for vdac control #include "bchp_sun_top_ctrl.h" #include "bchp_memc_misc_0.h" #include "birw.h" //standby #include "bchp_aon_ctrl.h" #include "bchp_aon_pm_l2.h" #if COMMENT ____Config____(){} #endif //--------------------------------------------------------------- // CONFIG MACRO #define SCRATCH_CMD_BASE BCHP_MEMC_MISC_0_SCRATCH_0 //--------------------------------------------------------------- // GLOBAL #define GPIO_IRQ_MASK(n) (((n) >= 0 && (n) <= 31) ? (1 << (n)) : 0) #if COMMENT ____Var____(){} #endif typedef enum { eDHL_IN_INVALID, eDHL_IN_POWER, eDHL_IN_CHDN, eDHL_IN_CHUP, eDHL_IN_RFM, eDHL_IN_WAKEUP, // generic wakeup message. eDHL_IN_WAKEUP_POWER, // special wakeup message about power button. // power button is special case. we cannot read its state at any time. } DHL_GIO_MSGTYPE; typedef struct { DHL_GIO_MSGTYPE type; //UINT32 mstick; UINT32 cputick; // cafrii 081006, mstick may not be correct for checking time gap. } DHL_GIO_MSG; DHL_OS_MSGQ_ID g_gpio_qid; DHL_OS_TASK_ID g_gpio_tid; // user callback // void (*g_dhl_sys_cb_func)(int type, UINT32 userparam, UINT32 state); UINT32 g_dhl_sys_cb_param; int g_Trace_bDHLGpio; #if COMMENT ____ISR____(){} #endif #if 0 static void dhl_isr_gpio(void *data) { /* in normal state, button gpio is pulled down (0V). if button (ch+,ch-) is pressed, it will be pulled up. (3V). pressed released +------+ | | ----+ +---------- gpio isr is programmed as falling-edge triggerred. */ // read gpio interrupt status. (not data) unsigned int status = ReadReg32(BCHP_GIO_STAT_LO); UINT32 mask = GPIO_IRQ_MASK(GPIO_CH_DN) | GPIO_IRQ_MASK(GPIO_CH_UP) | GPIO_IRQ_MASK(GPIO_CH34_SW_IN); DHL_GIO_MSG msg; int err; //printf("isr: gpio stat %08x\n", status); if (status & mask) { //msg.mstick = dhl_sys_get_ms_tick(); msg.cputick = dhl_sys_get_cpu_tick(); msg.type = eDHL_IN_INVALID; if (status & (1 << GPIO_CH_DN)) { //printf("isr: ch dn %d\n", dhl_sys_gpio_rw(GPIO_CH_DN, 0, 0)); msg.type = eDHL_IN_CHDN; } else if (status & (1 << GPIO_CH_UP)) { //printf("isr: ch up\n", dhl_sys_gpio_rw(GPIO_CH_UP, 0, 0)); msg.type = eDHL_IN_CHUP; } else if (status & (1 << GPIO_CH34_SW_IN)) { //printf("isr: ch %d\n", dhl_sys_gpio_rw(GPIO_CH34_SW_IN, 0, 0) ? 4 : 3); msg.type = eDHL_IN_RFM; } if (msg.type != eDHL_IN_INVALID) { err = DHL_OS_SendMessage(g_gpio_qid, &msg, sizeof(msg)); if (err) printf("!! send msg err %d\n", err); } WriteReg32(BCHP_GIO_STAT_LO, status); /* Reset status */ } } #endif #if 0 static void dhl_isr_power_button(void *data) { /* in normal state, power button is pulled down (0V). if button is pressed, it will be pulled up. (3V). pressed released +------+ | | ----+ +---------- power button cannot be accessed using gpio. power button isr is programmed as rising-edge triggerred and it is fixed!! */ unsigned int status = ReadReg32(BCHP_SUN_L2_CPU_STATUS); DHL_GIO_MSG msg; if (status & BCHP_SUN_L2_CPU_STATUS_AUX_INTR_MASK) { //printf("isr: power_btn\n"); //msg.mstick = dhl_sys_get_ms_tick(); msg.cputick = dhl_sys_get_cpu_tick(); msg.type = eDHL_IN_POWER; DHL_OS_SendMessage(g_gpio_qid, &msg, sizeof(msg)); } WriteReg32(BCHP_SUN_L2_CPU_CLEAR,status); /* Reset status */ } #endif #if COMMENT ____GpioDpc____(){} #endif void dhl_gpio_wakeup_proc(UINT32 nIDTimer, UINT32 param) { if (nIDTimer == eDHL_TIMER_GPIO_DPC) { DHL_GIO_MSG msg; msg.type = param == eDHL_IN_POWER ? eDHL_IN_WAKEUP_POWER : eDHL_IN_WAKEUP; //msg.mstick = dhl_sys_get_ms_tick(); msg.cputick = dhl_sys_get_cpu_tick(); //printf("gpio wakeup %d\n", param); DHL_OS_SendMessage(g_gpio_qid, &msg, sizeof(msg)); } } void dhl_gpio_dpc(DHL_OS_MSGQ_ID qid) { int r; DHL_GIO_MSG msg; // int msgLen; // static int prev_button_state = eDHL_IN_INVALID; // static BOOL prev_switch_state; // int state; if (g_Trace_bDHLGpio) printf("gpio dpc task start. qid %x\n", qid); while (1) { // qid == g_gpio_qid r = DHL_OS_ReceiveMessage(qid, &msg, DHL_TIMEOUT_FOREVER); if (r != 0) { printf("!! gpio_dpc: msg get err %d\n", r); DHL_OS_Delay(DHL_OS_GetTicksPerSecond()); continue; } //printf("gpio_dpc: msg %x\n", msg); // to avoid false input by glitch noise, // we program 2nd dpc using timer. // 10 ms is enough. if (0); else if (msg.type == eDHL_IN_CHDN) { //printf("gpio_dpc: chdn %d, tick %d\n", dhl_sys_gpio_rw(GPIO_CH_DN, 0, 0), msg.mstick); DHL_SYS_StartTimer(eDHL_TIMER_GPIO_DPC, 10, dhl_gpio_wakeup_proc, eDHL_IN_CHDN, TRUE); } else if (msg.type == eDHL_IN_CHUP) { //printf("gpio_dpc: chup %d, tick %d\n", dhl_sys_gpio_rw(GPIO_CH_UP, 0, 0), msg.mstick); DHL_SYS_StartTimer(eDHL_TIMER_GPIO_DPC, 10, dhl_gpio_wakeup_proc, eDHL_IN_CHUP, TRUE); } else if (msg.type == eDHL_IN_RFM) { //printf("gpio_dpc: rfm %d, tick %d\n", dhl_sys_gpio_rw(GPIO_CH34_SW_IN, 0, 0), msg.mstick); DHL_SYS_StartTimer(eDHL_TIMER_GPIO_DPC, 10, dhl_gpio_wakeup_proc, eDHL_IN_RFM, TRUE); } else if (msg.type == eDHL_IN_POWER) { //printf("gpio_dpc: power, tick %d\n", msg.mstick); DHL_SYS_StartTimer(eDHL_TIMER_GPIO_DPC, 10, dhl_gpio_wakeup_proc, eDHL_IN_POWER, TRUE); } else if (msg.type == eDHL_IN_WAKEUP || msg.type == eDHL_IN_WAKEUP_POWER) { if (msg.type == eDHL_IN_WAKEUP_POWER) { dhl_sys_notify_callback(eDHL_SYS_CB_POWER, 0); } #if 0//BKCHECK - °¢°¢ÀÇ callback¿¡¼­ Á÷Á¢ ³Ñ±âµµ·Ï ÇÔ. // this is order of button priority. // if (dhl_sys_gpio_rw(GPIO_CH_UP, 0, 0)) { state = GPIO_CH_UP; } else if (dhl_sys_gpio_rw(GPIO_CH_DN, 0, 0)) { state = GPIO_CH_DN; } else { state = 0; } if (state != prev_button_state) // if state is changed, { // printf("=== button state changed, %d\n", state); prev_button_state = state; // send message.. // at first, send ir task for repeat processing. dhl_ir_send_button_message(state); } #endif #if 0//BKTODO: state = dhl_sys_gpio_rw(GPIO_CH34_SW_IN, 0, 0); if (state != prev_switch_state) { printf("**** switch state changed, %d\n", state); prev_switch_state = state; // gpio value 0: ch 3 // gpio value 1: ch 4 // dhl_sys_notify_callback(eDHL_SYS_CB_RFM, state ? 4 : 3); } #endif } } } void dhl_init_gpio_dpc() { g_gpio_qid = DHL_OS_CreateMessageQueue("gpio", 0, 20, sizeof(DHL_GIO_MSG)); if (g_gpio_qid == 0) { printf("!! ir queue create err\n"); return; } g_gpio_tid = DHL_OS_CreateTask((OS_TASKFUNCTION)dhl_gpio_dpc, "gpio", TASK_PRI_DRV_GPIO, 4096, (SINT32)g_gpio_qid); if (g_gpio_tid == 0) { printf("!! ir task create err\n"); return; } } #if COMMENT ____GPIO____(){} #endif //--------------------------------------------------------------- // GPIO Table #if 0 #define GPIO_PIN_DEF(p) #p, p DHL_GPIO_DESC s_dhl_config_table[] = { //name/gpio#/pad#, reset_LH, PinMode, PinParam // { GPIO_PIN_DEF(GPIO_LED_GREEN), NON_RESET_PIN, GPIO_DIR_OUTPUT, PIN_OUTPUT_LOW, 0, 0 }, { GPIO_PIN_DEF(GPIO_CH_DN), NON_RESET_PIN, GPIO_DIR_INPUT, PIN_OUTPUT_NONE, 0, 0 }, { GPIO_PIN_DEF(GPIO_CH_UP), NON_RESET_PIN, GPIO_DIR_INPUT, PIN_OUTPUT_NONE, 0, 0 }, { GPIO_PIN_DEF(GPIO_CH34_SW_IN), NON_RESET_PIN, GPIO_DIR_INPUT, PIN_OUTPUT_NONE, 0, 0 }, { GPIO_PIN_DEF(GPIO_PATH_CONTROL), NON_RESET_PIN, GPIO_DIR_OUTPUT, PIN_OUTPUT_LOW, 0, 0 }, //{ GPIO_PIN_DEF(GPIO_FLASH_WP), NON_RESET_PIN, GPIO_DIR_INPUT, PIN_OUTPUT_NONE, 0, 0 }, }; int s_dhl_max_num_gpio = sizeof(s_dhl_config_table)/sizeof(DHL_GPIO_DESC); #endif /* configure initial gpio setting. refer buser_input_open() in bsettop_user_io.c. */ BGIO_Pin_Handle hPinMute; BGIO_Pin_Handle hPinChU; BGIO_Pin_Handle hPinChD; BGIO_Pin_Handle hPinChP; static bgpio_t gpioHandle_P; static bgpio_t gpioHandle_CHU; static bgpio_t gpioHandle_CHD; static BGIO_Pin_Handle pinLED_R = NULL; static BGIO_Pin_Handle pinLED_G = NULL; #define BUTTON_KEY_UP 0 #define BUTTON_KEY_DOWN 1 #define BUTTON_KEY_POWER 2 #define BUTTON_KEY_EXIT 3/*janzy@20121115,OSD TimeOut*/ static void dhl_isr_power_button(void *context) { BGIO_PinValue PinValue; BGIO_Pin_Handle hPin = (BGIO_Pin_Handle)context; DHL_GIO_MSG msg; if(BGIO_Pin_GetValue(hPin,&PinValue ) == 0) { if(PinValue == BGIO_PinValue_e0) { //printf("isr: power_btn\n"); //msg.mstick = dhl_sys_get_ms_tick(); msg.cputick = dhl_sys_get_cpu_tick(); msg.type = eDHL_IN_POWER; DHL_OS_SendMessage(g_gpio_qid, &msg, sizeof(msg)); } } } static void aov_ChannelUpButton_callback(void *context) { BGIO_PinValue PinValue; BGIO_Pin_Handle hPin = (BGIO_Pin_Handle)context; // DHL_GIO_MSG msg; int state; if(BGIO_Pin_GetValue(hPin,&PinValue ) == 0) { if(PinValue == BGIO_PinValue_e0) { #if 0// msg.cputick = dhl_sys_get_cpu_tick(); msg.type = eDHL_IN_CHUP; DHL_OS_SendMessage(g_gpio_qid, &msg, sizeof(msg)); #else state = GPIO_CH_UP; //BKTODO: dhl_ir_send_button_message(state); #endif } } } static void aov_ChannelDownButton_callback(void *context) { BGIO_PinValue PinValue; BGIO_Pin_Handle hPin = (BGIO_Pin_Handle)context; // DHL_GIO_MSG msg; int state; if(BGIO_Pin_GetValue(hPin,&PinValue ) == 0) { if(PinValue == BGIO_PinValue_e0) { #if 0 msg.cputick = dhl_sys_get_cpu_tick(); msg.type = eDHL_IN_CHDN; DHL_OS_SendMessage(g_gpio_qid, &msg, sizeof(msg)); #else state = GPIO_CH_DN; //BKTODO: dhl_ir_send_button_message(state); #endif } } } #ifndef WriteReg32 #define WriteReg32(reg,val) BREG_Write32(GetREG(),reg,val) #endif #ifndef ReadReg32 #define ReadReg32(reg) BREG_Read32(GetREG(),reg) #endif static DHL_RESULT dhl_sys_gpio_init(void) { bgpio_settings gpio_settings; BERR_Code err; uint32_t value; if (g_Trace_bDHLGpio) printf("%s: start \n", __FUNCTION__); err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eGpio118,&hPinMute); if (err != BERR_SUCCESS) { hPinMute = NULL; printf("BGIO_PinId_eGpio118 Fail\n"); return DHL_FAIL; } BGIO_Pin_SetType(hPinMute,BGIO_PinType_ePushPull); BGIO_Pin_PushPull_SetValue(hPinMute,BGIO_PinValue_e1); value = ReadReg32(BCHP_SUN_TOP_CTRL_PIN_MUX_PAD_CTRL_8); value &= ~BCHP_SUN_TOP_CTRL_PIN_MUX_PAD_CTRL_8_gpio_118_pad_ctrl_MASK; value |= (BCHP_SUN_TOP_CTRL_PIN_MUX_PAD_CTRL_8_gpio_118_pad_ctrl_PULL_UP << BCHP_SUN_TOP_CTRL_PIN_MUX_PAD_CTRL_8_gpio_118_pad_ctrl_SHIFT); WriteReg32(BCHP_SUN_TOP_CTRL_PIN_MUX_PAD_CTRL_8, value); err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eAgpio06,&hPinChU); if (err != BERR_SUCCESS) { hPinChU = NULL; printf("BGIO_PinId_eAgpio05 Fail\n"); return DHL_FAIL; } err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eAgpio05,&hPinChD); if (err != BERR_SUCCESS) { hPinChD = NULL; printf("BGIO_PinId_eAgpio06 Fail\n"); return DHL_FAIL; } err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eAgpio07,&hPinChP); if (err != BERR_SUCCESS) { hPinChP = NULL; printf("BGIO_PinId_eAgpio07 Fail\n"); return DHL_FAIL; } gpio_settings.type = eGPIO_AStandard; gpio_settings.mode = eGPIO_Input; gpio_settings.intMode = eGPIO_Edge; gpio_settings.user_callback = dhl_isr_power_button; gpio_settings.user_callback_context = hPinChP; gpioHandle_P = bgpio_open(BGIO_PinId_eAgpio07, &gpio_settings); gpio_settings.user_callback = aov_ChannelUpButton_callback; gpio_settings.user_callback_context = hPinChU; gpioHandle_CHU = bgpio_open(BGIO_PinId_eAgpio06, &gpio_settings); gpio_settings.user_callback = aov_ChannelDownButton_callback; gpio_settings.user_callback_context = hPinChD; gpioHandle_CHD = bgpio_open(BGIO_PinId_eAgpio05, &gpio_settings); //LED AON GPIO err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eAgpio04,&pinLED_R); if (err != BERR_SUCCESS) { printf("BGIO_PinId_eAgpio04 Fail\n"); return DHL_FAIL; } err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eAgpio09,&pinLED_G); if (err != BERR_SUCCESS) { printf("BGIO_PinId_eAgpio09 Fail\n"); return DHL_FAIL; } BGIO_Pin_SetType(pinLED_R,BGIO_PinType_ePushPull); BGIO_Pin_SetType(pinLED_G,BGIO_PinType_ePushPull); // dhl_sys_gpio_rw(GPIO_LED_GREEN, TRUE, TRUE); // dhl_sys_gpio_rw(GPIO_AUDIO_UNMUTE, TRUE, TRUE); // dhl_sys_gpio_config(GPIO_LED_GREEN, DHL_GPIO_OUTPUT, 1); // turn on green led. // dhl_sys_gpio_config(GPIO_AUDIO_UNMUTE, DHL_GPIO_OUTPUT, 1); // unmute audio. return DHL_OK; } /* read/write internal api. read: data = dhl_sys_gpio_rw(num, 0, 0); write: dhl_sys_gpio_rw(num, value, 1); */ int dhl_sys_gpio_rw(UINT32 num, int bData, BOOL bWrite) { #if 1// if(bWrite) { if(num == GPIO_LED_GREEN) { if(bData) BGIO_Pin_PushPull_SetValue(pinLED_G,BGIO_PinValue_e1); else BGIO_Pin_PushPull_SetValue(pinLED_G,BGIO_PinValue_e0); }else if(num == GPIO_LED_RED) { if(bData) BGIO_Pin_PushPull_SetValue(pinLED_R,BGIO_PinValue_e1); else BGIO_Pin_PushPull_SetValue(pinLED_R,BGIO_PinValue_e0); }else if(num == GPIO_AUDIO_MUTE) { if(bData) BGIO_Pin_PushPull_SetValue(hPinMute,BGIO_PinValue_e1); else BGIO_Pin_PushPull_SetValue(hPinMute,BGIO_PinValue_e0); }else { printf("!! check gpio %d is not available to write\n", num); } }else { { printf("!! check gpio %d is not available to read\n", num); } } return 0; #else//org UINT32 flag; UINT32 reg, mask; UINT32 value; if (g_Trace_bDHLGpio) printf("%s: %d %d %d\n", __FUNCTION__, num, bData, bWrite); if (num <= 31) { // GPIO LO reg = BCHP_GIO_DATA_LO; mask = (1 << num); } else if (num <= 46) { // GPIO HI reg = BCHP_GIO_DATA_HI; mask = (1 << (num - 32)); } else { printf("!! %s: gpio num %d invalid\n", __FUNCTION__, num); return -1; // gpio num is invalid. } flag = bos_enter_critical(); // replace this with OSAL api.. value = ReadReg32(reg); if (bWrite) { if (bData) { WriteReg32(reg, (value | mask)); } else { WriteReg32(reg, (value & ~mask)); } } bos_exit_critical(flag); // replace this with OSAL api.. if (g_Trace_bDHLGpio) printf("old value: 0x%x\n", value); return ((value & mask) ? 1 : 0); #endif } #if 0 /* RED led is not under control by GPIO. so, provide special routines. */ void dhl_sys_set_red_led(int bOn) { // for green led, use gpio api. // ex: dhl_sys_gpio_rw(GPIO_LED_GREEN, 1, TRUE); // red color is controlled by wake-up module, not GPIO. if (bOn) { // turn on red led. WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32( BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) | BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_led_cntrl_MASK); } else { // turn off red led. WriteReg32(BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1, ReadReg32( BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1) & ~BCHP_SUN_TOP_CTRL_GENERAL_CTRL_1_irw_top_sw_led_cntrl_MASK); } } #endif #if COMMENT ____SysControl____(){} #endif /* reboot system. boot_cmd: #define DHL_BOOTCMD_DOWNLOAD 0x1 #define DHL_BOOTCMD_FUPDATE 0x2 */ void dhl_sys_reset(int boot_cmd) { //BKTODO: test needed //BKNOTE: bcm_main()ÁÖ¼Ò·Î ÇØ¾ß ¿ÇÀºµ¥, À̹ÌÁö ¾÷µ¥ÀÌÆ® µÇ´Â °æ¿ì flash¿¡¼­ ´Ù½Ã ÀоîµéÀÏ Çʿ䰡 ÀÖÀ½.. #define START_S2_ADDR 0x80001000//__start_s2 (bootloader7574/bls2.S) uint32_t val; void (*system_boot)(); system_boot = (void (*)())START_S2_ADDR; bos_sleep(100); bos_enter_critical(); // disable interrupt.. /* clear KBD1 interrupt */ val = BREG_Read32(GetREG(), BCHP_KBD1_STATUS); val &= ~BCHP_KBD1_STATUS_irq_MASK; BREG_Write32(GetREG(), BCHP_KBD1_STATUS, val); /* clear reset history */ BREG_Write32(GetREG(), BCHP_AON_CTRL_RESET_CTRL, BCHP_AON_CTRL_RESET_CTRL_clear_reset_history_MASK); /* reset wake up device */ BREG_Write32(GetREG(), BCHP_AON_PM_L2_CPU_MASK_SET, 0xFFFFFFFF); BREG_Write32(GetREG(), BCHP_AON_PM_L2_CPU_CLEAR, 0xFFFFFFF); system_boot(); } /* test code.. jump to specific address. Shell> dhl_sys_jump 1234 --> exception vector occurrs repeatedly */ void dhl_sys_jump(UINT32 addr) { bos_enter_critical(); ((void (*)())addr)(); } /* go into standby mode. */ void dhl_sys_standby(void) { b_s3_standby(USERIO_ID); /* don't switch task, experimental till figure out the issue */ while (1); } UINT32 dhl_sys_get_clock_freq(int type) { extern unsigned int calc_mips_freq(void); // in bos.c // actually, this is NOT mips freq. this is mips clock counter freq. // clock counter freq is half of mips freq. if (type == 0) // cpu clock return (calc_mips_freq() * 2); #if 0//BKTODO: if (type == 1) // ddr clock { UINT32 val; UINT32 ddr_speed[4] = { 166000000, 200000000, 125000000, 142000000, }; val = ReadReg32(BCHP_SUN_TOP_CTRL_STRAP_VALUE_0); val = BCHP_GET_FIELD_DATA(val, SUN_TOP_CTRL_STRAP_VALUE_0, strap_ddr_speed); return ddr_speed[val & 3]; } #else printf("BKTODO: not yet dhl_sys_get_clock_freq() DDR\n"); #endif return 0; // invalid.. } UINT32 dhl_sys_get_cpu_tick(void) { return bcm_read_cp0($9,0); } UINT32 dhl_sys_cpu_ticks_per_ms(void) { static UINT32 divider; if (divider == 0) divider = dhl_sys_get_clock_freq(0)/2/1000; return divider; } /* note!! allowed range for ms tick is : 0xffffffff/108000 = 39768 ms. and 32bit integer is not multiple of 108000. so, when wrap around occurs, timing is not correct. do not use this api.. 39767 -> 39768 -> 0 -> 1 -> .. ^ ^ ^ ^ |<------>|<----->|<------>| =1 ms <1ms =1ms */ #if 0 static UINT32 g_dhl_tick_high, g_dhl_tick_low; #endif UINT32 dhl_sys_get_ms_tick(void) { // do not use this function for checking timing gap!! // use dhl_sys_get_cpu_tick() directly. #if 1 return dhl_sys_get_cpu_tick()/dhl_sys_cpu_ticks_per_ms(); #else static UINT32 prev_ms_tick; static BOOL first_call = 1; UINT32 tick; UINT32 flag; flag = DHL_OS_LockTask(); tick = bcm_read_cp0($9,0); if (first_call) { prev_ms_tick = tick; first_call = 0; return tick; } else { if (tick < g_dhl_tick_low) { // overflow g_dhl_tick_high++; } g_dhl_tick_low = tick; } DHL_OS_UnlockTask(flag); // if high part is same, calculate #endif } void dhl_sys_config_vdac(BOOL bEnable) { } void dhl_sys_register_callback(void (*cb)(int type, UINT32 param, UINT32 state), UINT32 param) { UINT32 flag; flag = bos_enter_critical(); g_dhl_sys_cb_func = cb; g_dhl_sys_cb_param = param; bos_exit_critical(flag); } /* 'state' has different meanings per 'type'. refer comments in 'type' */ void dhl_sys_notify_callback(int type, UINT32 state) { void (*cb)(int, UINT32, UINT32); UINT32 param; UINT32 flag; flag = bos_enter_critical(); cb = g_dhl_sys_cb_func; param = g_dhl_sys_cb_param; bos_exit_critical(flag); if (cb) (*cb)(type, param, state); } #if COMMENT ____Watchdog____(){} #endif /* comment: there is no way to know whether currently watchdog is running or not. normal timer provides to query current count value. (downcounter) but bcm3543 does not privode a way to know current watchdog count value. however, usually watchdog is used together with watchdog timeout interrupt. in watchdog timeout interrupt occurs, we re-program (restart) watchdog countdown. so, if watchdog timeout interrupt is enabled, we treat that watchdog is running. note that watchdog timeout interrupt can be disabled for test. in this case, above assumption becomes wrong. */ // this is only for test, to know watchdog is really working or not. // if we disable watchdog interrupt, system will reboot after a few second. // same result will occur when we disable system-wide interrupt (like OS_DisableInterrupts()). // void dhl_disable_watchdog_isr() { // just disable watchdog isr. then system will reboot after some time. WriteReg32(BCHP_TIMER_TIMER_IE0, ReadReg32(BCHP_TIMER_TIMER_IE0) & ~BCHP_TIMER_TIMER_IE0_WDINTMASK_MASK); } void dhl_sys_enable_watchdog(BOOL bEnable, UINT32 period) { /* period is watchdog timer timout value. (27MHz clock) maximum value for 3543 is unknown, but refsw used 0x1FFFFFFF. this is equivalent to 19.88 second in 27MHz clock source. if 0 is specified, maximum value will be used. */ #define MAX_WDTIMER_VALUE 0x1FFFFFFF UINT32 flag; flag = DHL_OS_DisableInterrupts(); if (period == 0 || period > MAX_WDTIMER_VALUE) period = MAX_WDTIMER_VALUE; // stop watchdog counter first. // WriteReg32(BCHP_TIMER_TIMER_IE0, ReadReg32(BCHP_TIMER_TIMER_IE0) & ~BCHP_TIMER_TIMER_IE0_WDINTMASK_MASK); WriteReg32(BCHP_TIMER_WDCMD,0xEE00); WriteReg32(BCHP_TIMER_WDCMD,0x00EE); if (bEnable) { // read watchdog chip reset status. check if watchdog is already occurred. if (ReadReg32(BCHP_TIMER_WDCRS) == BCHP_TIMER_WDCRS_WDCR_MASK) { // Clear the reset status register WriteReg32(BCHP_TIMER_WDCRS,BCHP_TIMER_WDCRS_WDCR_MASK); } // this interrupt is already registerred in bsettop_init() and never disabled. // //bint_set_handler(BCHP_HIF_CPU_INTR1_INTR_W0_STATUS_UPG_TMR_CPU_INTR_SHIFT,bsettop_wd_isr,NULL); //bint_enable(BCHP_HIF_CPU_INTR1_INTR_W0_STATUS_UPG_TMR_CPU_INTR_SHIFT,1); // timeout value 1FFFFFFF is about 19.88 second. // after 19.88/2 = 9.9 seconds, watchdog interrupt occurred. // WriteReg32(BCHP_TIMER_WDTIMEOUT, period); // <- 1FFFFFFF WriteReg32(BCHP_TIMER_TIMER_IE0, BCHP_TIMER_TIMER_IE0_WDINTMASK_MASK); WriteReg32(BCHP_TIMER_WDCHIPRST_CNT, 0x800000); // 300 ms // Write start sequence WriteReg32(BCHP_TIMER_WDCMD,0xFF00); WriteReg32(BCHP_TIMER_WDCMD,0x00FF); } DHL_OS_RestoreInterrupts(flag); } #if COMMENT ____Test____(){} #endif /* register read/write test. read: Shell> dhl_sys_reg 0x404000 write: Shell> dhl_sys_reg 0xxxxxxx value 1 */ void dhl_sys_reg(UINT32 regaddr, UINT32 val, BOOL bwrite) { UINT32 new_val; if (regaddr > 0x80000000) { // it seems that regaddr is system address. regaddr = (regaddr & 0x0FFFFFFF); } if (regaddr == 0) { printf("usage: %s regaddr [value] [1:write]\n", __FUNCTION__); return; } if (bwrite) { printf("***** Reg[0x%08x] <== 0x%08x (%d) \n", regaddr, val, val); WriteReg32(regaddr, val); } new_val = ReadReg32(regaddr); printf("***** Reg[0x%08x] = 0x%08x (%d) \n", regaddr, new_val, new_val); } void dhl_sys_test_cb(DHL_SYS_CB_TYPE type, UINT32 param, UINT32 state) { if (type == eDHL_SYS_CB_POWER) { printf("$$$ power\n"); } else if (type == eDHL_SYS_CB_CHUP) { printf("$$$ ch_up %d\n", state); } else if (type == eDHL_SYS_CB_CHDN) { printf("$$$ ch_dn %d\n", state); } else if (type == eDHL_SYS_CB_RFM) { printf("$$$ rfm %d\n", state); } } #if COMMENT ____Init____(){} #endif /* only for 3543!! */ static DHL_SymbolTable s_dhl_sys_symbols[] = { // it will be defined in OSAL. //{ "i", osi_show_taskinfo, DHL_SYM_FN, }, DHL_FNC_SYM_ENTRY(dhl_sys_reset), DHL_FNC_SYM_ENTRY(dhl_sys_standby), // DHL_FNC_SYM_ENTRY(dhl_sys_set_red_led), // { "reset", dhl_sys_standby, DHL_SYM_FN, }, //{ "reboot", dhl_sys_reset, DHL_SYM_FN, }, //{ "watchdog", dhl_sys_enable_watchdog, DHL_SYM_FN, }, //----- //DHL_VAR_SYM_ENTRY(dmc_bRequestVideoWidthReduction), }; void dhl_sys_init(void) { DHL_ASSERT(bsettop_init(BSETTOP_VERSION) == b_ok, ""); // gpio dhl_init_gpio_dpc(); dhl_sys_gpio_init(); //dhl_sys_gpio_rw(GPIO_LED_GREEN, 1, TRUE); // Green LED on. DHL_DBG_RegisterSymbols(s_dhl_sys_symbols, DHL_NUMSYMBOLS(s_dhl_sys_symbols)); // BOOTPRINT(("%s end\n", __FUNCTION__)); }