diff options
Diffstat (limited to 'arch/sparc64/kernel/auxio.c')
-rw-r--r-- | arch/sparc64/kernel/auxio.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c new file mode 100644 index 000000000000..a0716ccc2f4a --- /dev/null +++ b/arch/sparc64/kernel/auxio.c | |||
@@ -0,0 +1,152 @@ | |||
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 entry.S */ | ||
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 | void __init auxio_probe(void) | ||
114 | { | ||
115 | struct sbus_bus *sbus; | ||
116 | struct sbus_dev *sdev = NULL; | ||
117 | |||
118 | for_each_sbus(sbus) { | ||
119 | for_each_sbusdev(sdev, sbus) { | ||
120 | if(!strcmp(sdev->prom_name, "auxio")) | ||
121 | goto found_sdev; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | found_sdev: | ||
126 | if (sdev) { | ||
127 | auxio_devtype = AUXIO_TYPE_SBUS; | ||
128 | auxio_register = sbus_ioremap(&sdev->resource[0], 0, | ||
129 | sdev->reg_addrs[0].reg_size, | ||
130 | "auxiliaryIO"); | ||
131 | } | ||
132 | #ifdef CONFIG_PCI | ||
133 | else { | ||
134 | struct linux_ebus *ebus; | ||
135 | struct linux_ebus_device *edev = NULL; | ||
136 | |||
137 | for_each_ebus(ebus) { | ||
138 | for_each_ebusdev(edev, ebus) { | ||
139 | if (!strcmp(edev->prom_name, "auxio")) | ||
140 | goto ebus_done; | ||
141 | } | ||
142 | } | ||
143 | ebus_done: | ||
144 | if (edev) { | ||
145 | auxio_devtype = AUXIO_TYPE_EBUS; | ||
146 | auxio_register = | ||
147 | ioremap(edev->resource[0].start, sizeof(u32)); | ||
148 | } | ||
149 | } | ||
150 | auxio_set_led(AUXIO_LED_ON); | ||
151 | #endif | ||
152 | } | ||