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