[SPARC64]: Fix sched_clock() wrapping every ~17 seconds.
[linux-2.6] / arch / sparc64 / kernel / auxio.c
1 /* auxio.c: Probing for the Sparc AUXIO register at boot time.
2  *
3  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
4  *
5  * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
6  */
7
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/ioport.h>
13
14 #include <asm/prom.h>
15 #include <asm/of_device.h>
16 #include <asm/io.h>
17 #include <asm/auxio.h>
18
19 void __iomem *auxio_register = NULL;
20 EXPORT_SYMBOL(auxio_register);
21
22 enum auxio_type {
23         AUXIO_TYPE_NODEV,
24         AUXIO_TYPE_SBUS,
25         AUXIO_TYPE_EBUS
26 };
27
28 static enum auxio_type auxio_devtype = AUXIO_TYPE_NODEV;
29 static DEFINE_SPINLOCK(auxio_lock);
30
31 static void __auxio_sbus_set(u8 bits_on, u8 bits_off)
32 {
33         if (auxio_register) {
34                 unsigned char regval;
35                 unsigned long flags;
36                 unsigned char newval;
37
38                 spin_lock_irqsave(&auxio_lock, flags);
39
40                 regval =  sbus_readb(auxio_register);
41                 newval =  regval | bits_on;
42                 newval &= ~bits_off;
43                 newval &= ~AUXIO_AUX1_MASK;
44                 sbus_writeb(newval, auxio_register);
45                 
46                 spin_unlock_irqrestore(&auxio_lock, flags);
47         }
48 }
49
50 static void __auxio_ebus_set(u8 bits_on, u8 bits_off)
51 {
52         if (auxio_register) {
53                 unsigned char regval;
54                 unsigned long flags;
55                 unsigned char newval;
56
57                 spin_lock_irqsave(&auxio_lock, flags);
58
59                 regval =  (u8)readl(auxio_register);
60                 newval =  regval | bits_on;
61                 newval &= ~bits_off;
62                 writel((u32)newval, auxio_register);
63
64                 spin_unlock_irqrestore(&auxio_lock, flags);
65         }
66 }
67
68 static inline void __auxio_ebus_set_led(int on)
69 {
70         (on) ? __auxio_ebus_set(AUXIO_PCIO_LED, 0) :
71                 __auxio_ebus_set(0, AUXIO_PCIO_LED) ;
72 }
73
74 static inline void __auxio_sbus_set_led(int on)
75 {
76         (on) ? __auxio_sbus_set(AUXIO_AUX1_LED, 0) :
77                 __auxio_sbus_set(0, AUXIO_AUX1_LED) ;
78 }
79
80 void auxio_set_led(int on)
81 {
82         switch(auxio_devtype) {
83         case AUXIO_TYPE_SBUS:
84                 __auxio_sbus_set_led(on);
85                 break;
86         case AUXIO_TYPE_EBUS:
87                 __auxio_ebus_set_led(on);
88                 break;
89         default:
90                 break;
91         }
92 }
93
94 static inline void __auxio_sbus_set_lte(int on)
95 {
96         (on) ? __auxio_sbus_set(AUXIO_AUX1_LTE, 0) : 
97                 __auxio_sbus_set(0, AUXIO_AUX1_LTE) ;
98 }
99
100 void auxio_set_lte(int on)
101 {
102         switch(auxio_devtype) {
103         case AUXIO_TYPE_SBUS:
104                 __auxio_sbus_set_lte(on);
105                 break;
106         case AUXIO_TYPE_EBUS:
107                 /* FALL-THROUGH */
108         default:
109                 break;
110         }
111 }
112
113 static struct of_device_id auxio_match[] = {
114         {
115                 .name = "auxio",
116         },
117         {},
118 };
119
120 MODULE_DEVICE_TABLE(of, auxio_match);
121
122 static int __devinit auxio_probe(struct of_device *dev, const struct of_device_id *match)
123 {
124         struct device_node *dp = dev->node;
125         unsigned long size;
126
127         if (!strcmp(dp->parent->name, "ebus")) {
128                 auxio_devtype = AUXIO_TYPE_EBUS;
129                 size = sizeof(u32);
130         } else if (!strcmp(dp->parent->name, "sbus")) {
131                 auxio_devtype = AUXIO_TYPE_SBUS;
132                 size = 1;
133         } else {
134                 printk("auxio: Unknown parent bus type [%s]\n",
135                        dp->parent->name);
136                 return -ENODEV;
137         }
138         auxio_register = of_ioremap(&dev->resource[0], 0, size, "auxio");
139         if (!auxio_register)
140                 return -ENODEV;
141
142         printk(KERN_INFO "AUXIO: Found device at %s\n",
143                dp->full_name);
144
145         if (auxio_devtype == AUXIO_TYPE_EBUS)
146                 auxio_set_led(AUXIO_LED_ON);
147
148         return 0;
149 }
150
151 static struct of_platform_driver auxio_driver = {
152         .name           = "auxio",
153         .match_table    = auxio_match,
154         .probe          = auxio_probe,
155 };
156
157 static int __init auxio_init(void)
158 {
159         return of_register_driver(&auxio_driver, &of_bus_type);
160 }
161
162 /* Must be after subsys_initcall() so that busses are probed.  Must
163  * be before device_initcall() because things like the floppy driver
164  * need to use the AUXIO register.
165  */
166 fs_initcall(auxio_init);