]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/sparc64/kernel/auxio.c
[SPARC64]: Make auxio a real driver.
[linux-2.6-omap-h63xx.git] / 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/kernel.h>
10 #include <linux/init.h>
11 #include <linux/ioport.h>
12
13 #include <asm/oplib.h>
14 #include <asm/io.h>
15 #include <asm/sbus.h>
16 #include <asm/ebus.h>
17 #include <asm/auxio.h>
18
19 /* This cannot be static, as it is referenced in irq.c */
20 void __iomem *auxio_register = NULL;
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 void __devinit auxio_report_dev(struct device_node *dp)
114 {
115         printk(KERN_INFO "AUXIO: Found device at %s\n",
116                dp->full_name);
117 }
118
119 static struct of_device_id auxio_match[] = {
120         {
121                 .name = "auxio",
122         },
123         {},
124 };
125
126 MODULE_DEVICE_TABLE(of, auxio_match);
127
128 #ifdef CONFIG_SBUS
129 static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match)
130 {
131         struct sbus_dev *sdev = to_sbus_device(&dev->dev);
132
133         auxio_devtype  = AUXIO_TYPE_SBUS;
134         auxio_register = sbus_ioremap(&sdev->resource[0], 0,
135                                       sdev->reg_addrs[0].reg_size,
136                                       "auxiliaryIO");
137         if (!auxio_register)
138                 return -ENODEV;
139
140         auxio_report_dev(dev->node);
141         return 0;
142 }
143
144 static struct of_platform_driver auxio_sbus_driver = {
145         .name           = "auxio",
146         .match_table    = auxio_match,
147         .probe          = auxio_sbus_probe,
148 };
149 #endif
150
151 #ifdef CONFIG_PCI
152 static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match)
153 {
154         struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
155
156         auxio_devtype  = AUXIO_TYPE_EBUS;
157         auxio_register = ioremap(edev->resource[0].start, sizeof(u32));
158         if (!auxio_register)
159                 return -ENODEV;
160
161         auxio_report_dev(dev->node);
162
163         auxio_set_led(AUXIO_LED_ON);
164
165         return 0;
166 }
167
168 static struct of_platform_driver auxio_ebus_driver = {
169         .name           = "auxio",
170         .match_table    = auxio_match,
171         .probe          = auxio_ebus_probe,
172 };
173 #endif
174
175 static int __init auxio_probe(void)
176 {
177 #ifdef CONFIG_SBUS
178         of_register_driver(&auxio_sbus_driver, &sbus_bus_type);
179 #endif
180 #ifdef CONFIG_PCI
181         of_register_driver(&auxio_ebus_driver, &ebus_bus_type);
182 #endif
183
184         return 0;
185 }
186
187 /* Must be after subsys_initcall() so that busses are probed.  Must
188  * be before device_initcall() because things like the floppy driver
189  * need to use the AUXIO register.
190  */
191 fs_initcall(auxio_probe);