Merge branch 'master'
[linux-2.6] / arch / sh / boards / superh / microdev / led.c
1 /*
2  * linux/arch/sh/kernel/led_microdev.c
3  *
4  * Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com>
5  * Copyright (C) 2003 Richard Curnow (Richard.Curnow@superh.com)
6  *
7  * May be copied or modified under the terms of the GNU General Public
8  * License.  See linux/COPYING for more information.
9  *
10  */
11
12 #include <linux/config.h>
13 #include <asm/io.h>
14
15 #define LED_REGISTER 0xa6104d20
16
17 static void mach_led_d9(int value)
18 {
19         unsigned long reg;
20         reg = ctrl_inl(LED_REGISTER);
21         reg &= ~1;
22         reg |= (value & 1);
23         ctrl_outl(reg, LED_REGISTER);
24         return;
25 }
26
27 static void mach_led_d10(int value)
28 {
29         unsigned long reg;
30         reg = ctrl_inl(LED_REGISTER);
31         reg &= ~2;
32         reg |= ((value & 1) << 1);
33         ctrl_outl(reg, LED_REGISTER);
34         return;
35 }
36
37
38 #ifdef CONFIG_HEARTBEAT
39 #include <linux/sched.h>
40
41 static unsigned char banner_table[] = {
42         0x11, 0x01, 0x11, 0x01, 0x11, 0x03,
43         0x11, 0x01, 0x11, 0x01, 0x13, 0x03,
44         0x11, 0x01, 0x13, 0x01, 0x13, 0x01, 0x11, 0x03,
45         0x11, 0x03,
46         0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
47         0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x07,
48         0x13, 0x01, 0x13, 0x03,
49         0x11, 0x01, 0x11, 0x03,
50         0x13, 0x01, 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
51         0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
52         0x13, 0x01, 0x13, 0x01, 0x13, 0x03,
53         0x13, 0x01, 0x11, 0x01, 0x11, 0x03,
54         0x11, 0x03,
55         0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x13, 0x07,
56         0xff
57 };
58
59 static void banner(void)
60 {
61         static int pos = 0;
62         static int count = 0;
63
64         if (count) {
65                 count--;
66         } else {
67                 int val = banner_table[pos];
68                 if (val == 0xff) {
69                         pos = 0;
70                         val = banner_table[pos];
71                 }
72                 pos++;
73                 mach_led_d10((val >> 4) & 1);
74                 count = 10 * (val & 0xf);
75         }
76 }
77
78 /* From heartbeat_harp in the stboards directory */
79 /* acts like an actual heart beat -- ie thump-thump-pause... */
80 void microdev_heartbeat(void)
81 {
82         static unsigned cnt = 0, period = 0, dist = 0;
83
84         if (cnt == 0 || cnt == dist)
85                 mach_led_d9(1);
86         else if (cnt == 7 || cnt == dist+7)
87                 mach_led_d9(0);
88
89         if (++cnt > period) {
90                 cnt = 0;
91                 /* The hyperbolic function below modifies the heartbeat period
92                  * length in dependency of the current (5min) load. It goes
93                  * through the points f(0)=126, f(1)=86, f(5)=51,
94                  * f(inf)->30. */
95                 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
96                 dist = period / 4;
97         }
98
99         banner();
100 }
101
102 #endif