• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/linux/linux-2.6/arch/mips/brcm-boards/bcm947xx/
1/*
2 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 *
16 * $Id: time.c,v 1.9 2009-07-17 06:23:12 $
17 */
18#include <linux/config.h>
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/sched.h>
22#include <linux/serial_reg.h>
23#include <linux/interrupt.h>
24#include <asm/addrspace.h>
25#include <asm/io.h>
26#include <asm/time.h>
27
28#include <typedefs.h>
29#include <osl.h>
30#include <bcmutils.h>
31#include <bcmnvram.h>
32#include <hndsoc.h>
33#include <sbchipc.h>
34#include <siutils.h>
35#include <hndmips.h>
36#include <mipsinc.h>
37#include <hndcpu.h>
38#include <bcmdevs.h>
39
40#include <wps_led.h> /* Foxconn added, zacker, 07/04/2009 */
41/* Global SB handle */
42extern si_t *bcm947xx_sih;
43extern spinlock_t bcm947xx_sih_lock;
44
45/* Convenience */
46#define sih bcm947xx_sih
47#define sih_lock bcm947xx_sih_lock
48
49#define WATCHDOG_MIN	3000	/* milliseconds */
50extern int panic_timeout;
51extern int panic_on_oops;
52static uint32 watchdog = 0; /* Foxconn */
53
54#ifndef	CONFIG_HWSIM
55static u8 *mcr = NULL;
56#endif /* CONFIG_HWSIM */
57
58/* Foxconn added start */
59#define LED_BLINK_RATE_NORMAL   50
60#define LED_BLINK_RATE_QUICK    10
61
62int wps_led_pattern = 0;
63int wps_led_state = 0;
64
65/* foxconn added start, zacker, 09/17/2009, @wps_led */
66int is_wl_secu_mode = 0;
67static int wps_led_is_on = 0;
68/* foxconn added end, zacker, 09/17/2009, @wps_led */
69static int wps_led_state_old = 1;
70
71static si_t *gpio_sih;
72static int wps_led_init(void)
73{
74    if (!(gpio_sih = si_kattach(SI_OSH)))
75    {
76        printk("%s failed!\n", __FUNCTION__);
77        return -ENODEV;
78    }
79
80    return 0;
81}
82
83static int gpio_control_normal(int pin, int value)
84{
85    si_gpioreserve(gpio_sih, 1 << pin, GPIO_APP_PRIORITY);
86    si_gpioouten(gpio_sih, 1 << pin, 1 << pin, GPIO_APP_PRIORITY);
87    si_gpioout(gpio_sih, 1 << pin, value << pin, GPIO_APP_PRIORITY);
88
89    return 0;
90}
91
92#define GPIO_PIN(x)                     ((x) & 0x00FF)
93
94int gpio_led_on_off(int gpio, int value)
95{
96    int pin = GPIO_PIN(gpio);
97
98    /* foxconn added start, zacker, 09/17/2009, @wps_led */
99    if (gpio == WPS_LED_GPIO)
100        wps_led_is_on = !value;
101    /* foxconn added end, zacker, 09/17/2009, @wps_led */
102    gpio_control_normal(pin, value);
103
104    return 0;
105}
106
107static void quick_blink2(void)
108{
109    static int interrupt_count = -1;
110
111    interrupt_count++;
112    if (interrupt_count == LED_BLINK_RATE_QUICK * 2)
113        interrupt_count = 0;
114
115    if (interrupt_count == 0)
116        gpio_led_on_off(WPS_LED_GPIO, 0);
117    else if (interrupt_count == LED_BLINK_RATE_QUICK)
118        gpio_led_on_off(WPS_LED_GPIO, 1);
119}
120
121static void quick_blink(void)
122{
123    /* foxconn modified start, zacker, 09/17/2009, @wps_led */
124    //static int blink_interval = 3000; /* 30 seconds */
125    static int blink_interval = 500; /* 5 seconds */
126    /* foxconn modified end, zacker, 09/17/2009, @wps_led */
127    static int interrupt_count = -1;
128
129    blink_interval--;
130    interrupt_count++;
131    if (interrupt_count == LED_BLINK_RATE_QUICK * 2)
132        interrupt_count = 0;
133
134    if (interrupt_count == 0)
135        gpio_led_on_off(WPS_LED_GPIO, 0);
136    else if (interrupt_count == LED_BLINK_RATE_QUICK)
137        gpio_led_on_off(WPS_LED_GPIO, 1);
138
139    if ( blink_interval <= 0 )
140    {
141        /* foxconn modified start, zacker, 09/17/2009, @wps_led */
142        //blink_interval = 3000;
143        blink_interval = 500;
144        /* foxconn modified end, zacker, 09/17/2009, @wps_led */
145        wps_led_state = 0;
146    }
147}
148
149static int normal_blink(void)
150{
151    static int interrupt_count = -1;
152
153    interrupt_count++;
154    if (interrupt_count == LED_BLINK_RATE_NORMAL * 2)
155        interrupt_count = 0;
156
157    if (interrupt_count == 0)
158        gpio_led_on_off(WPS_LED_GPIO, 0);
159    else if (interrupt_count == LED_BLINK_RATE_NORMAL)
160        gpio_led_on_off(WPS_LED_GPIO, 1);
161}
162
163static int wps_ap_lockdown_blink(void)
164{
165    static int interrupt_count = -1;
166
167    interrupt_count++;
168    if (interrupt_count == LED_BLINK_RATE_QUICK * 10)
169        interrupt_count = 0;
170
171    if (interrupt_count == 0)
172        gpio_led_on_off(WPS_LED_GPIO, 0);
173    else if (interrupt_count == LED_BLINK_RATE_QUICK)
174        gpio_led_on_off(WPS_LED_GPIO, 1);
175}
176/* Foxconn added end */
177
178/* Foxconn added start pling 02/26/2010 */
179/* Add USB LED  */
180#if (defined INCLUDE_USB_LED)
181/* Foxconn modified start, Wins, 04/11/2011 */
182#define GPIO_USB1_LED       8   /* USB1 LED. */
183#define GPIO_USB2_LED       14  /* USB2 LED. */
184#define LED_BLINK_RATE  5
185int usb1_pkt_cnt = 0;
186int usb2_pkt_cnt = 0;
187int usb1_led_state = 0;
188int usb2_led_state = 0;
189static int usb1_led_state_old = 1;
190static int usb2_led_state_old = 1;
191EXPORT_SYMBOL(usb1_pkt_cnt);
192EXPORT_SYMBOL(usb2_pkt_cnt);
193EXPORT_SYMBOL(usb1_led_state);
194EXPORT_SYMBOL(usb2_led_state);
195/* Foxconn modified end, Wins, 04/11/2011 */
196
197static int gpio_on_off(int gpio_num, int on_off)
198{
199    si_gpioreserve(gpio_sih, 1 << gpio_num, GPIO_APP_PRIORITY);
200    si_gpioouten(gpio_sih, 1 << gpio_num, 1 << gpio_num, GPIO_APP_PRIORITY);
201    si_gpioout(gpio_sih, 1 << gpio_num, on_off << gpio_num, GPIO_APP_PRIORITY);
202    return 0;
203}
204
205static int usb1_normal_blink(void)
206{
207    static int interrupt_count1 = -1;
208    static int usb1_pkt_cnt_old = 0;
209
210    interrupt_count1++;
211    if (interrupt_count1 == LED_BLINK_RATE * 2)
212        interrupt_count1 = 0;
213
214    if (interrupt_count1 == 0){
215        /*Foxconn, [MJ], turn off USB_Led. */
216        gpio_on_off(GPIO_USB1_LED, 0);
217    }
218    else if (interrupt_count1 == LED_BLINK_RATE)
219    {
220        if (usb1_pkt_cnt != usb1_pkt_cnt_old)
221        {
222            usb1_pkt_cnt_old = usb1_pkt_cnt;
223            /*Foxconn, [MJ], turn on USB_Led. */
224            gpio_on_off(GPIO_USB1_LED, 1);
225            //printk("<1> turn on USB_LED.\n");
226        }
227    }
228    return 0;
229}
230
231static int usb2_normal_blink(void)
232{
233    static int interrupt_count2 = -1;
234    static int usb2_pkt_cnt_old = 0;
235
236    interrupt_count2++;
237    if (interrupt_count2 == LED_BLINK_RATE * 2)
238        interrupt_count2 = 0;
239
240    if (interrupt_count2 == 0){
241        /*Foxconn, [MJ], turn off USB_Led. */
242        gpio_on_off(GPIO_USB2_LED, 0);
243    }
244    else if (interrupt_count2 == LED_BLINK_RATE)
245    {
246        if (usb2_pkt_cnt != usb2_pkt_cnt_old)
247        {
248            usb2_pkt_cnt_old = usb2_pkt_cnt;
249            /*Foxconn, [MJ], turn on USB_Led. */
250            gpio_on_off(GPIO_USB2_LED, 1);
251            //printk("<1> turn on USB_LED.\n");
252        }
253    }
254    return 0;
255}
256#endif
257/* Foxconn added end pling 02/26/2010 */
258
259void __init
260bcm947xx_time_init(void)
261{
262	unsigned int hz;
263	char cn[8];
264
265	/*
266	 * Use deterministic values for initial counter interrupt
267	 * so that calibrate delay avoids encountering a counter wrap.
268	 */
269	write_c0_count(0);
270	write_c0_compare(0xffff);
271
272	if (!(hz = si_cpu_clock(sih)))
273		hz = 100000000;
274
275	bcm_chipname(sih->chip, cn, 8);
276	printk("CPU: BCM%s rev %d at %d MHz\n", cn, sih->chiprev,
277	       (hz + 500000) / 1000000);
278
279	/* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
280	mips_hpt_frequency = hz / 2;
281
282	/* Set watchdog interval in ms */
283	watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0);
284
285	/* Ensure at least WATCHDOG_MIN */
286	if ((watchdog > 0) && (watchdog < WATCHDOG_MIN))
287		watchdog = WATCHDOG_MIN;
288
289	/* Set panic timeout in seconds */
290	panic_timeout = watchdog / 1000;
291	panic_on_oops = watchdog / 1000;
292    /* Init WLAN LED */
293    wps_led_init(); /* Foxconn added */
294}
295
296#ifdef CONFIG_HND_BMIPS3300_PROF
297extern bool hndprofiling;
298#ifdef CONFIG_MIPS64
299typedef u_int64_t sbprof_pc;
300#else
301typedef u_int32_t sbprof_pc;
302#endif
303extern void sbprof_cpu_intr(sbprof_pc restartpc);
304#endif	/* CONFIG_HND_BMIPS3300_PROF */
305
306static irqreturn_t
307bcm947xx_timer_interrupt(int irq, void *dev_id)
308{
309#ifdef CONFIG_HND_BMIPS3300_PROF
310	/*
311	 * Are there any ExcCode or other mean(s) to determine what has caused
312	 * the timer interrupt? For now simply stop the normal timer proc if
313	 * count register is less than compare register.
314	 */
315	if (hndprofiling) {
316		sbprof_cpu_intr(read_c0_epc() +
317		                ((read_c0_cause() >> (CAUSEB_BD - 2)) & 4));
318		if (read_c0_count() < read_c0_compare())
319			return (IRQ_HANDLED);
320	}
321#endif	/* CONFIG_HND_BMIPS3300_PROF */
322
323	/* Generic MIPS timer code */
324	timer_interrupt(irq, dev_id);
325
326	/* Set the watchdog timer to reset after the specified number of ms */
327	if (watchdog > 0)
328		si_watchdog_ms(sih, watchdog);
329
330#ifdef	CONFIG_HWSIM
331	(*((int *)0xa0000f1c))++;
332#else
333	/* Blink one of the LEDs in the external UART */
334	if (mcr && !(jiffies % (HZ/2)))
335		writeb(readb(mcr) ^ UART_MCR_OUT2, mcr);
336#endif
337
338    /* Foxconn added start */
339    /* Blink LED depending of WPS status */
340    if ( wps_led_state == 0 )
341    {
342        if (wps_led_state_old != 0)
343            gpio_led_on_off(WPS_LED_GPIO, 1);
344
345        /* foxconn added start, zacker, 09/17/2009, @wps_led */
346        if ((!is_wl_secu_mode) && wps_led_is_on)
347            gpio_led_on_off(WPS_LED_GPIO, 1);
348
349        if (is_wl_secu_mode && (!wps_led_is_on))
350            gpio_led_on_off(WPS_LED_GPIO, 0);
351        /* foxconn added end, zacker, 09/17/2009, @wps_led */
352    }
353    else
354    if (wps_led_state == 1)
355    {
356        normal_blink();
357    }
358    else
359    if (wps_led_state == 2)
360    {
361        quick_blink();
362    }
363    else
364    if (wps_led_state == 3)
365    {
366        quick_blink2();
367    }
368    else
369    if (wps_led_state == 4)
370    {
371        wps_ap_lockdown_blink();
372    }
373
374    wps_led_state_old = wps_led_state;
375    /* Foxconn added end */
376    /* Foxconn added start pling 02/26/2010 */
377    /* Blink USB LED if necessary */
378#if (defined INCLUDE_USB_LED)
379    /* Foxconn modified start, Wins, 04/11/2011 */
380    if (usb1_led_state)
381    {
382        usb1_normal_blink();
383    }
384    else
385    {
386        if (usb1_led_state_old){
387            /* Foxconn, [MJ], turn on USB1_Led. */
388            gpio_on_off(GPIO_USB1_LED, 1);
389        }
390    }
391    usb1_led_state_old = usb1_led_state;
392
393    if (usb2_led_state)
394    {
395        usb2_normal_blink();
396    }
397    else
398    {
399        if (usb2_led_state_old){
400            /* Foxconn, [MJ], turn on USB2_Led. */
401            gpio_on_off(GPIO_USB2_LED, 1);
402        }
403    }
404    usb2_led_state_old = usb2_led_state;
405    /* Foxconn modified end, Wins, 04/11/2011 */
406#endif
407    /* Foxconn added end pling 02/26/2010 */
408
409	return (IRQ_HANDLED);
410}
411
412static struct irqaction bcm947xx_timer_irqaction = {
413	bcm947xx_timer_interrupt,
414	IRQF_DISABLED,
415	{ { 0 } },
416	"timer",
417	NULL,
418	NULL,
419	0,
420	NULL
421};
422
423void __init
424plat_timer_setup(struct irqaction *irq)
425{
426	/* Enable the timer interrupt */
427	setup_irq(7, &bcm947xx_timer_irqaction);
428}
429