diff options
Diffstat (limited to 'arch/sparc/kernel/auxio_64.c')
-rw-r--r-- | arch/sparc/kernel/auxio_64.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c new file mode 100644 index 000000000000..8b67347d4221 --- /dev/null +++ b/arch/sparc/kernel/auxio_64.c | |||
@@ -0,0 +1,149 @@ | |||
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 | #include <linux/of_device.h> | ||
13 | |||
14 | #include <asm/prom.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_rmw(u8 bits_on, u8 bits_off, int ebus) | ||
31 | { | ||
32 | if (auxio_register) { | ||
33 | unsigned long flags; | ||
34 | u8 regval, newval; | ||
35 | |||
36 | spin_lock_irqsave(&auxio_lock, flags); | ||
37 | |||
38 | regval = (ebus ? | ||
39 | (u8) readl(auxio_register) : | ||
40 | sbus_readb(auxio_register)); | ||
41 | newval = regval | bits_on; | ||
42 | newval &= ~bits_off; | ||
43 | if (!ebus) | ||
44 | newval &= ~AUXIO_AUX1_MASK; | ||
45 | if (ebus) | ||
46 | writel((u32) newval, auxio_register); | ||
47 | else | ||
48 | sbus_writeb(newval, auxio_register); | ||
49 | |||
50 | spin_unlock_irqrestore(&auxio_lock, flags); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | static void __auxio_set_bit(u8 bit, int on, int ebus) | ||
55 | { | ||
56 | u8 bits_on = (ebus ? AUXIO_PCIO_LED : AUXIO_AUX1_LED); | ||
57 | u8 bits_off = 0; | ||
58 | |||
59 | if (!on) { | ||
60 | u8 tmp = bits_off; | ||
61 | bits_off = bits_on; | ||
62 | bits_on = tmp; | ||
63 | } | ||
64 | __auxio_rmw(bits_on, bits_off, ebus); | ||
65 | } | ||
66 | |||
67 | void auxio_set_led(int on) | ||
68 | { | ||
69 | int ebus = auxio_devtype == AUXIO_TYPE_EBUS; | ||
70 | u8 bit; | ||
71 | |||
72 | bit = (ebus ? AUXIO_PCIO_LED : AUXIO_AUX1_LED); | ||
73 | __auxio_set_bit(bit, on, ebus); | ||
74 | } | ||
75 | |||
76 | static void __auxio_sbus_set_lte(int on) | ||
77 | { | ||
78 | __auxio_set_bit(AUXIO_AUX1_LTE, on, 0); | ||
79 | } | ||
80 | |||
81 | void auxio_set_lte(int on) | ||
82 | { | ||
83 | switch(auxio_devtype) { | ||
84 | case AUXIO_TYPE_SBUS: | ||
85 | __auxio_sbus_set_lte(on); | ||
86 | break; | ||
87 | case AUXIO_TYPE_EBUS: | ||
88 | /* FALL-THROUGH */ | ||
89 | default: | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static struct of_device_id __initdata auxio_match[] = { | ||
95 | { | ||
96 | .name = "auxio", | ||
97 | }, | ||
98 | {}, | ||
99 | }; | ||
100 | |||
101 | MODULE_DEVICE_TABLE(of, auxio_match); | ||
102 | |||
103 | static int __devinit auxio_probe(struct of_device *dev, const struct of_device_id *match) | ||
104 | { | ||
105 | struct device_node *dp = dev->node; | ||
106 | unsigned long size; | ||
107 | |||
108 | if (!strcmp(dp->parent->name, "ebus")) { | ||
109 | auxio_devtype = AUXIO_TYPE_EBUS; | ||
110 | size = sizeof(u32); | ||
111 | } else if (!strcmp(dp->parent->name, "sbus")) { | ||
112 | auxio_devtype = AUXIO_TYPE_SBUS; | ||
113 | size = 1; | ||
114 | } else { | ||
115 | printk("auxio: Unknown parent bus type [%s]\n", | ||
116 | dp->parent->name); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | auxio_register = of_ioremap(&dev->resource[0], 0, size, "auxio"); | ||
120 | if (!auxio_register) | ||
121 | return -ENODEV; | ||
122 | |||
123 | printk(KERN_INFO "AUXIO: Found device at %s\n", | ||
124 | dp->full_name); | ||
125 | |||
126 | if (auxio_devtype == AUXIO_TYPE_EBUS) | ||
127 | auxio_set_led(AUXIO_LED_ON); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct of_platform_driver auxio_driver = { | ||
133 | .match_table = auxio_match, | ||
134 | .probe = auxio_probe, | ||
135 | .driver = { | ||
136 | .name = "auxio", | ||
137 | }, | ||
138 | }; | ||
139 | |||
140 | static int __init auxio_init(void) | ||
141 | { | ||
142 | return of_register_driver(&auxio_driver, &of_platform_bus_type); | ||
143 | } | ||
144 | |||
145 | /* Must be after subsys_initcall() so that busses are probed. Must | ||
146 | * be before device_initcall() because things like the floppy driver | ||
147 | * need to use the AUXIO register. | ||
148 | */ | ||
149 | fs_initcall(auxio_init); | ||