/* * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $Id: time.c,v 1.9 2009-07-17 06:23:12 $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Foxconn added, zacker, 07/04/2009 */ /* Global SB handle */ extern si_t *bcm947xx_sih; extern spinlock_t bcm947xx_sih_lock; /* Convenience */ #define sih bcm947xx_sih #define sih_lock bcm947xx_sih_lock #define WATCHDOG_MIN 3000 /* milliseconds */ extern int panic_timeout; extern int panic_on_oops; static uint32 watchdog = 0; /* Foxconn */ #ifndef CONFIG_HWSIM static u8 *mcr = NULL; #endif /* CONFIG_HWSIM */ /* Foxconn added start */ #define LED_BLINK_RATE_NORMAL 50 #define LED_BLINK_RATE_QUICK 10 int wps_led_pattern = 0; int wps_led_state = 0; /* foxconn added start, zacker, 09/17/2009, @wps_led */ int is_wl_secu_mode = 0; static int wps_led_is_on = 0; /* foxconn added end, zacker, 09/17/2009, @wps_led */ static int wps_led_state_old = 1; static si_t *gpio_sih; static int wps_led_init(void) { if (!(gpio_sih = si_kattach(SI_OSH))) { printk("%s failed!\n", __FUNCTION__); return -ENODEV; } return 0; } static int gpio_control_normal(int pin, int value) { si_gpioreserve(gpio_sih, 1 << pin, GPIO_APP_PRIORITY); si_gpioouten(gpio_sih, 1 << pin, 1 << pin, GPIO_APP_PRIORITY); si_gpioout(gpio_sih, 1 << pin, value << pin, GPIO_APP_PRIORITY); return 0; } #define GPIO_PIN(x) ((x) & 0x00FF) int gpio_led_on_off(int gpio, int value) { int pin = GPIO_PIN(gpio); /* foxconn added start, zacker, 09/17/2009, @wps_led */ if (gpio == WPS_LED_GPIO) wps_led_is_on = !value; /* foxconn added end, zacker, 09/17/2009, @wps_led */ gpio_control_normal(pin, value); return 0; } static void quick_blink2(void) { static int interrupt_count = -1; interrupt_count++; if (interrupt_count == LED_BLINK_RATE_QUICK * 2) interrupt_count = 0; if (interrupt_count == 0) gpio_led_on_off(WPS_LED_GPIO, 0); else if (interrupt_count == LED_BLINK_RATE_QUICK) gpio_led_on_off(WPS_LED_GPIO, 1); } static void quick_blink(void) { /* foxconn modified start, zacker, 09/17/2009, @wps_led */ //static int blink_interval = 3000; /* 30 seconds */ static int blink_interval = 500; /* 5 seconds */ /* foxconn modified end, zacker, 09/17/2009, @wps_led */ static int interrupt_count = -1; blink_interval--; interrupt_count++; if (interrupt_count == LED_BLINK_RATE_QUICK * 2) interrupt_count = 0; if (interrupt_count == 0) gpio_led_on_off(WPS_LED_GPIO, 0); else if (interrupt_count == LED_BLINK_RATE_QUICK) gpio_led_on_off(WPS_LED_GPIO, 1); if ( blink_interval <= 0 ) { /* foxconn modified start, zacker, 09/17/2009, @wps_led */ //blink_interval = 3000; blink_interval = 500; /* foxconn modified end, zacker, 09/17/2009, @wps_led */ wps_led_state = 0; } } static int normal_blink(void) { static int interrupt_count = -1; interrupt_count++; if (interrupt_count == LED_BLINK_RATE_NORMAL * 2) interrupt_count = 0; if (interrupt_count == 0) gpio_led_on_off(WPS_LED_GPIO, 0); else if (interrupt_count == LED_BLINK_RATE_NORMAL) gpio_led_on_off(WPS_LED_GPIO, 1); } static int wps_ap_lockdown_blink(void) { static int interrupt_count = -1; interrupt_count++; if (interrupt_count == LED_BLINK_RATE_QUICK * 10) interrupt_count = 0; if (interrupt_count == 0) gpio_led_on_off(WPS_LED_GPIO, 0); else if (interrupt_count == LED_BLINK_RATE_QUICK) gpio_led_on_off(WPS_LED_GPIO, 1); } /* Foxconn added end */ /* Foxconn added start pling 02/26/2010 */ /* Add USB LED */ #if (defined INCLUDE_USB_LED) /* Foxconn modified start, Wins, 04/11/2011 */ #define GPIO_USB1_LED 8 /* USB1 LED. */ #define GPIO_USB2_LED 14 /* USB2 LED. */ #define LED_BLINK_RATE 5 int usb1_pkt_cnt = 0; int usb2_pkt_cnt = 0; int usb1_led_state = 0; int usb2_led_state = 0; static int usb1_led_state_old = 1; static int usb2_led_state_old = 1; EXPORT_SYMBOL(usb1_pkt_cnt); EXPORT_SYMBOL(usb2_pkt_cnt); EXPORT_SYMBOL(usb1_led_state); EXPORT_SYMBOL(usb2_led_state); /* Foxconn modified end, Wins, 04/11/2011 */ static int gpio_on_off(int gpio_num, int on_off) { si_gpioreserve(gpio_sih, 1 << gpio_num, GPIO_APP_PRIORITY); si_gpioouten(gpio_sih, 1 << gpio_num, 1 << gpio_num, GPIO_APP_PRIORITY); si_gpioout(gpio_sih, 1 << gpio_num, on_off << gpio_num, GPIO_APP_PRIORITY); return 0; } static int usb1_normal_blink(void) { static int interrupt_count1 = -1; static int usb1_pkt_cnt_old = 0; interrupt_count1++; if (interrupt_count1 == LED_BLINK_RATE * 2) interrupt_count1 = 0; if (interrupt_count1 == 0){ /*Foxconn, [MJ], turn off USB_Led. */ gpio_on_off(GPIO_USB1_LED, 0); } else if (interrupt_count1 == LED_BLINK_RATE) { if (usb1_pkt_cnt != usb1_pkt_cnt_old) { usb1_pkt_cnt_old = usb1_pkt_cnt; /*Foxconn, [MJ], turn on USB_Led. */ gpio_on_off(GPIO_USB1_LED, 1); //printk("<1> turn on USB_LED.\n"); } } return 0; } static int usb2_normal_blink(void) { static int interrupt_count2 = -1; static int usb2_pkt_cnt_old = 0; interrupt_count2++; if (interrupt_count2 == LED_BLINK_RATE * 2) interrupt_count2 = 0; if (interrupt_count2 == 0){ /*Foxconn, [MJ], turn off USB_Led. */ gpio_on_off(GPIO_USB2_LED, 0); } else if (interrupt_count2 == LED_BLINK_RATE) { if (usb2_pkt_cnt != usb2_pkt_cnt_old) { usb2_pkt_cnt_old = usb2_pkt_cnt; /*Foxconn, [MJ], turn on USB_Led. */ gpio_on_off(GPIO_USB2_LED, 1); //printk("<1> turn on USB_LED.\n"); } } return 0; } #endif /* Foxconn added end pling 02/26/2010 */ void __init bcm947xx_time_init(void) { unsigned int hz; char cn[8]; /* * Use deterministic values for initial counter interrupt * so that calibrate delay avoids encountering a counter wrap. */ write_c0_count(0); write_c0_compare(0xffff); if (!(hz = si_cpu_clock(sih))) hz = 100000000; bcm_chipname(sih->chip, cn, 8); printk("CPU: BCM%s rev %d at %d MHz\n", cn, sih->chiprev, (hz + 500000) / 1000000); /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ mips_hpt_frequency = hz / 2; /* Set watchdog interval in ms */ watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0); /* Ensure at least WATCHDOG_MIN */ if ((watchdog > 0) && (watchdog < WATCHDOG_MIN)) watchdog = WATCHDOG_MIN; /* Set panic timeout in seconds */ panic_timeout = watchdog / 1000; panic_on_oops = watchdog / 1000; /* Init WLAN LED */ wps_led_init(); /* Foxconn added */ } #ifdef CONFIG_HND_BMIPS3300_PROF extern bool hndprofiling; #ifdef CONFIG_MIPS64 typedef u_int64_t sbprof_pc; #else typedef u_int32_t sbprof_pc; #endif extern void sbprof_cpu_intr(sbprof_pc restartpc); #endif /* CONFIG_HND_BMIPS3300_PROF */ static irqreturn_t bcm947xx_timer_interrupt(int irq, void *dev_id) { #ifdef CONFIG_HND_BMIPS3300_PROF /* * Are there any ExcCode or other mean(s) to determine what has caused * the timer interrupt? For now simply stop the normal timer proc if * count register is less than compare register. */ if (hndprofiling) { sbprof_cpu_intr(read_c0_epc() + ((read_c0_cause() >> (CAUSEB_BD - 2)) & 4)); if (read_c0_count() < read_c0_compare()) return (IRQ_HANDLED); } #endif /* CONFIG_HND_BMIPS3300_PROF */ /* Generic MIPS timer code */ timer_interrupt(irq, dev_id); /* Set the watchdog timer to reset after the specified number of ms */ if (watchdog > 0) si_watchdog_ms(sih, watchdog); #ifdef CONFIG_HWSIM (*((int *)0xa0000f1c))++; #else /* Blink one of the LEDs in the external UART */ if (mcr && !(jiffies % (HZ/2))) writeb(readb(mcr) ^ UART_MCR_OUT2, mcr); #endif /* Foxconn added start */ /* Blink LED depending of WPS status */ if ( wps_led_state == 0 ) { if (wps_led_state_old != 0) gpio_led_on_off(WPS_LED_GPIO, 1); /* foxconn added start, zacker, 09/17/2009, @wps_led */ if ((!is_wl_secu_mode) && wps_led_is_on) gpio_led_on_off(WPS_LED_GPIO, 1); if (is_wl_secu_mode && (!wps_led_is_on)) gpio_led_on_off(WPS_LED_GPIO, 0); /* foxconn added end, zacker, 09/17/2009, @wps_led */ } else if (wps_led_state == 1) { normal_blink(); } else if (wps_led_state == 2) { quick_blink(); } else if (wps_led_state == 3) { quick_blink2(); } else if (wps_led_state == 4) { wps_ap_lockdown_blink(); } wps_led_state_old = wps_led_state; /* Foxconn added end */ /* Foxconn added start pling 02/26/2010 */ /* Blink USB LED if necessary */ #if (defined INCLUDE_USB_LED) /* Foxconn modified start, Wins, 04/11/2011 */ if (usb1_led_state) { usb1_normal_blink(); } else { if (usb1_led_state_old){ /* Foxconn, [MJ], turn on USB1_Led. */ gpio_on_off(GPIO_USB1_LED, 1); } } usb1_led_state_old = usb1_led_state; if (usb2_led_state) { usb2_normal_blink(); } else { if (usb2_led_state_old){ /* Foxconn, [MJ], turn on USB2_Led. */ gpio_on_off(GPIO_USB2_LED, 1); } } usb2_led_state_old = usb2_led_state; /* Foxconn modified end, Wins, 04/11/2011 */ #endif /* Foxconn added end pling 02/26/2010 */ return (IRQ_HANDLED); } static struct irqaction bcm947xx_timer_irqaction = { bcm947xx_timer_interrupt, IRQF_DISABLED, { { 0 } }, "timer", NULL, NULL, 0, NULL }; void __init plat_timer_setup(struct irqaction *irq) { /* Enable the timer interrupt */ setup_irq(7, &bcm947xx_timer_irqaction); }