Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
63b61452 | 19 | /* This cannot be static, as it is referenced in irq.c */ |
1da177e4 LT |
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 | ||
b5ba0740 | 113 | static void __devinit auxio_report_dev(struct device_node *dp) |
1da177e4 | 114 | { |
b5ba0740 DM |
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 | ||
1da177e4 | 151 | #ifdef CONFIG_PCI |
b5ba0740 DM |
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 | ||
1da177e4 | 163 | auxio_set_led(AUXIO_LED_ON); |
b5ba0740 DM |
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 | }; | |
1da177e4 | 173 | #endif |
b5ba0740 DM |
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; | |
1da177e4 | 185 | } |
b5ba0740 DM |
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); |