diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/macintosh |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/macintosh')
24 files changed, 18915 insertions, 0 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig new file mode 100644 index 000000000000..8a7117a08cf0 --- /dev/null +++ b/drivers/macintosh/Kconfig | |||
@@ -0,0 +1,198 @@ | |||
1 | |||
2 | menu "Macintosh device drivers" | ||
3 | depends on PPC || MAC | ||
4 | |||
5 | config ADB | ||
6 | bool "Apple Desktop Bus (ADB) support" | ||
7 | depends on MAC || PPC_PMAC | ||
8 | help | ||
9 | Apple Desktop Bus (ADB) support is for support of devices which | ||
10 | are connected to an ADB port. ADB devices tend to have 4 pins. | ||
11 | If you have an Apple Macintosh prior to the iMac, an iBook or | ||
12 | PowerBook, or a "Blue and White G3", you probably want to say Y | ||
13 | here. Otherwise say N. | ||
14 | |||
15 | config ADB_MACII | ||
16 | bool "Include Mac II ADB driver" | ||
17 | depends on ADB && MAC | ||
18 | help | ||
19 | Say Y here if want your kernel to support Macintosh systems that use | ||
20 | the Mac II style ADB. This includes the II, IIx, IIcx, SE/30, IIci, | ||
21 | Quadra 610, Quadra 650, Quadra 700, Quadra 800, Centris 610 and | ||
22 | Centris 650. | ||
23 | |||
24 | config ADB_MACIISI | ||
25 | bool "Include Mac IIsi ADB driver" | ||
26 | depends on ADB && MAC | ||
27 | help | ||
28 | Say Y here if want your kernel to support Macintosh systems that use | ||
29 | the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic | ||
30 | II, LC, LC II, LC III, Performa 460, and the Performa 600. | ||
31 | |||
32 | config ADB_IOP | ||
33 | bool "Include IOP (IIfx/Quadra 9x0) ADB driver" | ||
34 | depends on ADB && MAC | ||
35 | help | ||
36 | The I/O Processor (IOP) is an Apple custom IC designed to provide | ||
37 | intelligent support for I/O controllers. It is described at | ||
38 | <http://www.angelfire.com/ca2/dev68k/iopdesc.html> to enable direct | ||
39 | support for it, say 'Y' here. | ||
40 | |||
41 | config ADB_PMU68K | ||
42 | bool "Include PMU (Powerbook) ADB driver" | ||
43 | depends on ADB && MAC | ||
44 | help | ||
45 | Say Y here if want your kernel to support the m68k based Powerbooks. | ||
46 | This includes the PowerBook 140, PowerBook 145, PowerBook 150, | ||
47 | PowerBook 160, PowerBook 165, PowerBook 165c, PowerBook 170, | ||
48 | PowerBook 180, PowerBook, 180c, PowerBook 190cs, PowerBook 520, | ||
49 | PowerBook Duo 210, PowerBook Duo 230, PowerBook Duo 250, | ||
50 | PowerBook Duo 270c, PowerBook Duo 280 and PowerBook Duo 280c. | ||
51 | |||
52 | # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU | ||
53 | config ADB_CUDA | ||
54 | bool "Support for CUDA based Macs and PowerMacs" | ||
55 | depends on (ADB || PPC_PMAC) && !PPC_PMAC64 | ||
56 | help | ||
57 | This provides support for CUDA based Macintosh and Power Macintosh | ||
58 | systems. This includes many m68k based Macs (Color Classic, Mac TV, | ||
59 | Performa 475, Performa 520, Performa 550, Performa 575, | ||
60 | Performa 588, Quadra 605, Quadra 630, Quadra/Centris 660AV, and | ||
61 | Quadra 840AV), most OldWorld PowerMacs, the first generation iMacs, | ||
62 | the Blue&White G3 and the "Yikes" G4 (PCI Graphics). All later | ||
63 | models should use CONFIG_ADB_PMU instead. It is safe to say Y here | ||
64 | even if your machine doesn't have a CUDA. | ||
65 | |||
66 | If unsure say Y. | ||
67 | |||
68 | config ADB_PMU | ||
69 | bool "Support for PMU based PowerMacs" | ||
70 | depends on PPC_PMAC | ||
71 | help | ||
72 | On PowerBooks, iBooks, and recent iMacs and Power Macintoshes, the | ||
73 | PMU is an embedded microprocessor whose primary function is to | ||
74 | control system power, and battery charging on the portable models. | ||
75 | The PMU also controls the ADB (Apple Desktop Bus) which connects to | ||
76 | the keyboard and mouse on some machines, as well as the non-volatile | ||
77 | RAM and the RTC (real time clock) chip. Say Y to enable support for | ||
78 | this device; you should do so if your machine is one of those | ||
79 | mentioned above. | ||
80 | |||
81 | config PMAC_SMU | ||
82 | bool "Support for SMU based PowerMacs" | ||
83 | depends on PPC_PMAC64 | ||
84 | help | ||
85 | This option adds support for the newer G5 iMacs and PowerMacs based | ||
86 | on the "SMU" system control chip which replaces the old PMU. | ||
87 | If you don't know, say Y. | ||
88 | |||
89 | config PMAC_PBOOK | ||
90 | bool "Power management support for PowerBooks" | ||
91 | depends on ADB_PMU | ||
92 | ---help--- | ||
93 | This provides support for putting a PowerBook to sleep; it also | ||
94 | enables media bay support. Power management works on the | ||
95 | PB2400/3400/3500, Wallstreet, Lombard, and Bronze PowerBook G3 and | ||
96 | the Titanium Powerbook G4, as well as the iBooks. You should get | ||
97 | the power management daemon, pmud, to make it work and you must have | ||
98 | the /dev/pmu device (see the pmud README). | ||
99 | |||
100 | Get pmud from <ftp://ftp.samba.org/pub/ppclinux/pmud/>. | ||
101 | |||
102 | If you have a PowerBook, you should say Y here. | ||
103 | |||
104 | You may also want to compile the dma sound driver as a module and | ||
105 | have it autoloaded. The act of removing the module shuts down the | ||
106 | sound hardware for more power savings. | ||
107 | |||
108 | config PM | ||
109 | bool | ||
110 | depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK | ||
111 | default y | ||
112 | |||
113 | config PMAC_APM_EMU | ||
114 | tristate "APM emulation" | ||
115 | depends on PMAC_PBOOK | ||
116 | |||
117 | # made a separate option since backlight may end up beeing used | ||
118 | # on non-powerbook machines (but only on PMU based ones AFAIK) | ||
119 | config PMAC_BACKLIGHT | ||
120 | bool "Backlight control for LCD screens" | ||
121 | depends on ADB_PMU | ||
122 | help | ||
123 | Say Y here to build in code to manage the LCD backlight on a | ||
124 | Macintosh PowerBook. With this code, the backlight will be turned | ||
125 | on and off appropriately on power-management and lid-open/lid-closed | ||
126 | events; also, the PowerBook button device will be enabled so you can | ||
127 | change the screen brightness. | ||
128 | |||
129 | config MAC_SERIAL | ||
130 | tristate "Support for PowerMac serial ports (OBSOLETE DRIVER)" | ||
131 | depends on PPC_PMAC && BROKEN | ||
132 | help | ||
133 | This driver is obsolete. Use CONFIG_SERIAL_PMACZILOG in | ||
134 | "Character devices --> Serial drivers --> PowerMac z85c30" option. | ||
135 | |||
136 | config ADB_MACIO | ||
137 | bool "Include MacIO (CHRP) ADB driver" | ||
138 | depends on ADB && PPC_CHRP && !PPC_PMAC64 | ||
139 | help | ||
140 | Say Y here to include direct support for the ADB controller in the | ||
141 | Hydra chip used on PowerPC Macintoshes of the CHRP type. (The Hydra | ||
142 | also includes a MESH II SCSI controller, DBDMA controller, VIA chip, | ||
143 | OpenPIC controller and two RS422/Geoports.) | ||
144 | |||
145 | config INPUT_ADBHID | ||
146 | bool "Support for ADB input devices (keyboard, mice, ...)" | ||
147 | depends on ADB && INPUT=y | ||
148 | help | ||
149 | Say Y here if you want to have ADB (Apple Desktop Bus) HID devices | ||
150 | such as keyboards, mice, joysticks, trackpads or graphic tablets | ||
151 | handled by the input layer. If you say Y here, make sure to say Y to | ||
152 | the corresponding drivers "Keyboard support" (CONFIG_INPUT_KEYBDEV), | ||
153 | "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and "Event interface | ||
154 | support" (CONFIG_INPUT_EVDEV) as well. | ||
155 | |||
156 | If unsure, say Y. | ||
157 | |||
158 | config MAC_EMUMOUSEBTN | ||
159 | bool "Support for mouse button 2+3 emulation" | ||
160 | depends on INPUT_ADBHID | ||
161 | help | ||
162 | This provides generic support for emulating the 2nd and 3rd mouse | ||
163 | button with keypresses. If you say Y here, the emulation is still | ||
164 | disabled by default. The emulation is controlled by these sysctl | ||
165 | entries: | ||
166 | /proc/sys/dev/mac_hid/mouse_button_emulation | ||
167 | /proc/sys/dev/mac_hid/mouse_button2_keycode | ||
168 | /proc/sys/dev/mac_hid/mouse_button3_keycode | ||
169 | |||
170 | If you have an Apple machine with a 1-button mouse, say Y here. | ||
171 | |||
172 | config THERM_WINDTUNNEL | ||
173 | tristate "Support for thermal management on Windtunnel G4s" | ||
174 | depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 | ||
175 | help | ||
176 | This driver provides some thermostat and fan control for the desktop | ||
177 | G4 "Windtunnel" | ||
178 | |||
179 | config THERM_ADT746X | ||
180 | tristate "Support for thermal mgmnt on laptops with ADT 746x chipset" | ||
181 | depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 | ||
182 | help | ||
183 | This driver provides some thermostat and fan control for the | ||
184 | iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty | ||
185 | better fan behaviour by default, and some manual control. | ||
186 | |||
187 | config THERM_PM72 | ||
188 | tristate "Support for thermal management on PowerMac G5" | ||
189 | depends on I2C && I2C_KEYWEST && PPC_PMAC64 | ||
190 | help | ||
191 | This driver provides thermostat and fan control for the desktop | ||
192 | G5 machines. | ||
193 | |||
194 | config ANSLCD | ||
195 | tristate "Support for ANS LCD display" | ||
196 | depends on ADB_CUDA && PPC_PMAC | ||
197 | |||
198 | endmenu | ||
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile new file mode 100644 index 000000000000..c3a4705a8295 --- /dev/null +++ b/drivers/macintosh/Makefile | |||
@@ -0,0 +1,29 @@ | |||
1 | # | ||
2 | # Makefile for the Macintosh-specific device drivers. | ||
3 | # | ||
4 | |||
5 | # Each configuration option enables a list of files. | ||
6 | |||
7 | obj-$(CONFIG_PPC_PMAC) += macio_asic.o | ||
8 | |||
9 | obj-$(CONFIG_PMAC_PBOOK) += mediabay.o | ||
10 | obj-$(CONFIG_MAC_SERIAL) += macserial.o | ||
11 | obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o | ||
12 | obj-$(CONFIG_INPUT_ADBHID) += adbhid.o | ||
13 | obj-$(CONFIG_ANSLCD) += ans-lcd.o | ||
14 | |||
15 | obj-$(CONFIG_ADB_PMU) += via-pmu.o | ||
16 | obj-$(CONFIG_ADB_CUDA) += via-cuda.o | ||
17 | obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o | ||
18 | obj-$(CONFIG_PMAC_SMU) += smu.o | ||
19 | |||
20 | obj-$(CONFIG_ADB) += adb.o | ||
21 | obj-$(CONFIG_ADB_MACII) += via-macii.o | ||
22 | obj-$(CONFIG_ADB_MACIISI) += via-maciisi.o | ||
23 | obj-$(CONFIG_ADB_IOP) += adb-iop.o | ||
24 | obj-$(CONFIG_ADB_PMU68K) += via-pmu68k.o | ||
25 | obj-$(CONFIG_ADB_MACIO) += macio-adb.o | ||
26 | |||
27 | obj-$(CONFIG_THERM_PM72) += therm_pm72.o | ||
28 | obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o | ||
29 | obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o | ||
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c new file mode 100644 index 000000000000..71aeb912ec61 --- /dev/null +++ b/drivers/macintosh/adb-iop.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | * I/O Processor (IOP) ADB Driver | ||
3 | * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org) | ||
4 | * Based on via-cuda.c by Paul Mackerras. | ||
5 | * | ||
6 | * 1999-07-01 (jmt) - First implementation for new driver architecture. | ||
7 | * | ||
8 | * 1999-07-31 (jmt) - First working version. | ||
9 | * | ||
10 | * TODO: | ||
11 | * | ||
12 | * o Implement SRQ handling. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/proc_fs.h> | ||
21 | |||
22 | #include <asm/bootinfo.h> | ||
23 | #include <asm/macintosh.h> | ||
24 | #include <asm/macints.h> | ||
25 | #include <asm/mac_iop.h> | ||
26 | #include <asm/mac_oss.h> | ||
27 | #include <asm/adb_iop.h> | ||
28 | |||
29 | #include <linux/adb.h> | ||
30 | |||
31 | /*#define DEBUG_ADB_IOP*/ | ||
32 | |||
33 | extern void iop_ism_irq(int, void *, struct pt_regs *); | ||
34 | |||
35 | static struct adb_request *current_req; | ||
36 | static struct adb_request *last_req; | ||
37 | #if 0 | ||
38 | static unsigned char reply_buff[16]; | ||
39 | static unsigned char *reply_ptr; | ||
40 | #endif | ||
41 | |||
42 | static enum adb_iop_state { | ||
43 | idle, | ||
44 | sending, | ||
45 | awaiting_reply | ||
46 | } adb_iop_state; | ||
47 | |||
48 | static void adb_iop_start(void); | ||
49 | static int adb_iop_probe(void); | ||
50 | static int adb_iop_init(void); | ||
51 | static int adb_iop_send_request(struct adb_request *, int); | ||
52 | static int adb_iop_write(struct adb_request *); | ||
53 | static int adb_iop_autopoll(int); | ||
54 | static void adb_iop_poll(void); | ||
55 | static int adb_iop_reset_bus(void); | ||
56 | |||
57 | struct adb_driver adb_iop_driver = { | ||
58 | "ISM IOP", | ||
59 | adb_iop_probe, | ||
60 | adb_iop_init, | ||
61 | adb_iop_send_request, | ||
62 | adb_iop_autopoll, | ||
63 | adb_iop_poll, | ||
64 | adb_iop_reset_bus | ||
65 | }; | ||
66 | |||
67 | static void adb_iop_end_req(struct adb_request *req, int state) | ||
68 | { | ||
69 | req->complete = 1; | ||
70 | current_req = req->next; | ||
71 | if (req->done) (*req->done)(req); | ||
72 | adb_iop_state = state; | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * Completion routine for ADB commands sent to the IOP. | ||
77 | * | ||
78 | * This will be called when a packet has been successfully sent. | ||
79 | */ | ||
80 | |||
81 | static void adb_iop_complete(struct iop_msg *msg, struct pt_regs *regs) | ||
82 | { | ||
83 | struct adb_request *req; | ||
84 | uint flags; | ||
85 | |||
86 | local_irq_save(flags); | ||
87 | |||
88 | req = current_req; | ||
89 | if ((adb_iop_state == sending) && req && req->reply_expected) { | ||
90 | adb_iop_state = awaiting_reply; | ||
91 | } | ||
92 | |||
93 | local_irq_restore(flags); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Listen for ADB messages from the IOP. | ||
98 | * | ||
99 | * This will be called when unsolicited messages (usually replies to TALK | ||
100 | * commands or autopoll packets) are received. | ||
101 | */ | ||
102 | |||
103 | static void adb_iop_listen(struct iop_msg *msg, struct pt_regs *regs) | ||
104 | { | ||
105 | struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message; | ||
106 | struct adb_request *req; | ||
107 | uint flags; | ||
108 | #ifdef DEBUG_ADB_IOP | ||
109 | int i; | ||
110 | #endif | ||
111 | |||
112 | local_irq_save(flags); | ||
113 | |||
114 | req = current_req; | ||
115 | |||
116 | #ifdef DEBUG_ADB_IOP | ||
117 | printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req, | ||
118 | (uint) amsg->count + 2, (uint) amsg->flags, (uint) amsg->cmd); | ||
119 | for (i = 0; i < amsg->count; i++) | ||
120 | printk(" %02X", (uint) amsg->data[i]); | ||
121 | printk("\n"); | ||
122 | #endif | ||
123 | |||
124 | /* Handle a timeout. Timeout packets seem to occur even after */ | ||
125 | /* we've gotten a valid reply to a TALK, so I'm assuming that */ | ||
126 | /* a "timeout" is actually more like an "end-of-data" signal. */ | ||
127 | /* We need to send back a timeout packet to the IOP to shut */ | ||
128 | /* it up, plus complete the current request, if any. */ | ||
129 | |||
130 | if (amsg->flags & ADB_IOP_TIMEOUT) { | ||
131 | msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL; | ||
132 | msg->reply[1] = 0; | ||
133 | msg->reply[2] = 0; | ||
134 | if (req && (adb_iop_state != idle)) { | ||
135 | adb_iop_end_req(req, idle); | ||
136 | } | ||
137 | } else { | ||
138 | /* TODO: is it possible for more than one chunk of data */ | ||
139 | /* to arrive before the timeout? If so we need to */ | ||
140 | /* use reply_ptr here like the other drivers do. */ | ||
141 | if ((adb_iop_state == awaiting_reply) && | ||
142 | (amsg->flags & ADB_IOP_EXPLICIT)) { | ||
143 | req->reply_len = amsg->count + 1; | ||
144 | memcpy(req->reply, &amsg->cmd, req->reply_len); | ||
145 | } else { | ||
146 | adb_input(&amsg->cmd, amsg->count + 1, regs, | ||
147 | amsg->flags & ADB_IOP_AUTOPOLL); | ||
148 | } | ||
149 | memcpy(msg->reply, msg->message, IOP_MSG_LEN); | ||
150 | } | ||
151 | iop_complete_message(msg); | ||
152 | local_irq_restore(flags); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Start sending an ADB packet, IOP style | ||
157 | * | ||
158 | * There isn't much to do other than hand the packet over to the IOP | ||
159 | * after encapsulating it in an adb_iopmsg. | ||
160 | */ | ||
161 | |||
162 | static void adb_iop_start(void) | ||
163 | { | ||
164 | unsigned long flags; | ||
165 | struct adb_request *req; | ||
166 | struct adb_iopmsg amsg; | ||
167 | #ifdef DEBUG_ADB_IOP | ||
168 | int i; | ||
169 | #endif | ||
170 | |||
171 | /* get the packet to send */ | ||
172 | req = current_req; | ||
173 | if (!req) return; | ||
174 | |||
175 | local_irq_save(flags); | ||
176 | |||
177 | #ifdef DEBUG_ADB_IOP | ||
178 | printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes); | ||
179 | for (i = 0 ; i < req->nbytes ; i++) | ||
180 | printk(" %02X", (uint) req->data[i]); | ||
181 | printk("\n"); | ||
182 | #endif | ||
183 | |||
184 | /* The IOP takes MacII-style packets, so */ | ||
185 | /* strip the initial ADB_PACKET byte. */ | ||
186 | |||
187 | amsg.flags = ADB_IOP_EXPLICIT; | ||
188 | amsg.count = req->nbytes - 2; | ||
189 | |||
190 | /* amsg.data immediately follows amsg.cmd, effectively making */ | ||
191 | /* amsg.cmd a pointer to the beginning of a full ADB packet. */ | ||
192 | memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1); | ||
193 | |||
194 | req->sent = 1; | ||
195 | adb_iop_state = sending; | ||
196 | local_irq_restore(flags); | ||
197 | |||
198 | /* Now send it. The IOP manager will call adb_iop_complete */ | ||
199 | /* when the packet has been sent. */ | ||
200 | |||
201 | iop_send_message(ADB_IOP, ADB_CHAN, req, | ||
202 | sizeof(amsg), (__u8 *) &amsg, adb_iop_complete); | ||
203 | } | ||
204 | |||
205 | int adb_iop_probe(void) | ||
206 | { | ||
207 | if (!iop_ism_present) return -ENODEV; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | int adb_iop_init(void) | ||
212 | { | ||
213 | printk("adb: IOP ISM driver v0.4 for Unified ADB.\n"); | ||
214 | iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB"); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | int adb_iop_send_request(struct adb_request *req, int sync) | ||
219 | { | ||
220 | int err; | ||
221 | |||
222 | err = adb_iop_write(req); | ||
223 | if (err) return err; | ||
224 | |||
225 | if (sync) { | ||
226 | while (!req->complete) adb_iop_poll(); | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int adb_iop_write(struct adb_request *req) | ||
232 | { | ||
233 | unsigned long flags; | ||
234 | |||
235 | if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) { | ||
236 | req->complete = 1; | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | local_irq_save(flags); | ||
241 | |||
242 | req->next = 0; | ||
243 | req->sent = 0; | ||
244 | req->complete = 0; | ||
245 | req->reply_len = 0; | ||
246 | |||
247 | if (current_req != 0) { | ||
248 | last_req->next = req; | ||
249 | last_req = req; | ||
250 | } else { | ||
251 | current_req = req; | ||
252 | last_req = req; | ||
253 | } | ||
254 | |||
255 | local_irq_restore(flags); | ||
256 | if (adb_iop_state == idle) adb_iop_start(); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | int adb_iop_autopoll(int devs) | ||
261 | { | ||
262 | /* TODO: how do we enable/disable autopoll? */ | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | void adb_iop_poll(void) | ||
267 | { | ||
268 | if (adb_iop_state == idle) adb_iop_start(); | ||
269 | iop_ism_irq(0, (void *) ADB_IOP, NULL); | ||
270 | } | ||
271 | |||
272 | int adb_iop_reset_bus(void) | ||
273 | { | ||
274 | struct adb_request req = { | ||
275 | .reply_expected = 0, | ||
276 | .nbytes = 2, | ||
277 | .data = { ADB_PACKET, 0 }, | ||
278 | }; | ||
279 | |||
280 | adb_iop_write(&req); | ||
281 | while (!req.complete) { | ||
282 | adb_iop_poll(); | ||
283 | schedule(); | ||
284 | } | ||
285 | |||
286 | return 0; | ||
287 | } | ||
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c new file mode 100644 index 000000000000..7297c77f99cf --- /dev/null +++ b/drivers/macintosh/adb.c | |||
@@ -0,0 +1,910 @@ | |||
1 | /* | ||
2 | * Device driver for the Apple Desktop Bus | ||
3 | * and the /dev/adb device on macintoshes. | ||
4 | * | ||
5 | * Copyright (C) 1996 Paul Mackerras. | ||
6 | * | ||
7 | * Modified to declare controllers as structures, added | ||
8 | * client notification of bus reset and handles PowerBook | ||
9 | * sleep, by Benjamin Herrenschmidt. | ||
10 | * | ||
11 | * To do: | ||
12 | * | ||
13 | * - /sys/bus/adb to list the devices and infos | ||
14 | * - more /dev/adb to allow userland to receive the | ||
15 | * flow of auto-polling datas from a given device. | ||
16 | * - move bus probe to a kernel thread | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/smp_lock.h> | ||
29 | #include <linux/adb.h> | ||
30 | #include <linux/cuda.h> | ||
31 | #include <linux/pmu.h> | ||
32 | #include <linux/notifier.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/completion.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/devfs_fs_kernel.h> | ||
40 | |||
41 | #include <asm/uaccess.h> | ||
42 | #include <asm/semaphore.h> | ||
43 | #ifdef CONFIG_PPC | ||
44 | #include <asm/prom.h> | ||
45 | #endif | ||
46 | |||
47 | |||
48 | EXPORT_SYMBOL(adb_controller); | ||
49 | EXPORT_SYMBOL(adb_client_list); | ||
50 | |||
51 | extern struct adb_driver via_macii_driver; | ||
52 | extern struct adb_driver via_maciisi_driver; | ||
53 | extern struct adb_driver via_cuda_driver; | ||
54 | extern struct adb_driver adb_iop_driver; | ||
55 | extern struct adb_driver via_pmu_driver; | ||
56 | extern struct adb_driver macio_adb_driver; | ||
57 | |||
58 | static struct adb_driver *adb_driver_list[] = { | ||
59 | #ifdef CONFIG_ADB_MACII | ||
60 | &via_macii_driver, | ||
61 | #endif | ||
62 | #ifdef CONFIG_ADB_MACIISI | ||
63 | &via_maciisi_driver, | ||
64 | #endif | ||
65 | #ifdef CONFIG_ADB_CUDA | ||
66 | &via_cuda_driver, | ||
67 | #endif | ||
68 | #ifdef CONFIG_ADB_IOP | ||
69 | &adb_iop_driver, | ||
70 | #endif | ||
71 | #if defined(CONFIG_ADB_PMU) || defined(CONFIG_ADB_PMU68K) | ||
72 | &via_pmu_driver, | ||
73 | #endif | ||
74 | #ifdef CONFIG_ADB_MACIO | ||
75 | &macio_adb_driver, | ||
76 | #endif | ||
77 | NULL | ||
78 | }; | ||
79 | |||
80 | static struct class_simple *adb_dev_class; | ||
81 | |||
82 | struct adb_driver *adb_controller; | ||
83 | struct notifier_block *adb_client_list = NULL; | ||
84 | static int adb_got_sleep; | ||
85 | static int adb_inited; | ||
86 | static pid_t adb_probe_task_pid; | ||
87 | static DECLARE_MUTEX(adb_probe_mutex); | ||
88 | static struct completion adb_probe_task_comp; | ||
89 | static int sleepy_trackpad; | ||
90 | static int autopoll_devs; | ||
91 | int __adb_probe_sync; | ||
92 | |||
93 | #ifdef CONFIG_PMAC_PBOOK | ||
94 | static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); | ||
95 | static struct pmu_sleep_notifier adb_sleep_notifier = { | ||
96 | adb_notify_sleep, | ||
97 | SLEEP_LEVEL_ADB, | ||
98 | }; | ||
99 | #endif | ||
100 | |||
101 | static int adb_scan_bus(void); | ||
102 | static int do_adb_reset_bus(void); | ||
103 | static void adbdev_init(void); | ||
104 | static int try_handler_change(int, int); | ||
105 | |||
106 | static struct adb_handler { | ||
107 | void (*handler)(unsigned char *, int, struct pt_regs *, int); | ||
108 | int original_address; | ||
109 | int handler_id; | ||
110 | int busy; | ||
111 | } adb_handler[16]; | ||
112 | |||
113 | /* | ||
114 | * The adb_handler_sem mutex protects all accesses to the original_address | ||
115 | * and handler_id fields of adb_handler[i] for all i, and changes to the | ||
116 | * handler field. | ||
117 | * Accesses to the handler field are protected by the adb_handler_lock | ||
118 | * rwlock. It is held across all calls to any handler, so that by the | ||
119 | * time adb_unregister returns, we know that the old handler isn't being | ||
120 | * called. | ||
121 | */ | ||
122 | static DECLARE_MUTEX(adb_handler_sem); | ||
123 | static DEFINE_RWLOCK(adb_handler_lock); | ||
124 | |||
125 | #if 0 | ||
126 | static void printADBreply(struct adb_request *req) | ||
127 | { | ||
128 | int i; | ||
129 | |||
130 | printk("adb reply (%d)", req->reply_len); | ||
131 | for(i = 0; i < req->reply_len; i++) | ||
132 | printk(" %x", req->reply[i]); | ||
133 | printk("\n"); | ||
134 | |||
135 | } | ||
136 | #endif | ||
137 | |||
138 | |||
139 | static __inline__ void adb_wait_ms(unsigned int ms) | ||
140 | { | ||
141 | if (current->pid && adb_probe_task_pid && | ||
142 | adb_probe_task_pid == current->pid) | ||
143 | msleep(ms); | ||
144 | else | ||
145 | mdelay(ms); | ||
146 | } | ||
147 | |||
148 | static int adb_scan_bus(void) | ||
149 | { | ||
150 | int i, highFree=0, noMovement; | ||
151 | int devmask = 0; | ||
152 | struct adb_request req; | ||
153 | |||
154 | /* assumes adb_handler[] is all zeroes at this point */ | ||
155 | for (i = 1; i < 16; i++) { | ||
156 | /* see if there is anything at address i */ | ||
157 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
158 | (i << 4) | 0xf); | ||
159 | if (req.reply_len > 1) | ||
160 | /* one or more devices at this address */ | ||
161 | adb_handler[i].original_address = i; | ||
162 | else if (i > highFree) | ||
163 | highFree = i; | ||
164 | } | ||
165 | |||
166 | /* Note we reset noMovement to 0 each time we move a device */ | ||
167 | for (noMovement = 1; noMovement < 2 && highFree > 0; noMovement++) { | ||
168 | for (i = 1; i < 16; i++) { | ||
169 | if (adb_handler[i].original_address == 0) | ||
170 | continue; | ||
171 | /* | ||
172 | * Send a "talk register 3" command to address i | ||
173 | * to provoke a collision if there is more than | ||
174 | * one device at this address. | ||
175 | */ | ||
176 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
177 | (i << 4) | 0xf); | ||
178 | /* | ||
179 | * Move the device(s) which didn't detect a | ||
180 | * collision to address `highFree'. Hopefully | ||
181 | * this only moves one device. | ||
182 | */ | ||
183 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
184 | (i<< 4) | 0xb, (highFree | 0x60), 0xfe); | ||
185 | /* | ||
186 | * See if anybody actually moved. This is suggested | ||
187 | * by HW TechNote 01: | ||
188 | * | ||
189 | * http://developer.apple.com/technotes/hw/hw_01.html | ||
190 | */ | ||
191 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
192 | (highFree << 4) | 0xf); | ||
193 | if (req.reply_len <= 1) continue; | ||
194 | /* | ||
195 | * Test whether there are any device(s) left | ||
196 | * at address i. | ||
197 | */ | ||
198 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
199 | (i << 4) | 0xf); | ||
200 | if (req.reply_len > 1) { | ||
201 | /* | ||
202 | * There are still one or more devices | ||
203 | * left at address i. Register the one(s) | ||
204 | * we moved to `highFree', and find a new | ||
205 | * value for highFree. | ||
206 | */ | ||
207 | adb_handler[highFree].original_address = | ||
208 | adb_handler[i].original_address; | ||
209 | while (highFree > 0 && | ||
210 | adb_handler[highFree].original_address) | ||
211 | highFree--; | ||
212 | if (highFree <= 0) | ||
213 | break; | ||
214 | |||
215 | noMovement = 0; | ||
216 | } | ||
217 | else { | ||
218 | /* | ||
219 | * No devices left at address i; move the | ||
220 | * one(s) we moved to `highFree' back to i. | ||
221 | */ | ||
222 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
223 | (highFree << 4) | 0xb, | ||
224 | (i | 0x60), 0xfe); | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /* Now fill in the handler_id field of the adb_handler entries. */ | ||
230 | printk(KERN_DEBUG "adb devices:"); | ||
231 | for (i = 1; i < 16; i++) { | ||
232 | if (adb_handler[i].original_address == 0) | ||
233 | continue; | ||
234 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
235 | (i << 4) | 0xf); | ||
236 | adb_handler[i].handler_id = req.reply[2]; | ||
237 | printk(" [%d]: %d %x", i, adb_handler[i].original_address, | ||
238 | adb_handler[i].handler_id); | ||
239 | devmask |= 1 << i; | ||
240 | } | ||
241 | printk("\n"); | ||
242 | return devmask; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * This kernel task handles ADB probing. It dies once probing is | ||
247 | * completed. | ||
248 | */ | ||
249 | static int | ||
250 | adb_probe_task(void *x) | ||
251 | { | ||
252 | sigset_t blocked; | ||
253 | |||
254 | strcpy(current->comm, "kadbprobe"); | ||
255 | |||
256 | sigfillset(&blocked); | ||
257 | sigprocmask(SIG_BLOCK, &blocked, NULL); | ||
258 | flush_signals(current); | ||
259 | |||
260 | printk(KERN_INFO "adb: starting probe task...\n"); | ||
261 | do_adb_reset_bus(); | ||
262 | printk(KERN_INFO "adb: finished probe task...\n"); | ||
263 | |||
264 | adb_probe_task_pid = 0; | ||
265 | up(&adb_probe_mutex); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static void | ||
271 | __adb_probe_task(void *data) | ||
272 | { | ||
273 | adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL); | ||
274 | } | ||
275 | |||
276 | static DECLARE_WORK(adb_reset_work, __adb_probe_task, NULL); | ||
277 | |||
278 | int | ||
279 | adb_reset_bus(void) | ||
280 | { | ||
281 | if (__adb_probe_sync) { | ||
282 | do_adb_reset_bus(); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | down(&adb_probe_mutex); | ||
287 | schedule_work(&adb_reset_work); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | int __init adb_init(void) | ||
292 | { | ||
293 | struct adb_driver *driver; | ||
294 | int i; | ||
295 | |||
296 | #ifdef CONFIG_PPC32 | ||
297 | if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) | ||
298 | return 0; | ||
299 | #endif | ||
300 | #ifdef CONFIG_MAC | ||
301 | if (!MACH_IS_MAC) | ||
302 | return 0; | ||
303 | #endif | ||
304 | |||
305 | /* xmon may do early-init */ | ||
306 | if (adb_inited) | ||
307 | return 0; | ||
308 | adb_inited = 1; | ||
309 | |||
310 | adb_controller = NULL; | ||
311 | |||
312 | i = 0; | ||
313 | while ((driver = adb_driver_list[i++]) != NULL) { | ||
314 | if (!driver->probe()) { | ||
315 | adb_controller = driver; | ||
316 | break; | ||
317 | } | ||
318 | } | ||
319 | if ((adb_controller == NULL) || adb_controller->init()) { | ||
320 | printk(KERN_WARNING "Warning: no ADB interface detected\n"); | ||
321 | adb_controller = NULL; | ||
322 | } else { | ||
323 | #ifdef CONFIG_PMAC_PBOOK | ||
324 | pmu_register_sleep_notifier(&adb_sleep_notifier); | ||
325 | #endif /* CONFIG_PMAC_PBOOK */ | ||
326 | #ifdef CONFIG_PPC | ||
327 | if (machine_is_compatible("AAPL,PowerBook1998") || | ||
328 | machine_is_compatible("PowerBook1,1")) | ||
329 | sleepy_trackpad = 1; | ||
330 | #endif /* CONFIG_PPC */ | ||
331 | init_completion(&adb_probe_task_comp); | ||
332 | adbdev_init(); | ||
333 | adb_reset_bus(); | ||
334 | } | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | __initcall(adb_init); | ||
339 | |||
340 | #ifdef CONFIG_PMAC_PBOOK | ||
341 | /* | ||
342 | * notify clients before sleep and reset bus afterwards | ||
343 | */ | ||
344 | int | ||
345 | adb_notify_sleep(struct pmu_sleep_notifier *self, int when) | ||
346 | { | ||
347 | int ret; | ||
348 | |||
349 | switch (when) { | ||
350 | case PBOOK_SLEEP_REQUEST: | ||
351 | adb_got_sleep = 1; | ||
352 | /* We need to get a lock on the probe thread */ | ||
353 | down(&adb_probe_mutex); | ||
354 | /* Stop autopoll */ | ||
355 | if (adb_controller->autopoll) | ||
356 | adb_controller->autopoll(0); | ||
357 | ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL); | ||
358 | if (ret & NOTIFY_STOP_MASK) { | ||
359 | up(&adb_probe_mutex); | ||
360 | return PBOOK_SLEEP_REFUSE; | ||
361 | } | ||
362 | break; | ||
363 | case PBOOK_SLEEP_REJECT: | ||
364 | if (adb_got_sleep) { | ||
365 | adb_got_sleep = 0; | ||
366 | up(&adb_probe_mutex); | ||
367 | adb_reset_bus(); | ||
368 | } | ||
369 | break; | ||
370 | |||
371 | case PBOOK_SLEEP_NOW: | ||
372 | break; | ||
373 | case PBOOK_WAKE: | ||
374 | adb_got_sleep = 0; | ||
375 | up(&adb_probe_mutex); | ||
376 | adb_reset_bus(); | ||
377 | break; | ||
378 | } | ||
379 | return PBOOK_SLEEP_OK; | ||
380 | } | ||
381 | #endif /* CONFIG_PMAC_PBOOK */ | ||
382 | |||
383 | static int | ||
384 | do_adb_reset_bus(void) | ||
385 | { | ||
386 | int ret, nret; | ||
387 | |||
388 | if (adb_controller == NULL) | ||
389 | return -ENXIO; | ||
390 | |||
391 | if (adb_controller->autopoll) | ||
392 | adb_controller->autopoll(0); | ||
393 | |||
394 | nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL); | ||
395 | if (nret & NOTIFY_STOP_MASK) { | ||
396 | if (adb_controller->autopoll) | ||
397 | adb_controller->autopoll(autopoll_devs); | ||
398 | return -EBUSY; | ||
399 | } | ||
400 | |||
401 | if (sleepy_trackpad) { | ||
402 | /* Let the trackpad settle down */ | ||
403 | adb_wait_ms(500); | ||
404 | } | ||
405 | |||
406 | down(&adb_handler_sem); | ||
407 | write_lock_irq(&adb_handler_lock); | ||
408 | memset(adb_handler, 0, sizeof(adb_handler)); | ||
409 | write_unlock_irq(&adb_handler_lock); | ||
410 | |||
411 | /* That one is still a bit synchronous, oh well... */ | ||
412 | if (adb_controller->reset_bus) | ||
413 | ret = adb_controller->reset_bus(); | ||
414 | else | ||
415 | ret = 0; | ||
416 | |||
417 | if (sleepy_trackpad) { | ||
418 | /* Let the trackpad settle down */ | ||
419 | adb_wait_ms(1500); | ||
420 | } | ||
421 | |||
422 | if (!ret) { | ||
423 | autopoll_devs = adb_scan_bus(); | ||
424 | if (adb_controller->autopoll) | ||
425 | adb_controller->autopoll(autopoll_devs); | ||
426 | } | ||
427 | up(&adb_handler_sem); | ||
428 | |||
429 | nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL); | ||
430 | if (nret & NOTIFY_STOP_MASK) | ||
431 | return -EBUSY; | ||
432 | |||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | void | ||
437 | adb_poll(void) | ||
438 | { | ||
439 | if ((adb_controller == NULL)||(adb_controller->poll == NULL)) | ||
440 | return; | ||
441 | adb_controller->poll(); | ||
442 | } | ||
443 | |||
444 | static void | ||
445 | adb_probe_wakeup(struct adb_request *req) | ||
446 | { | ||
447 | complete(&adb_probe_task_comp); | ||
448 | } | ||
449 | |||
450 | /* Static request used during probe */ | ||
451 | static struct adb_request adb_sreq; | ||
452 | static unsigned long adb_sreq_lock; // Use semaphore ! */ | ||
453 | |||
454 | int | ||
455 | adb_request(struct adb_request *req, void (*done)(struct adb_request *), | ||
456 | int flags, int nbytes, ...) | ||
457 | { | ||
458 | va_list list; | ||
459 | int i, use_sreq; | ||
460 | int rc; | ||
461 | |||
462 | if ((adb_controller == NULL) || (adb_controller->send_request == NULL)) | ||
463 | return -ENXIO; | ||
464 | if (nbytes < 1) | ||
465 | return -EINVAL; | ||
466 | if (req == NULL && (flags & ADBREQ_NOSEND)) | ||
467 | return -EINVAL; | ||
468 | |||
469 | if (req == NULL) { | ||
470 | if (test_and_set_bit(0,&adb_sreq_lock)) { | ||
471 | printk("adb.c: Warning: contention on static request !\n"); | ||
472 | return -EPERM; | ||
473 | } | ||
474 | req = &adb_sreq; | ||
475 | flags |= ADBREQ_SYNC; | ||
476 | use_sreq = 1; | ||
477 | } else | ||
478 | use_sreq = 0; | ||
479 | req->nbytes = nbytes+1; | ||
480 | req->done = done; | ||
481 | req->reply_expected = flags & ADBREQ_REPLY; | ||
482 | req->data[0] = ADB_PACKET; | ||
483 | va_start(list, nbytes); | ||
484 | for (i = 0; i < nbytes; ++i) | ||
485 | req->data[i+1] = va_arg(list, int); | ||
486 | va_end(list); | ||
487 | |||
488 | if (flags & ADBREQ_NOSEND) | ||
489 | return 0; | ||
490 | |||
491 | /* Synchronous requests send from the probe thread cause it to | ||
492 | * block. Beware that the "done" callback will be overriden ! | ||
493 | */ | ||
494 | if ((flags & ADBREQ_SYNC) && | ||
495 | (current->pid && adb_probe_task_pid && | ||
496 | adb_probe_task_pid == current->pid)) { | ||
497 | req->done = adb_probe_wakeup; | ||
498 | rc = adb_controller->send_request(req, 0); | ||
499 | if (rc || req->complete) | ||
500 | goto bail; | ||
501 | wait_for_completion(&adb_probe_task_comp); | ||
502 | rc = 0; | ||
503 | goto bail; | ||
504 | } | ||
505 | |||
506 | rc = adb_controller->send_request(req, flags & ADBREQ_SYNC); | ||
507 | bail: | ||
508 | if (use_sreq) | ||
509 | clear_bit(0, &adb_sreq_lock); | ||
510 | |||
511 | return rc; | ||
512 | } | ||
513 | |||
514 | /* Ultimately this should return the number of devices with | ||
515 | the given default id. | ||
516 | And it does it now ! Note: changed behaviour: This function | ||
517 | will now register if default_id _and_ handler_id both match | ||
518 | but handler_id can be left to 0 to match with default_id only. | ||
519 | When handler_id is set, this function will try to adjust | ||
520 | the handler_id id it doesn't match. */ | ||
521 | int | ||
522 | adb_register(int default_id, int handler_id, struct adb_ids *ids, | ||
523 | void (*handler)(unsigned char *, int, struct pt_regs *, int)) | ||
524 | { | ||
525 | int i; | ||
526 | |||
527 | down(&adb_handler_sem); | ||
528 | ids->nids = 0; | ||
529 | for (i = 1; i < 16; i++) { | ||
530 | if ((adb_handler[i].original_address == default_id) && | ||
531 | (!handler_id || (handler_id == adb_handler[i].handler_id) || | ||
532 | try_handler_change(i, handler_id))) { | ||
533 | if (adb_handler[i].handler != 0) { | ||
534 | printk(KERN_ERR | ||
535 | "Two handlers for ADB device %d\n", | ||
536 | default_id); | ||
537 | continue; | ||
538 | } | ||
539 | write_lock_irq(&adb_handler_lock); | ||
540 | adb_handler[i].handler = handler; | ||
541 | write_unlock_irq(&adb_handler_lock); | ||
542 | ids->id[ids->nids++] = i; | ||
543 | } | ||
544 | } | ||
545 | up(&adb_handler_sem); | ||
546 | return ids->nids; | ||
547 | } | ||
548 | |||
549 | int | ||
550 | adb_unregister(int index) | ||
551 | { | ||
552 | int ret = -ENODEV; | ||
553 | |||
554 | down(&adb_handler_sem); | ||
555 | write_lock_irq(&adb_handler_lock); | ||
556 | if (adb_handler[index].handler) { | ||
557 | while(adb_handler[index].busy) { | ||
558 | write_unlock_irq(&adb_handler_lock); | ||
559 | yield(); | ||
560 | write_lock_irq(&adb_handler_lock); | ||
561 | } | ||
562 | ret = 0; | ||
563 | adb_handler[index].handler = NULL; | ||
564 | } | ||
565 | write_unlock_irq(&adb_handler_lock); | ||
566 | up(&adb_handler_sem); | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | void | ||
571 | adb_input(unsigned char *buf, int nb, struct pt_regs *regs, int autopoll) | ||
572 | { | ||
573 | int i, id; | ||
574 | static int dump_adb_input = 0; | ||
575 | unsigned long flags; | ||
576 | |||
577 | void (*handler)(unsigned char *, int, struct pt_regs *, int); | ||
578 | |||
579 | /* We skip keystrokes and mouse moves when the sleep process | ||
580 | * has been started. We stop autopoll, but this is another security | ||
581 | */ | ||
582 | if (adb_got_sleep) | ||
583 | return; | ||
584 | |||
585 | id = buf[0] >> 4; | ||
586 | if (dump_adb_input) { | ||
587 | printk(KERN_INFO "adb packet: "); | ||
588 | for (i = 0; i < nb; ++i) | ||
589 | printk(" %x", buf[i]); | ||
590 | printk(", id = %d\n", id); | ||
591 | } | ||
592 | write_lock_irqsave(&adb_handler_lock, flags); | ||
593 | handler = adb_handler[id].handler; | ||
594 | if (handler != NULL) | ||
595 | adb_handler[id].busy = 1; | ||
596 | write_unlock_irqrestore(&adb_handler_lock, flags); | ||
597 | if (handler != NULL) { | ||
598 | (*handler)(buf, nb, regs, autopoll); | ||
599 | wmb(); | ||
600 | adb_handler[id].busy = 0; | ||
601 | } | ||
602 | |||
603 | } | ||
604 | |||
605 | /* Try to change handler to new_id. Will return 1 if successful. */ | ||
606 | static int try_handler_change(int address, int new_id) | ||
607 | { | ||
608 | struct adb_request req; | ||
609 | |||
610 | if (adb_handler[address].handler_id == new_id) | ||
611 | return 1; | ||
612 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
613 | ADB_WRITEREG(address, 3), address | 0x20, new_id); | ||
614 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
615 | ADB_READREG(address, 3)); | ||
616 | if (req.reply_len < 2) | ||
617 | return 0; | ||
618 | if (req.reply[2] != new_id) | ||
619 | return 0; | ||
620 | adb_handler[address].handler_id = req.reply[2]; | ||
621 | |||
622 | return 1; | ||
623 | } | ||
624 | |||
625 | int | ||
626 | adb_try_handler_change(int address, int new_id) | ||
627 | { | ||
628 | int ret; | ||
629 | |||
630 | down(&adb_handler_sem); | ||
631 | ret = try_handler_change(address, new_id); | ||
632 | up(&adb_handler_sem); | ||
633 | return ret; | ||
634 | } | ||
635 | |||
636 | int | ||
637 | adb_get_infos(int address, int *original_address, int *handler_id) | ||
638 | { | ||
639 | down(&adb_handler_sem); | ||
640 | *original_address = adb_handler[address].original_address; | ||
641 | *handler_id = adb_handler[address].handler_id; | ||
642 | up(&adb_handler_sem); | ||
643 | |||
644 | return (*original_address != 0); | ||
645 | } | ||
646 | |||
647 | |||
648 | /* | ||
649 | * /dev/adb device driver. | ||
650 | */ | ||
651 | |||
652 | #define ADB_MAJOR 56 /* major number for /dev/adb */ | ||
653 | |||
654 | struct adbdev_state { | ||
655 | spinlock_t lock; | ||
656 | atomic_t n_pending; | ||
657 | struct adb_request *completed; | ||
658 | wait_queue_head_t wait_queue; | ||
659 | int inuse; | ||
660 | }; | ||
661 | |||
662 | static void adb_write_done(struct adb_request *req) | ||
663 | { | ||
664 | struct adbdev_state *state = (struct adbdev_state *) req->arg; | ||
665 | unsigned long flags; | ||
666 | |||
667 | if (!req->complete) { | ||
668 | req->reply_len = 0; | ||
669 | req->complete = 1; | ||
670 | } | ||
671 | spin_lock_irqsave(&state->lock, flags); | ||
672 | atomic_dec(&state->n_pending); | ||
673 | if (!state->inuse) { | ||
674 | kfree(req); | ||
675 | if (atomic_read(&state->n_pending) == 0) { | ||
676 | spin_unlock_irqrestore(&state->lock, flags); | ||
677 | kfree(state); | ||
678 | return; | ||
679 | } | ||
680 | } else { | ||
681 | struct adb_request **ap = &state->completed; | ||
682 | while (*ap != NULL) | ||
683 | ap = &(*ap)->next; | ||
684 | req->next = NULL; | ||
685 | *ap = req; | ||
686 | wake_up_interruptible(&state->wait_queue); | ||
687 | } | ||
688 | spin_unlock_irqrestore(&state->lock, flags); | ||
689 | } | ||
690 | |||
691 | static int | ||
692 | do_adb_query(struct adb_request *req) | ||
693 | { | ||
694 | int ret = -EINVAL; | ||
695 | |||
696 | switch(req->data[1]) | ||
697 | { | ||
698 | case ADB_QUERY_GETDEVINFO: | ||
699 | if (req->nbytes < 3) | ||
700 | break; | ||
701 | down(&adb_handler_sem); | ||
702 | req->reply[0] = adb_handler[req->data[2]].original_address; | ||
703 | req->reply[1] = adb_handler[req->data[2]].handler_id; | ||
704 | up(&adb_handler_sem); | ||
705 | req->complete = 1; | ||
706 | req->reply_len = 2; | ||
707 | adb_write_done(req); | ||
708 | ret = 0; | ||
709 | break; | ||
710 | } | ||
711 | return ret; | ||
712 | } | ||
713 | |||
714 | static int adb_open(struct inode *inode, struct file *file) | ||
715 | { | ||
716 | struct adbdev_state *state; | ||
717 | |||
718 | if (iminor(inode) > 0 || adb_controller == NULL) | ||
719 | return -ENXIO; | ||
720 | state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL); | ||
721 | if (state == 0) | ||
722 | return -ENOMEM; | ||
723 | file->private_data = state; | ||
724 | spin_lock_init(&state->lock); | ||
725 | atomic_set(&state->n_pending, 0); | ||
726 | state->completed = NULL; | ||
727 | init_waitqueue_head(&state->wait_queue); | ||
728 | state->inuse = 1; | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static int adb_release(struct inode *inode, struct file *file) | ||
734 | { | ||
735 | struct adbdev_state *state = file->private_data; | ||
736 | unsigned long flags; | ||
737 | |||
738 | lock_kernel(); | ||
739 | if (state) { | ||
740 | file->private_data = NULL; | ||
741 | spin_lock_irqsave(&state->lock, flags); | ||
742 | if (atomic_read(&state->n_pending) == 0 | ||
743 | && state->completed == NULL) { | ||
744 | spin_unlock_irqrestore(&state->lock, flags); | ||
745 | kfree(state); | ||
746 | } else { | ||
747 | state->inuse = 0; | ||
748 | spin_unlock_irqrestore(&state->lock, flags); | ||
749 | } | ||
750 | } | ||
751 | unlock_kernel(); | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static ssize_t adb_read(struct file *file, char __user *buf, | ||
756 | size_t count, loff_t *ppos) | ||
757 | { | ||
758 | int ret = 0; | ||
759 | struct adbdev_state *state = file->private_data; | ||
760 | struct adb_request *req; | ||
761 | wait_queue_t wait = __WAITQUEUE_INITIALIZER(wait,current); | ||
762 | unsigned long flags; | ||
763 | |||
764 | if (count < 2) | ||
765 | return -EINVAL; | ||
766 | if (count > sizeof(req->reply)) | ||
767 | count = sizeof(req->reply); | ||
768 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
769 | return -EFAULT; | ||
770 | |||
771 | req = NULL; | ||
772 | spin_lock_irqsave(&state->lock, flags); | ||
773 | add_wait_queue(&state->wait_queue, &wait); | ||
774 | current->state = TASK_INTERRUPTIBLE; | ||
775 | |||
776 | for (;;) { | ||
777 | req = state->completed; | ||
778 | if (req != NULL) | ||
779 | state->completed = req->next; | ||
780 | else if (atomic_read(&state->n_pending) == 0) | ||
781 | ret = -EIO; | ||
782 | if (req != NULL || ret != 0) | ||
783 | break; | ||
784 | |||
785 | if (file->f_flags & O_NONBLOCK) { | ||
786 | ret = -EAGAIN; | ||
787 | break; | ||
788 | } | ||
789 | if (signal_pending(current)) { | ||
790 | ret = -ERESTARTSYS; | ||
791 | break; | ||
792 | } | ||
793 | spin_unlock_irqrestore(&state->lock, flags); | ||
794 | schedule(); | ||
795 | spin_lock_irqsave(&state->lock, flags); | ||
796 | } | ||
797 | |||
798 | current->state = TASK_RUNNING; | ||
799 | remove_wait_queue(&state->wait_queue, &wait); | ||
800 | spin_unlock_irqrestore(&state->lock, flags); | ||
801 | |||
802 | if (ret) | ||
803 | return ret; | ||
804 | |||
805 | ret = req->reply_len; | ||
806 | if (ret > count) | ||
807 | ret = count; | ||
808 | if (ret > 0 && copy_to_user(buf, req->reply, ret)) | ||
809 | ret = -EFAULT; | ||
810 | |||
811 | kfree(req); | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static ssize_t adb_write(struct file *file, const char __user *buf, | ||
816 | size_t count, loff_t *ppos) | ||
817 | { | ||
818 | int ret/*, i*/; | ||
819 | struct adbdev_state *state = file->private_data; | ||
820 | struct adb_request *req; | ||
821 | |||
822 | if (count < 2 || count > sizeof(req->data)) | ||
823 | return -EINVAL; | ||
824 | if (adb_controller == NULL) | ||
825 | return -ENXIO; | ||
826 | if (!access_ok(VERIFY_READ, buf, count)) | ||
827 | return -EFAULT; | ||
828 | |||
829 | req = (struct adb_request *) kmalloc(sizeof(struct adb_request), | ||
830 | GFP_KERNEL); | ||
831 | if (req == NULL) | ||
832 | return -ENOMEM; | ||
833 | |||
834 | req->nbytes = count; | ||
835 | req->done = adb_write_done; | ||
836 | req->arg = (void *) state; | ||
837 | req->complete = 0; | ||
838 | |||
839 | ret = -EFAULT; | ||
840 | if (copy_from_user(req->data, buf, count)) | ||
841 | goto out; | ||
842 | |||
843 | atomic_inc(&state->n_pending); | ||
844 | |||
845 | /* If a probe is in progress or we are sleeping, wait for it to complete */ | ||
846 | down(&adb_probe_mutex); | ||
847 | |||
848 | /* Queries are special requests sent to the ADB driver itself */ | ||
849 | if (req->data[0] == ADB_QUERY) { | ||
850 | if (count > 1) | ||
851 | ret = do_adb_query(req); | ||
852 | else | ||
853 | ret = -EINVAL; | ||
854 | up(&adb_probe_mutex); | ||
855 | } | ||
856 | /* Special case for ADB_BUSRESET request, all others are sent to | ||
857 | the controller */ | ||
858 | else if ((req->data[0] == ADB_PACKET)&&(count > 1) | ||
859 | &&(req->data[1] == ADB_BUSRESET)) { | ||
860 | ret = do_adb_reset_bus(); | ||
861 | up(&adb_probe_mutex); | ||
862 | atomic_dec(&state->n_pending); | ||
863 | if (ret == 0) | ||
864 | ret = count; | ||
865 | goto out; | ||
866 | } else { | ||
867 | req->reply_expected = ((req->data[1] & 0xc) == 0xc); | ||
868 | if (adb_controller && adb_controller->send_request) | ||
869 | ret = adb_controller->send_request(req, 0); | ||
870 | else | ||
871 | ret = -ENXIO; | ||
872 | up(&adb_probe_mutex); | ||
873 | } | ||
874 | |||
875 | if (ret != 0) { | ||
876 | atomic_dec(&state->n_pending); | ||
877 | goto out; | ||
878 | } | ||
879 | return count; | ||
880 | |||
881 | out: | ||
882 | kfree(req); | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | static struct file_operations adb_fops = { | ||
887 | .owner = THIS_MODULE, | ||
888 | .llseek = no_llseek, | ||
889 | .read = adb_read, | ||
890 | .write = adb_write, | ||
891 | .open = adb_open, | ||
892 | .release = adb_release, | ||
893 | }; | ||
894 | |||
895 | static void | ||
896 | adbdev_init(void) | ||
897 | { | ||
898 | if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) { | ||
899 | printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); | ||
900 | return; | ||
901 | } | ||
902 | |||
903 | devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR, "adb"); | ||
904 | |||
905 | adb_dev_class = class_simple_create(THIS_MODULE, "adb"); | ||
906 | if (IS_ERR(adb_dev_class)) { | ||
907 | return; | ||
908 | } | ||
909 | class_simple_device_add(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb"); | ||
910 | } | ||
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c new file mode 100644 index 000000000000..8f93d01d8928 --- /dev/null +++ b/drivers/macintosh/adbhid.c | |||
@@ -0,0 +1,1177 @@ | |||
1 | /* | ||
2 | * drivers/input/adbhid.c | ||
3 | * | ||
4 | * ADB HID driver for Power Macintosh computers. | ||
5 | * | ||
6 | * Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl. | ||
7 | * drivers/macintosh/mac_keyb.c was Copyright (C) 1996 Paul Mackerras | ||
8 | * with considerable contributions from Ben Herrenschmidt and others. | ||
9 | * | ||
10 | * Copyright (C) 2000 Franz Sirl. | ||
11 | * | ||
12 | * Adapted to ADB changes and support for more devices by | ||
13 | * Benjamin Herrenschmidt. Adapted from code in MkLinux | ||
14 | * and reworked. | ||
15 | * | ||
16 | * Supported devices: | ||
17 | * | ||
18 | * - Standard 1 button mouse | ||
19 | * - All standard Apple Extended protocol (handler ID 4) | ||
20 | * - mouseman and trackman mice & trackballs | ||
21 | * - PowerBook Trackpad (default setup: enable tapping) | ||
22 | * - MicroSpeed mouse & trackball (needs testing) | ||
23 | * - CH Products Trackball Pro (needs testing) | ||
24 | * - Contour Design (Contour Mouse) | ||
25 | * - Hunter digital (NoHandsMouse) | ||
26 | * - Kensignton TurboMouse 5 (needs testing) | ||
27 | * - Mouse Systems A3 mice and trackballs <aidan@kublai.com> | ||
28 | * - MacAlly 2-buttons mouse (needs testing) <pochini@denise.shiny.it> | ||
29 | * | ||
30 | * To do: | ||
31 | * | ||
32 | * Improve Kensington support. | ||
33 | * Split mouse/kbd | ||
34 | * Move to syfs | ||
35 | */ | ||
36 | |||
37 | #include <linux/config.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/notifier.h> | ||
42 | #include <linux/input.h> | ||
43 | |||
44 | #include <linux/adb.h> | ||
45 | #include <linux/cuda.h> | ||
46 | #include <linux/pmu.h> | ||
47 | |||
48 | #include <asm/machdep.h> | ||
49 | #ifdef CONFIG_PPC_PMAC | ||
50 | #include <asm/pmac_feature.h> | ||
51 | #endif | ||
52 | |||
53 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
54 | #include <asm/backlight.h> | ||
55 | #endif | ||
56 | |||
57 | MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); | ||
58 | |||
59 | #define KEYB_KEYREG 0 /* register # for key up/down data */ | ||
60 | #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ | ||
61 | #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ | ||
62 | |||
63 | static int adb_message_handler(struct notifier_block *, unsigned long, void *); | ||
64 | static struct notifier_block adbhid_adb_notifier = { | ||
65 | .notifier_call = adb_message_handler, | ||
66 | }; | ||
67 | |||
68 | /* Some special keys */ | ||
69 | #define ADB_KEY_DEL 0x33 | ||
70 | #define ADB_KEY_CMD 0x37 | ||
71 | #define ADB_KEY_CAPSLOCK 0x39 | ||
72 | #define ADB_KEY_FN 0x3f | ||
73 | #define ADB_KEY_FWDEL 0x75 | ||
74 | #define ADB_KEY_POWER_OLD 0x7e | ||
75 | #define ADB_KEY_POWER 0x7f | ||
76 | |||
77 | u8 adb_to_linux_keycodes[128] = { | ||
78 | /* 0x00 */ KEY_A, /* 30 */ | ||
79 | /* 0x01 */ KEY_S, /* 31 */ | ||
80 | /* 0x02 */ KEY_D, /* 32 */ | ||
81 | /* 0x03 */ KEY_F, /* 33 */ | ||
82 | /* 0x04 */ KEY_H, /* 35 */ | ||
83 | /* 0x05 */ KEY_G, /* 34 */ | ||
84 | /* 0x06 */ KEY_Z, /* 44 */ | ||
85 | /* 0x07 */ KEY_X, /* 45 */ | ||
86 | /* 0x08 */ KEY_C, /* 46 */ | ||
87 | /* 0x09 */ KEY_V, /* 47 */ | ||
88 | /* 0x0a */ KEY_102ND, /* 86 */ | ||
89 | /* 0x0b */ KEY_B, /* 48 */ | ||
90 | /* 0x0c */ KEY_Q, /* 16 */ | ||
91 | /* 0x0d */ KEY_W, /* 17 */ | ||
92 | /* 0x0e */ KEY_E, /* 18 */ | ||
93 | /* 0x0f */ KEY_R, /* 19 */ | ||
94 | /* 0x10 */ KEY_Y, /* 21 */ | ||
95 | /* 0x11 */ KEY_T, /* 20 */ | ||
96 | /* 0x12 */ KEY_1, /* 2 */ | ||
97 | /* 0x13 */ KEY_2, /* 3 */ | ||
98 | /* 0x14 */ KEY_3, /* 4 */ | ||
99 | /* 0x15 */ KEY_4, /* 5 */ | ||
100 | /* 0x16 */ KEY_6, /* 7 */ | ||
101 | /* 0x17 */ KEY_5, /* 6 */ | ||
102 | /* 0x18 */ KEY_EQUAL, /* 13 */ | ||
103 | /* 0x19 */ KEY_9, /* 10 */ | ||
104 | /* 0x1a */ KEY_7, /* 8 */ | ||
105 | /* 0x1b */ KEY_MINUS, /* 12 */ | ||
106 | /* 0x1c */ KEY_8, /* 9 */ | ||
107 | /* 0x1d */ KEY_0, /* 11 */ | ||
108 | /* 0x1e */ KEY_RIGHTBRACE, /* 27 */ | ||
109 | /* 0x1f */ KEY_O, /* 24 */ | ||
110 | /* 0x20 */ KEY_U, /* 22 */ | ||
111 | /* 0x21 */ KEY_LEFTBRACE, /* 26 */ | ||
112 | /* 0x22 */ KEY_I, /* 23 */ | ||
113 | /* 0x23 */ KEY_P, /* 25 */ | ||
114 | /* 0x24 */ KEY_ENTER, /* 28 */ | ||
115 | /* 0x25 */ KEY_L, /* 38 */ | ||
116 | /* 0x26 */ KEY_J, /* 36 */ | ||
117 | /* 0x27 */ KEY_APOSTROPHE, /* 40 */ | ||
118 | /* 0x28 */ KEY_K, /* 37 */ | ||
119 | /* 0x29 */ KEY_SEMICOLON, /* 39 */ | ||
120 | /* 0x2a */ KEY_BACKSLASH, /* 43 */ | ||
121 | /* 0x2b */ KEY_COMMA, /* 51 */ | ||
122 | /* 0x2c */ KEY_SLASH, /* 53 */ | ||
123 | /* 0x2d */ KEY_N, /* 49 */ | ||
124 | /* 0x2e */ KEY_M, /* 50 */ | ||
125 | /* 0x2f */ KEY_DOT, /* 52 */ | ||
126 | /* 0x30 */ KEY_TAB, /* 15 */ | ||
127 | /* 0x31 */ KEY_SPACE, /* 57 */ | ||
128 | /* 0x32 */ KEY_GRAVE, /* 41 */ | ||
129 | /* 0x33 */ KEY_BACKSPACE, /* 14 */ | ||
130 | /* 0x34 */ KEY_KPENTER, /* 96 */ | ||
131 | /* 0x35 */ KEY_ESC, /* 1 */ | ||
132 | /* 0x36 */ KEY_LEFTCTRL, /* 29 */ | ||
133 | /* 0x37 */ KEY_LEFTMETA, /* 125 */ | ||
134 | /* 0x38 */ KEY_LEFTSHIFT, /* 42 */ | ||
135 | /* 0x39 */ KEY_CAPSLOCK, /* 58 */ | ||
136 | /* 0x3a */ KEY_LEFTALT, /* 56 */ | ||
137 | /* 0x3b */ KEY_LEFT, /* 105 */ | ||
138 | /* 0x3c */ KEY_RIGHT, /* 106 */ | ||
139 | /* 0x3d */ KEY_DOWN, /* 108 */ | ||
140 | /* 0x3e */ KEY_UP, /* 103 */ | ||
141 | /* 0x3f */ 0, | ||
142 | /* 0x40 */ 0, | ||
143 | /* 0x41 */ KEY_KPDOT, /* 83 */ | ||
144 | /* 0x42 */ 0, | ||
145 | /* 0x43 */ KEY_KPASTERISK, /* 55 */ | ||
146 | /* 0x44 */ 0, | ||
147 | /* 0x45 */ KEY_KPPLUS, /* 78 */ | ||
148 | /* 0x46 */ 0, | ||
149 | /* 0x47 */ KEY_NUMLOCK, /* 69 */ | ||
150 | /* 0x48 */ 0, | ||
151 | /* 0x49 */ 0, | ||
152 | /* 0x4a */ 0, | ||
153 | /* 0x4b */ KEY_KPSLASH, /* 98 */ | ||
154 | /* 0x4c */ KEY_KPENTER, /* 96 */ | ||
155 | /* 0x4d */ 0, | ||
156 | /* 0x4e */ KEY_KPMINUS, /* 74 */ | ||
157 | /* 0x4f */ 0, | ||
158 | /* 0x50 */ 0, | ||
159 | /* 0x51 */ KEY_KPEQUAL, /* 117 */ | ||
160 | /* 0x52 */ KEY_KP0, /* 82 */ | ||
161 | /* 0x53 */ KEY_KP1, /* 79 */ | ||
162 | /* 0x54 */ KEY_KP2, /* 80 */ | ||
163 | /* 0x55 */ KEY_KP3, /* 81 */ | ||
164 | /* 0x56 */ KEY_KP4, /* 75 */ | ||
165 | /* 0x57 */ KEY_KP5, /* 76 */ | ||
166 | /* 0x58 */ KEY_KP6, /* 77 */ | ||
167 | /* 0x59 */ KEY_KP7, /* 71 */ | ||
168 | /* 0x5a */ 0, | ||
169 | /* 0x5b */ KEY_KP8, /* 72 */ | ||
170 | /* 0x5c */ KEY_KP9, /* 73 */ | ||
171 | /* 0x5d */ KEY_YEN, /* 124 */ | ||
172 | /* 0x5e */ KEY_RO, /* 89 */ | ||
173 | /* 0x5f */ KEY_KPCOMMA, /* 121 */ | ||
174 | /* 0x60 */ KEY_F5, /* 63 */ | ||
175 | /* 0x61 */ KEY_F6, /* 64 */ | ||
176 | /* 0x62 */ KEY_F7, /* 65 */ | ||
177 | /* 0x63 */ KEY_F3, /* 61 */ | ||
178 | /* 0x64 */ KEY_F8, /* 66 */ | ||
179 | /* 0x65 */ KEY_F9, /* 67 */ | ||
180 | /* 0x66 */ KEY_HANJA, /* 123 */ | ||
181 | /* 0x67 */ KEY_F11, /* 87 */ | ||
182 | /* 0x68 */ KEY_HANGUEL, /* 122 */ | ||
183 | /* 0x69 */ KEY_SYSRQ, /* 99 */ | ||
184 | /* 0x6a */ 0, | ||
185 | /* 0x6b */ KEY_SCROLLLOCK, /* 70 */ | ||
186 | /* 0x6c */ 0, | ||
187 | /* 0x6d */ KEY_F10, /* 68 */ | ||
188 | /* 0x6e */ KEY_COMPOSE, /* 127 */ | ||
189 | /* 0x6f */ KEY_F12, /* 88 */ | ||
190 | /* 0x70 */ 0, | ||
191 | /* 0x71 */ KEY_PAUSE, /* 119 */ | ||
192 | /* 0x72 */ KEY_INSERT, /* 110 */ | ||
193 | /* 0x73 */ KEY_HOME, /* 102 */ | ||
194 | /* 0x74 */ KEY_PAGEUP, /* 104 */ | ||
195 | /* 0x75 */ KEY_DELETE, /* 111 */ | ||
196 | /* 0x76 */ KEY_F4, /* 62 */ | ||
197 | /* 0x77 */ KEY_END, /* 107 */ | ||
198 | /* 0x78 */ KEY_F2, /* 60 */ | ||
199 | /* 0x79 */ KEY_PAGEDOWN, /* 109 */ | ||
200 | /* 0x7a */ KEY_F1, /* 59 */ | ||
201 | /* 0x7b */ KEY_RIGHTSHIFT, /* 54 */ | ||
202 | /* 0x7c */ KEY_RIGHTALT, /* 100 */ | ||
203 | /* 0x7d */ KEY_RIGHTCTRL, /* 97 */ | ||
204 | /* 0x7e */ KEY_RIGHTMETA, /* 126 */ | ||
205 | /* 0x7f */ KEY_POWER, /* 116 */ | ||
206 | }; | ||
207 | |||
208 | struct adbhid { | ||
209 | struct input_dev input; | ||
210 | int id; | ||
211 | int default_id; | ||
212 | int original_handler_id; | ||
213 | int current_handler_id; | ||
214 | int mouse_kind; | ||
215 | unsigned char *keycode; | ||
216 | char name[64]; | ||
217 | char phys[32]; | ||
218 | int flags; | ||
219 | }; | ||
220 | |||
221 | #define FLAG_FN_KEY_PRESSED 0x00000001 | ||
222 | #define FLAG_POWER_FROM_FN 0x00000002 | ||
223 | #define FLAG_EMU_FWDEL_DOWN 0x00000004 | ||
224 | |||
225 | static struct adbhid *adbhid[16]; | ||
226 | |||
227 | static void adbhid_probe(void); | ||
228 | |||
229 | static void adbhid_input_keycode(int, int, int, struct pt_regs *); | ||
230 | |||
231 | static void init_trackpad(int id); | ||
232 | static void init_trackball(int id); | ||
233 | static void init_turbomouse(int id); | ||
234 | static void init_microspeed(int id); | ||
235 | static void init_ms_a3(int id); | ||
236 | |||
237 | static struct adb_ids keyboard_ids; | ||
238 | static struct adb_ids mouse_ids; | ||
239 | static struct adb_ids buttons_ids; | ||
240 | |||
241 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
242 | /* Exported to via-pmu.c */ | ||
243 | int disable_kernel_backlight = 0; | ||
244 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
245 | |||
246 | /* Kind of keyboard, see Apple technote 1152 */ | ||
247 | #define ADB_KEYBOARD_UNKNOWN 0 | ||
248 | #define ADB_KEYBOARD_ANSI 0x0100 | ||
249 | #define ADB_KEYBOARD_ISO 0x0200 | ||
250 | #define ADB_KEYBOARD_JIS 0x0300 | ||
251 | |||
252 | /* Kind of mouse */ | ||
253 | #define ADBMOUSE_STANDARD_100 0 /* Standard 100cpi mouse (handler 1) */ | ||
254 | #define ADBMOUSE_STANDARD_200 1 /* Standard 200cpi mouse (handler 2) */ | ||
255 | #define ADBMOUSE_EXTENDED 2 /* Apple Extended mouse (handler 4) */ | ||
256 | #define ADBMOUSE_TRACKBALL 3 /* TrackBall (handler 4) */ | ||
257 | #define ADBMOUSE_TRACKPAD 4 /* Apple's PowerBook trackpad (handler 4) */ | ||
258 | #define ADBMOUSE_TURBOMOUSE5 5 /* Turbomouse 5 (previously req. mousehack) */ | ||
259 | #define ADBMOUSE_MICROSPEED 6 /* Microspeed mouse (&trackball ?), MacPoint */ | ||
260 | #define ADBMOUSE_TRACKBALLPRO 7 /* Trackball Pro (special buttons) */ | ||
261 | #define ADBMOUSE_MS_A3 8 /* Mouse systems A3 trackball (handler 3) */ | ||
262 | #define ADBMOUSE_MACALLY2 9 /* MacAlly 2-button mouse */ | ||
263 | |||
264 | static void | ||
265 | adbhid_keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll) | ||
266 | { | ||
267 | int id = (data[0] >> 4) & 0x0f; | ||
268 | |||
269 | if (!adbhid[id]) { | ||
270 | printk(KERN_ERR "ADB HID on ID %d not yet registered, packet %#02x, %#02x, %#02x, %#02x\n", | ||
271 | id, data[0], data[1], data[2], data[3]); | ||
272 | return; | ||
273 | } | ||
274 | |||
275 | /* first check this is from register 0 */ | ||
276 | if (nb != 3 || (data[0] & 3) != KEYB_KEYREG) | ||
277 | return; /* ignore it */ | ||
278 | adbhid_input_keycode(id, data[1], 0, regs); | ||
279 | if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f))) | ||
280 | adbhid_input_keycode(id, data[2], 0, regs); | ||
281 | } | ||
282 | |||
283 | static void | ||
284 | adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs) | ||
285 | { | ||
286 | struct adbhid *ahid = adbhid[id]; | ||
287 | int up_flag; | ||
288 | |||
289 | up_flag = (keycode & 0x80); | ||
290 | keycode &= 0x7f; | ||
291 | |||
292 | switch (keycode) { | ||
293 | case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */ | ||
294 | input_regs(&ahid->input, regs); | ||
295 | input_report_key(&ahid->input, KEY_CAPSLOCK, 1); | ||
296 | input_report_key(&ahid->input, KEY_CAPSLOCK, 0); | ||
297 | input_sync(&ahid->input); | ||
298 | return; | ||
299 | #ifdef CONFIG_PPC_PMAC | ||
300 | case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ | ||
301 | switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
302 | NULL, PMAC_MB_INFO_MODEL, 0)) { | ||
303 | case PMAC_TYPE_COMET: | ||
304 | case PMAC_TYPE_HOOPER: | ||
305 | case PMAC_TYPE_KANGA: | ||
306 | keycode = ADB_KEY_POWER; | ||
307 | } | ||
308 | break; | ||
309 | case ADB_KEY_POWER: | ||
310 | /* Fn + Command will produce a bogus "power" keycode */ | ||
311 | if (ahid->flags & FLAG_FN_KEY_PRESSED) { | ||
312 | keycode = ADB_KEY_CMD; | ||
313 | if (up_flag) | ||
314 | ahid->flags &= ~FLAG_POWER_FROM_FN; | ||
315 | else | ||
316 | ahid->flags |= FLAG_POWER_FROM_FN; | ||
317 | } else if (ahid->flags & FLAG_POWER_FROM_FN) { | ||
318 | keycode = ADB_KEY_CMD; | ||
319 | ahid->flags &= ~FLAG_POWER_FROM_FN; | ||
320 | } | ||
321 | break; | ||
322 | case ADB_KEY_FN: | ||
323 | /* Keep track of the Fn key state */ | ||
324 | if (up_flag) { | ||
325 | ahid->flags &= ~FLAG_FN_KEY_PRESSED; | ||
326 | /* Emulate Fn+delete = forward delete */ | ||
327 | if (ahid->flags & FLAG_EMU_FWDEL_DOWN) { | ||
328 | ahid->flags &= ~FLAG_EMU_FWDEL_DOWN; | ||
329 | keycode = ADB_KEY_FWDEL; | ||
330 | break; | ||
331 | } | ||
332 | } else | ||
333 | ahid->flags |= FLAG_FN_KEY_PRESSED; | ||
334 | /* Swallow the key press */ | ||
335 | return; | ||
336 | case ADB_KEY_DEL: | ||
337 | /* Emulate Fn+delete = forward delete */ | ||
338 | if (ahid->flags & FLAG_FN_KEY_PRESSED) { | ||
339 | keycode = ADB_KEY_FWDEL; | ||
340 | if (up_flag) | ||
341 | ahid->flags &= ~FLAG_EMU_FWDEL_DOWN; | ||
342 | else | ||
343 | ahid->flags |= FLAG_EMU_FWDEL_DOWN; | ||
344 | } | ||
345 | break; | ||
346 | #endif /* CONFIG_PPC_PMAC */ | ||
347 | } | ||
348 | |||
349 | if (adbhid[id]->keycode[keycode]) { | ||
350 | input_regs(&adbhid[id]->input, regs); | ||
351 | input_report_key(&adbhid[id]->input, | ||
352 | adbhid[id]->keycode[keycode], !up_flag); | ||
353 | input_sync(&adbhid[id]->input); | ||
354 | } else | ||
355 | printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode, | ||
356 | up_flag ? "released" : "pressed"); | ||
357 | |||
358 | } | ||
359 | |||
360 | static void | ||
361 | adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll) | ||
362 | { | ||
363 | int id = (data[0] >> 4) & 0x0f; | ||
364 | |||
365 | if (!adbhid[id]) { | ||
366 | printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | Handler 1 -- 100cpi original Apple mouse protocol. | ||
372 | Handler 2 -- 200cpi original Apple mouse protocol. | ||
373 | |||
374 | For Apple's standard one-button mouse protocol the data array will | ||
375 | contain the following values: | ||
376 | |||
377 | BITS COMMENTS | ||
378 | data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. | ||
379 | data[1] = bxxx xxxx First button and x-axis motion. | ||
380 | data[2] = byyy yyyy Second button and y-axis motion. | ||
381 | |||
382 | Handler 4 -- Apple Extended mouse protocol. | ||
383 | |||
384 | For Apple's 3-button mouse protocol the data array will contain the | ||
385 | following values: | ||
386 | |||
387 | BITS COMMENTS | ||
388 | data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. | ||
389 | data[1] = bxxx xxxx Left button and x-axis motion. | ||
390 | data[2] = byyy yyyy Second button and y-axis motion. | ||
391 | data[3] = byyy bxxx Third button and fourth button. Y is additional | ||
392 | high bits of y-axis motion. XY is additional | ||
393 | high bits of x-axis motion. | ||
394 | |||
395 | MacAlly 2-button mouse protocol. | ||
396 | |||
397 | For MacAlly 2-button mouse protocol the data array will contain the | ||
398 | following values: | ||
399 | |||
400 | BITS COMMENTS | ||
401 | data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. | ||
402 | data[1] = bxxx xxxx Left button and x-axis motion. | ||
403 | data[2] = byyy yyyy Right button and y-axis motion. | ||
404 | data[3] = ???? ???? unknown | ||
405 | data[4] = ???? ???? unknown | ||
406 | |||
407 | */ | ||
408 | |||
409 | /* If it's a trackpad, we alias the second button to the first. | ||
410 | NOTE: Apple sends an ADB flush command to the trackpad when | ||
411 | the first (the real) button is released. We could do | ||
412 | this here using async flush requests. | ||
413 | */ | ||
414 | switch (adbhid[id]->mouse_kind) | ||
415 | { | ||
416 | case ADBMOUSE_TRACKPAD: | ||
417 | data[1] = (data[1] & 0x7f) | ((data[1] & data[2]) & 0x80); | ||
418 | data[2] = data[2] | 0x80; | ||
419 | break; | ||
420 | case ADBMOUSE_MICROSPEED: | ||
421 | data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7); | ||
422 | data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6); | ||
423 | data[3] = (data[3] & 0x77) | ((data[3] & 0x04) << 5) | ||
424 | | (data[3] & 0x08); | ||
425 | break; | ||
426 | case ADBMOUSE_TRACKBALLPRO: | ||
427 | data[1] = (data[1] & 0x7f) | (((data[3] & 0x04) << 5) | ||
428 | & ((data[3] & 0x08) << 4)); | ||
429 | data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7); | ||
430 | data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6); | ||
431 | break; | ||
432 | case ADBMOUSE_MS_A3: | ||
433 | data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7); | ||
434 | data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6); | ||
435 | data[3] = ((data[3] & 0x04) << 5); | ||
436 | break; | ||
437 | case ADBMOUSE_MACALLY2: | ||
438 | data[3] = (data[2] & 0x80) ? 0x80 : 0x00; | ||
439 | data[2] |= 0x80; /* Right button is mapped as button 3 */ | ||
440 | nb=4; | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | input_regs(&adbhid[id]->input, regs); | ||
445 | |||
446 | input_report_key(&adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1)); | ||
447 | input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1)); | ||
448 | |||
449 | if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD) | ||
450 | input_report_key(&adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1)); | ||
451 | |||
452 | input_report_rel(&adbhid[id]->input, REL_X, | ||
453 | ((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 )); | ||
454 | input_report_rel(&adbhid[id]->input, REL_Y, | ||
455 | ((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 )); | ||
456 | |||
457 | input_sync(&adbhid[id]->input); | ||
458 | } | ||
459 | |||
460 | static void | ||
461 | adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll) | ||
462 | { | ||
463 | int id = (data[0] >> 4) & 0x0f; | ||
464 | |||
465 | if (!adbhid[id]) { | ||
466 | printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id); | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | input_regs(&adbhid[id]->input, regs); | ||
471 | |||
472 | switch (adbhid[id]->original_handler_id) { | ||
473 | default: | ||
474 | case 0x02: /* Adjustable keyboard button device */ | ||
475 | { | ||
476 | int down = (data[1] == (data[1] & 0xf)); | ||
477 | |||
478 | switch (data[1] & 0x0f) { | ||
479 | case 0x0: /* microphone */ | ||
480 | input_report_key(&adbhid[id]->input, KEY_SOUND, down); | ||
481 | break; | ||
482 | |||
483 | case 0x1: /* mute */ | ||
484 | input_report_key(&adbhid[id]->input, KEY_MUTE, down); | ||
485 | break; | ||
486 | |||
487 | case 0x2: /* volume decrease */ | ||
488 | input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down); | ||
489 | break; | ||
490 | |||
491 | case 0x3: /* volume increase */ | ||
492 | input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down); | ||
493 | break; | ||
494 | |||
495 | default: | ||
496 | printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n", | ||
497 | data[0], data[1], data[2], data[3]); | ||
498 | break; | ||
499 | } | ||
500 | } | ||
501 | break; | ||
502 | |||
503 | case 0x1f: /* Powerbook button device */ | ||
504 | { | ||
505 | int down = (data[1] == (data[1] & 0xf)); | ||
506 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
507 | int backlight = get_backlight_level(); | ||
508 | #endif | ||
509 | /* | ||
510 | * XXX: Where is the contrast control for the passive? | ||
511 | * -- Cort | ||
512 | */ | ||
513 | |||
514 | switch (data[1] & 0x0f) { | ||
515 | case 0x8: /* mute */ | ||
516 | input_report_key(&adbhid[id]->input, KEY_MUTE, down); | ||
517 | break; | ||
518 | |||
519 | case 0x7: /* volume decrease */ | ||
520 | input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down); | ||
521 | break; | ||
522 | |||
523 | case 0x6: /* volume increase */ | ||
524 | input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down); | ||
525 | break; | ||
526 | |||
527 | case 0xb: /* eject */ | ||
528 | input_report_key(&adbhid[id]->input, KEY_EJECTCD, down); | ||
529 | break; | ||
530 | |||
531 | case 0xa: /* brightness decrease */ | ||
532 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
533 | if (!disable_kernel_backlight) { | ||
534 | if (down && backlight >= 0) { | ||
535 | if (backlight > BACKLIGHT_OFF) | ||
536 | set_backlight_level(backlight-1); | ||
537 | else | ||
538 | set_backlight_level(BACKLIGHT_OFF); | ||
539 | } | ||
540 | } | ||
541 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
542 | input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); | ||
543 | break; | ||
544 | |||
545 | case 0x9: /* brightness increase */ | ||
546 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
547 | if (!disable_kernel_backlight) { | ||
548 | if (down && backlight >= 0) { | ||
549 | if (backlight < BACKLIGHT_MAX) | ||
550 | set_backlight_level(backlight+1); | ||
551 | else | ||
552 | set_backlight_level(BACKLIGHT_MAX); | ||
553 | } | ||
554 | } | ||
555 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
556 | input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down); | ||
557 | break; | ||
558 | } | ||
559 | } | ||
560 | break; | ||
561 | } | ||
562 | |||
563 | input_sync(&adbhid[id]->input); | ||
564 | } | ||
565 | |||
566 | static struct adb_request led_request; | ||
567 | static int leds_pending[16]; | ||
568 | static int leds_req_pending; | ||
569 | static int pending_devs[16]; | ||
570 | static int pending_led_start=0; | ||
571 | static int pending_led_end=0; | ||
572 | static DEFINE_SPINLOCK(leds_lock); | ||
573 | |||
574 | static void leds_done(struct adb_request *req) | ||
575 | { | ||
576 | int leds = 0, device = 0, pending = 0; | ||
577 | unsigned long flags; | ||
578 | |||
579 | spin_lock_irqsave(&leds_lock, flags); | ||
580 | |||
581 | if (pending_led_start != pending_led_end) { | ||
582 | device = pending_devs[pending_led_start]; | ||
583 | leds = leds_pending[device] & 0xff; | ||
584 | leds_pending[device] = 0; | ||
585 | pending_led_start++; | ||
586 | pending_led_start = (pending_led_start < 16) ? pending_led_start : 0; | ||
587 | pending = leds_req_pending; | ||
588 | } else | ||
589 | leds_req_pending = 0; | ||
590 | spin_unlock_irqrestore(&leds_lock, flags); | ||
591 | if (pending) | ||
592 | adb_request(&led_request, leds_done, 0, 3, | ||
593 | ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds); | ||
594 | } | ||
595 | |||
596 | static void real_leds(unsigned char leds, int device) | ||
597 | { | ||
598 | unsigned long flags; | ||
599 | |||
600 | spin_lock_irqsave(&leds_lock, flags); | ||
601 | if (!leds_req_pending) { | ||
602 | leds_req_pending = 1; | ||
603 | spin_unlock_irqrestore(&leds_lock, flags); | ||
604 | adb_request(&led_request, leds_done, 0, 3, | ||
605 | ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds); | ||
606 | return; | ||
607 | } else { | ||
608 | if (!(leds_pending[device] & 0x100)) { | ||
609 | pending_devs[pending_led_end] = device; | ||
610 | pending_led_end++; | ||
611 | pending_led_end = (pending_led_end < 16) ? pending_led_end : 0; | ||
612 | } | ||
613 | leds_pending[device] = leds | 0x100; | ||
614 | } | ||
615 | spin_unlock_irqrestore(&leds_lock, flags); | ||
616 | } | ||
617 | |||
618 | /* | ||
619 | * Event callback from the input module. Events that change the state of | ||
620 | * the hardware are processed here. | ||
621 | */ | ||
622 | static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
623 | { | ||
624 | struct adbhid *adbhid = dev->private; | ||
625 | unsigned char leds; | ||
626 | |||
627 | switch (type) { | ||
628 | case EV_LED: | ||
629 | leds = (test_bit(LED_SCROLLL, dev->led) ? 4 : 0) | ||
630 | | (test_bit(LED_NUML, dev->led) ? 1 : 0) | ||
631 | | (test_bit(LED_CAPSL, dev->led) ? 2 : 0); | ||
632 | real_leds(leds, adbhid->id); | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | return -1; | ||
637 | } | ||
638 | |||
639 | static int | ||
640 | adb_message_handler(struct notifier_block *this, unsigned long code, void *x) | ||
641 | { | ||
642 | switch (code) { | ||
643 | case ADB_MSG_PRE_RESET: | ||
644 | case ADB_MSG_POWERDOWN: | ||
645 | /* Stop the repeat timer. Autopoll is already off at this point */ | ||
646 | { | ||
647 | int i; | ||
648 | for (i = 1; i < 16; i++) { | ||
649 | if (adbhid[i]) | ||
650 | del_timer_sync(&adbhid[i]->input.timer); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | /* Stop pending led requests */ | ||
655 | while(leds_req_pending) | ||
656 | adb_poll(); | ||
657 | break; | ||
658 | |||
659 | case ADB_MSG_POST_RESET: | ||
660 | adbhid_probe(); | ||
661 | break; | ||
662 | } | ||
663 | return NOTIFY_DONE; | ||
664 | } | ||
665 | |||
666 | static void | ||
667 | adbhid_input_register(int id, int default_id, int original_handler_id, | ||
668 | int current_handler_id, int mouse_kind) | ||
669 | { | ||
670 | int i; | ||
671 | |||
672 | if (adbhid[id]) { | ||
673 | printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id); | ||
674 | return; | ||
675 | } | ||
676 | |||
677 | if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL))) | ||
678 | return; | ||
679 | |||
680 | memset(adbhid[id], 0, sizeof(struct adbhid)); | ||
681 | sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id); | ||
682 | |||
683 | init_input_dev(&adbhid[id]->input); | ||
684 | |||
685 | adbhid[id]->id = default_id; | ||
686 | adbhid[id]->original_handler_id = original_handler_id; | ||
687 | adbhid[id]->current_handler_id = current_handler_id; | ||
688 | adbhid[id]->mouse_kind = mouse_kind; | ||
689 | adbhid[id]->flags = 0; | ||
690 | adbhid[id]->input.private = adbhid[id]; | ||
691 | adbhid[id]->input.name = adbhid[id]->name; | ||
692 | adbhid[id]->input.phys = adbhid[id]->phys; | ||
693 | adbhid[id]->input.id.bustype = BUS_ADB; | ||
694 | adbhid[id]->input.id.vendor = 0x0001; | ||
695 | adbhid[id]->input.id.product = (id << 12) | (default_id << 8) | original_handler_id; | ||
696 | adbhid[id]->input.id.version = 0x0100; | ||
697 | |||
698 | switch (default_id) { | ||
699 | case ADB_KEYBOARD: | ||
700 | if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) { | ||
701 | kfree(adbhid[id]); | ||
702 | return; | ||
703 | } | ||
704 | |||
705 | sprintf(adbhid[id]->name, "ADB keyboard"); | ||
706 | |||
707 | memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes)); | ||
708 | |||
709 | printk(KERN_INFO "Detected ADB keyboard, type "); | ||
710 | switch (original_handler_id) { | ||
711 | default: | ||
712 | printk("<unknown>.\n"); | ||
713 | adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN; | ||
714 | break; | ||
715 | |||
716 | case 0x01: case 0x02: case 0x03: case 0x06: case 0x08: | ||
717 | case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C: | ||
718 | case 0xC0: case 0xC3: case 0xC6: | ||
719 | printk("ANSI.\n"); | ||
720 | adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI; | ||
721 | break; | ||
722 | |||
723 | case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: | ||
724 | case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: | ||
725 | case 0xC4: case 0xC7: | ||
726 | printk("ISO, swapping keys.\n"); | ||
727 | adbhid[id]->input.id.version = ADB_KEYBOARD_ISO; | ||
728 | i = adbhid[id]->keycode[10]; | ||
729 | adbhid[id]->keycode[10] = adbhid[id]->keycode[50]; | ||
730 | adbhid[id]->keycode[50] = i; | ||
731 | break; | ||
732 | |||
733 | case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A: | ||
734 | case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9: | ||
735 | printk("JIS.\n"); | ||
736 | adbhid[id]->input.id.version = ADB_KEYBOARD_JIS; | ||
737 | break; | ||
738 | } | ||
739 | |||
740 | for (i = 0; i < 128; i++) | ||
741 | if (adbhid[id]->keycode[i]) | ||
742 | set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit); | ||
743 | |||
744 | adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); | ||
745 | adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML); | ||
746 | adbhid[id]->input.event = adbhid_kbd_event; | ||
747 | adbhid[id]->input.keycodemax = 127; | ||
748 | adbhid[id]->input.keycodesize = 1; | ||
749 | break; | ||
750 | |||
751 | case ADB_MOUSE: | ||
752 | sprintf(adbhid[id]->name, "ADB mouse"); | ||
753 | |||
754 | adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
755 | adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
756 | adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
757 | break; | ||
758 | |||
759 | case ADB_MISC: | ||
760 | switch (original_handler_id) { | ||
761 | case 0x02: /* Adjustable keyboard button device */ | ||
762 | sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons"); | ||
763 | adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
764 | set_bit(KEY_SOUND, adbhid[id]->input.keybit); | ||
765 | set_bit(KEY_MUTE, adbhid[id]->input.keybit); | ||
766 | set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit); | ||
767 | set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit); | ||
768 | break; | ||
769 | case 0x1f: /* Powerbook button device */ | ||
770 | sprintf(adbhid[id]->name, "ADB Powerbook buttons"); | ||
771 | adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
772 | set_bit(KEY_MUTE, adbhid[id]->input.keybit); | ||
773 | set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit); | ||
774 | set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit); | ||
775 | set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit); | ||
776 | set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit); | ||
777 | set_bit(KEY_EJECTCD, adbhid[id]->input.keybit); | ||
778 | break; | ||
779 | } | ||
780 | if (adbhid[id]->name[0]) | ||
781 | break; | ||
782 | /* else fall through */ | ||
783 | |||
784 | default: | ||
785 | printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n"); | ||
786 | kfree(adbhid[id]); | ||
787 | return; | ||
788 | } | ||
789 | |||
790 | adbhid[id]->input.keycode = adbhid[id]->keycode; | ||
791 | |||
792 | input_register_device(&adbhid[id]->input); | ||
793 | |||
794 | printk(KERN_INFO "input: %s on %s\n", | ||
795 | adbhid[id]->name, adbhid[id]->phys); | ||
796 | |||
797 | if (default_id == ADB_KEYBOARD) { | ||
798 | /* HACK WARNING!! This should go away as soon there is an utility | ||
799 | * to control that for event devices. | ||
800 | */ | ||
801 | adbhid[id]->input.rep[REP_DELAY] = 500; /* input layer default: 250 */ | ||
802 | adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */ | ||
803 | } | ||
804 | } | ||
805 | |||
806 | static void adbhid_input_unregister(int id) | ||
807 | { | ||
808 | input_unregister_device(&adbhid[id]->input); | ||
809 | if (adbhid[id]->keycode) | ||
810 | kfree(adbhid[id]->keycode); | ||
811 | kfree(adbhid[id]); | ||
812 | adbhid[id] = NULL; | ||
813 | } | ||
814 | |||
815 | |||
816 | static u16 | ||
817 | adbhid_input_reregister(int id, int default_id, int org_handler_id, | ||
818 | int cur_handler_id, int mk) | ||
819 | { | ||
820 | if (adbhid[id]) { | ||
821 | if (adbhid[id]->input.id.product != | ||
822 | ((id << 12)|(default_id << 8)|org_handler_id)) { | ||
823 | adbhid_input_unregister(id); | ||
824 | adbhid_input_register(id, default_id, org_handler_id, | ||
825 | cur_handler_id, mk); | ||
826 | } | ||
827 | } else | ||
828 | adbhid_input_register(id, default_id, org_handler_id, | ||
829 | cur_handler_id, mk); | ||
830 | return 1<<id; | ||
831 | } | ||
832 | |||
833 | static void | ||
834 | adbhid_input_devcleanup(u16 exist) | ||
835 | { | ||
836 | int i; | ||
837 | for(i=1; i<16; i++) | ||
838 | if (adbhid[i] && !(exist&(1<<i))) | ||
839 | adbhid_input_unregister(i); | ||
840 | } | ||
841 | |||
842 | static void | ||
843 | adbhid_probe(void) | ||
844 | { | ||
845 | struct adb_request req; | ||
846 | int i, default_id, org_handler_id, cur_handler_id; | ||
847 | u16 reg = 0; | ||
848 | |||
849 | adb_register(ADB_MOUSE, 0, &mouse_ids, adbhid_mouse_input); | ||
850 | adb_register(ADB_KEYBOARD, 0, &keyboard_ids, adbhid_keyboard_input); | ||
851 | adb_register(ADB_MISC, 0, &buttons_ids, adbhid_buttons_input); | ||
852 | |||
853 | for (i = 0; i < keyboard_ids.nids; i++) { | ||
854 | int id = keyboard_ids.id[i]; | ||
855 | |||
856 | adb_get_infos(id, &default_id, &org_handler_id); | ||
857 | |||
858 | /* turn off all leds */ | ||
859 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
860 | ADB_WRITEREG(id, KEYB_LEDREG), 0xff, 0xff); | ||
861 | |||
862 | /* Enable full feature set of the keyboard | ||
863 | ->get it to send separate codes for left and right shift, | ||
864 | control, option keys */ | ||
865 | #if 0 /* handler 5 doesn't send separate codes for R modifiers */ | ||
866 | if (adb_try_handler_change(id, 5)) | ||
867 | printk("ADB keyboard at %d, handler set to 5\n", id); | ||
868 | else | ||
869 | #endif | ||
870 | if (adb_try_handler_change(id, 3)) | ||
871 | printk("ADB keyboard at %d, handler set to 3\n", id); | ||
872 | else | ||
873 | printk("ADB keyboard at %d, handler 1\n", id); | ||
874 | |||
875 | adb_get_infos(id, &default_id, &cur_handler_id); | ||
876 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, | ||
877 | cur_handler_id, 0); | ||
878 | } | ||
879 | |||
880 | for (i = 0; i < buttons_ids.nids; i++) { | ||
881 | int id = buttons_ids.id[i]; | ||
882 | |||
883 | adb_get_infos(id, &default_id, &org_handler_id); | ||
884 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, | ||
885 | org_handler_id, 0); | ||
886 | } | ||
887 | |||
888 | /* Try to switch all mice to handler 4, or 2 for three-button | ||
889 | mode and full resolution. */ | ||
890 | for (i = 0; i < mouse_ids.nids; i++) { | ||
891 | int id = mouse_ids.id[i]; | ||
892 | int mouse_kind; | ||
893 | |||
894 | adb_get_infos(id, &default_id, &org_handler_id); | ||
895 | |||
896 | if (adb_try_handler_change(id, 4)) { | ||
897 | printk("ADB mouse at %d, handler set to 4", id); | ||
898 | mouse_kind = ADBMOUSE_EXTENDED; | ||
899 | } | ||
900 | else if (adb_try_handler_change(id, 0x2F)) { | ||
901 | printk("ADB mouse at %d, handler set to 0x2F", id); | ||
902 | mouse_kind = ADBMOUSE_MICROSPEED; | ||
903 | } | ||
904 | else if (adb_try_handler_change(id, 0x42)) { | ||
905 | printk("ADB mouse at %d, handler set to 0x42", id); | ||
906 | mouse_kind = ADBMOUSE_TRACKBALLPRO; | ||
907 | } | ||
908 | else if (adb_try_handler_change(id, 0x66)) { | ||
909 | printk("ADB mouse at %d, handler set to 0x66", id); | ||
910 | mouse_kind = ADBMOUSE_MICROSPEED; | ||
911 | } | ||
912 | else if (adb_try_handler_change(id, 0x5F)) { | ||
913 | printk("ADB mouse at %d, handler set to 0x5F", id); | ||
914 | mouse_kind = ADBMOUSE_MICROSPEED; | ||
915 | } | ||
916 | else if (adb_try_handler_change(id, 3)) { | ||
917 | printk("ADB mouse at %d, handler set to 3", id); | ||
918 | mouse_kind = ADBMOUSE_MS_A3; | ||
919 | } | ||
920 | else if (adb_try_handler_change(id, 2)) { | ||
921 | printk("ADB mouse at %d, handler set to 2", id); | ||
922 | mouse_kind = ADBMOUSE_STANDARD_200; | ||
923 | } | ||
924 | else { | ||
925 | printk("ADB mouse at %d, handler 1", id); | ||
926 | mouse_kind = ADBMOUSE_STANDARD_100; | ||
927 | } | ||
928 | |||
929 | if ((mouse_kind == ADBMOUSE_TRACKBALLPRO) | ||
930 | || (mouse_kind == ADBMOUSE_MICROSPEED)) { | ||
931 | init_microspeed(id); | ||
932 | } else if (mouse_kind == ADBMOUSE_MS_A3) { | ||
933 | init_ms_a3(id); | ||
934 | } else if (mouse_kind == ADBMOUSE_EXTENDED) { | ||
935 | /* | ||
936 | * Register 1 is usually used for device | ||
937 | * identification. Here, we try to identify | ||
938 | * a known device and call the appropriate | ||
939 | * init function. | ||
940 | */ | ||
941 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
942 | ADB_READREG(id, 1)); | ||
943 | |||
944 | if ((req.reply_len) && | ||
945 | (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21) | ||
946 | || (req.reply[2] == 0x20))) { | ||
947 | mouse_kind = ADBMOUSE_TRACKBALL; | ||
948 | init_trackball(id); | ||
949 | } | ||
950 | else if ((req.reply_len >= 4) && | ||
951 | (req.reply[1] == 0x74) && (req.reply[2] == 0x70) && | ||
952 | (req.reply[3] == 0x61) && (req.reply[4] == 0x64)) { | ||
953 | mouse_kind = ADBMOUSE_TRACKPAD; | ||
954 | init_trackpad(id); | ||
955 | } | ||
956 | else if ((req.reply_len >= 4) && | ||
957 | (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) && | ||
958 | (req.reply[3] == 0x4c) && (req.reply[4] == 0x31)) { | ||
959 | mouse_kind = ADBMOUSE_TURBOMOUSE5; | ||
960 | init_turbomouse(id); | ||
961 | } | ||
962 | else if ((req.reply_len == 9) && | ||
963 | (req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) && | ||
964 | (req.reply[3] == 0x49) && (req.reply[4] == 0x54)) { | ||
965 | if (adb_try_handler_change(id, 0x42)) { | ||
966 | printk("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id); | ||
967 | mouse_kind = ADBMOUSE_MACALLY2; | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | printk("\n"); | ||
972 | |||
973 | adb_get_infos(id, &default_id, &cur_handler_id); | ||
974 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, | ||
975 | cur_handler_id, mouse_kind); | ||
976 | } | ||
977 | adbhid_input_devcleanup(reg); | ||
978 | } | ||
979 | |||
980 | static void | ||
981 | init_trackpad(int id) | ||
982 | { | ||
983 | struct adb_request req; | ||
984 | unsigned char r1_buffer[8]; | ||
985 | |||
986 | printk(" (trackpad)"); | ||
987 | |||
988 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | ||
989 | ADB_READREG(id,1)); | ||
990 | if (req.reply_len < 8) | ||
991 | printk("bad length for reg. 1\n"); | ||
992 | else | ||
993 | { | ||
994 | memcpy(r1_buffer, &req.reply[1], 8); | ||
995 | |||
996 | adb_request(&req, NULL, ADBREQ_SYNC, 9, | ||
997 | ADB_WRITEREG(id,1), | ||
998 | r1_buffer[0], | ||
999 | r1_buffer[1], | ||
1000 | r1_buffer[2], | ||
1001 | r1_buffer[3], | ||
1002 | r1_buffer[4], | ||
1003 | r1_buffer[5], | ||
1004 | 0x0d, | ||
1005 | r1_buffer[7]); | ||
1006 | |||
1007 | adb_request(&req, NULL, ADBREQ_SYNC, 9, | ||
1008 | ADB_WRITEREG(id,2), | ||
1009 | 0x99, | ||
1010 | 0x94, | ||
1011 | 0x19, | ||
1012 | 0xff, | ||
1013 | 0xb2, | ||
1014 | 0x8a, | ||
1015 | 0x1b, | ||
1016 | 0x50); | ||
1017 | |||
1018 | adb_request(&req, NULL, ADBREQ_SYNC, 9, | ||
1019 | ADB_WRITEREG(id,1), | ||
1020 | r1_buffer[0], | ||
1021 | r1_buffer[1], | ||
1022 | r1_buffer[2], | ||
1023 | r1_buffer[3], | ||
1024 | r1_buffer[4], | ||
1025 | r1_buffer[5], | ||
1026 | 0x03, /*r1_buffer[6],*/ | ||
1027 | r1_buffer[7]); | ||
1028 | |||
1029 | /* Without this flush, the trackpad may be locked up */ | ||
1030 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | static void | ||
1035 | init_trackball(int id) | ||
1036 | { | ||
1037 | struct adb_request req; | ||
1038 | |||
1039 | printk(" (trackman/mouseman)"); | ||
1040 | |||
1041 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1042 | ADB_WRITEREG(id,1), 00,0x81); | ||
1043 | |||
1044 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1045 | ADB_WRITEREG(id,1), 01,0x81); | ||
1046 | |||
1047 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1048 | ADB_WRITEREG(id,1), 02,0x81); | ||
1049 | |||
1050 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1051 | ADB_WRITEREG(id,1), 03,0x38); | ||
1052 | |||
1053 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1054 | ADB_WRITEREG(id,1), 00,0x81); | ||
1055 | |||
1056 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1057 | ADB_WRITEREG(id,1), 01,0x81); | ||
1058 | |||
1059 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1060 | ADB_WRITEREG(id,1), 02,0x81); | ||
1061 | |||
1062 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1063 | ADB_WRITEREG(id,1), 03,0x38); | ||
1064 | } | ||
1065 | |||
1066 | static void | ||
1067 | init_turbomouse(int id) | ||
1068 | { | ||
1069 | struct adb_request req; | ||
1070 | |||
1071 | printk(" (TurboMouse 5)"); | ||
1072 | |||
1073 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | ||
1074 | |||
1075 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); | ||
1076 | |||
1077 | adb_request(&req, NULL, ADBREQ_SYNC, 9, | ||
1078 | ADB_WRITEREG(3,2), | ||
1079 | 0xe7, | ||
1080 | 0x8c, | ||
1081 | 0, | ||
1082 | 0, | ||
1083 | 0, | ||
1084 | 0xff, | ||
1085 | 0xff, | ||
1086 | 0x94); | ||
1087 | |||
1088 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); | ||
1089 | |||
1090 | adb_request(&req, NULL, ADBREQ_SYNC, 9, | ||
1091 | ADB_WRITEREG(3,2), | ||
1092 | 0xa5, | ||
1093 | 0x14, | ||
1094 | 0, | ||
1095 | 0, | ||
1096 | 0x69, | ||
1097 | 0xff, | ||
1098 | 0xff, | ||
1099 | 0x27); | ||
1100 | } | ||
1101 | |||
1102 | static void | ||
1103 | init_microspeed(int id) | ||
1104 | { | ||
1105 | struct adb_request req; | ||
1106 | |||
1107 | printk(" (Microspeed/MacPoint or compatible)"); | ||
1108 | |||
1109 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | ||
1110 | |||
1111 | /* This will initialize mice using the Microspeed, MacPoint and | ||
1112 | other compatible firmware. Bit 12 enables extended protocol. | ||
1113 | |||
1114 | Register 1 Listen (4 Bytes) | ||
1115 | 0 - 3 Button is mouse (set also for double clicking!!!) | ||
1116 | 4 - 7 Button is locking (affects change speed also) | ||
1117 | 8 - 11 Button changes speed | ||
1118 | 12 1 = Extended mouse mode, 0 = normal mouse mode | ||
1119 | 13 - 15 unused 0 | ||
1120 | 16 - 23 normal speed | ||
1121 | 24 - 31 changed speed | ||
1122 | |||
1123 | Register 1 talk holds version and product identification information. | ||
1124 | Register 1 Talk (4 Bytes): | ||
1125 | 0 - 7 Product code | ||
1126 | 8 - 23 undefined, reserved | ||
1127 | 24 - 31 Version number | ||
1128 | |||
1129 | Speed 0 is max. 1 to 255 set speed in increments of 1/256 of max. | ||
1130 | */ | ||
1131 | adb_request(&req, NULL, ADBREQ_SYNC, 5, | ||
1132 | ADB_WRITEREG(id,1), | ||
1133 | 0x20, /* alt speed = 0x20 (rather slow) */ | ||
1134 | 0x00, /* norm speed = 0x00 (fastest) */ | ||
1135 | 0x10, /* extended protocol, no speed change */ | ||
1136 | 0x07); /* all buttons enabled as mouse buttons, no locking */ | ||
1137 | |||
1138 | |||
1139 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | ||
1140 | } | ||
1141 | |||
1142 | static void | ||
1143 | init_ms_a3(int id) | ||
1144 | { | ||
1145 | struct adb_request req; | ||
1146 | |||
1147 | printk(" (Mouse Systems A3 Mouse, or compatible)"); | ||
1148 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | ||
1149 | ADB_WRITEREG(id, 0x2), | ||
1150 | 0x00, | ||
1151 | 0x07); | ||
1152 | |||
1153 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | ||
1154 | } | ||
1155 | |||
1156 | static int __init adbhid_init(void) | ||
1157 | { | ||
1158 | #ifndef CONFIG_MAC | ||
1159 | if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) | ||
1160 | return 0; | ||
1161 | #endif | ||
1162 | |||
1163 | led_request.complete = 1; | ||
1164 | |||
1165 | adbhid_probe(); | ||
1166 | |||
1167 | notifier_chain_register(&adb_client_list, &adbhid_adb_notifier); | ||
1168 | |||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | static void __exit adbhid_exit(void) | ||
1173 | { | ||
1174 | } | ||
1175 | |||
1176 | module_init(adbhid_init); | ||
1177 | module_exit(adbhid_exit); | ||
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c new file mode 100644 index 000000000000..5e0811dc6536 --- /dev/null +++ b/drivers/macintosh/ans-lcd.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * /dev/lcd driver for Apple Network Servers. | ||
3 | */ | ||
4 | |||
5 | #include <linux/types.h> | ||
6 | #include <linux/errno.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/miscdevice.h> | ||
9 | #include <linux/fcntl.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/fs.h> | ||
13 | |||
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/sections.h> | ||
16 | #include <asm/prom.h> | ||
17 | #include <asm/ans-lcd.h> | ||
18 | #include <asm/io.h> | ||
19 | |||
20 | #define ANSLCD_ADDR 0xf301c000 | ||
21 | #define ANSLCD_CTRL_IX 0x00 | ||
22 | #define ANSLCD_DATA_IX 0x10 | ||
23 | |||
24 | static unsigned long anslcd_short_delay = 80; | ||
25 | static unsigned long anslcd_long_delay = 3280; | ||
26 | static volatile unsigned char __iomem *anslcd_ptr; | ||
27 | |||
28 | #undef DEBUG | ||
29 | |||
30 | static void __pmac | ||
31 | anslcd_write_byte_ctrl ( unsigned char c ) | ||
32 | { | ||
33 | #ifdef DEBUG | ||
34 | printk(KERN_DEBUG "LCD: CTRL byte: %02x\n",c); | ||
35 | #endif | ||
36 | out_8(anslcd_ptr + ANSLCD_CTRL_IX, c); | ||
37 | switch(c) { | ||
38 | case 1: | ||
39 | case 2: | ||
40 | case 3: | ||
41 | udelay(anslcd_long_delay); break; | ||
42 | default: udelay(anslcd_short_delay); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static void __pmac | ||
47 | anslcd_write_byte_data ( unsigned char c ) | ||
48 | { | ||
49 | out_8(anslcd_ptr + ANSLCD_DATA_IX, c); | ||
50 | udelay(anslcd_short_delay); | ||
51 | } | ||
52 | |||
53 | static ssize_t __pmac | ||
54 | anslcd_write( struct file * file, const char __user * buf, | ||
55 | size_t count, loff_t *ppos ) | ||
56 | { | ||
57 | const char __user *p = buf; | ||
58 | int i; | ||
59 | |||
60 | #ifdef DEBUG | ||
61 | printk(KERN_DEBUG "LCD: write\n"); | ||
62 | #endif | ||
63 | |||
64 | if (!access_ok(VERIFY_READ, buf, count)) | ||
65 | return -EFAULT; | ||
66 | for ( i = *ppos; count > 0; ++i, ++p, --count ) | ||
67 | { | ||
68 | char c; | ||
69 | __get_user(c, p); | ||
70 | anslcd_write_byte_data( c ); | ||
71 | } | ||
72 | *ppos = i; | ||
73 | return p - buf; | ||
74 | } | ||
75 | |||
76 | static int __pmac | ||
77 | anslcd_ioctl( struct inode * inode, struct file * file, | ||
78 | unsigned int cmd, unsigned long arg ) | ||
79 | { | ||
80 | char ch, __user *temp; | ||
81 | |||
82 | #ifdef DEBUG | ||
83 | printk(KERN_DEBUG "LCD: ioctl(%d,%d)\n",cmd,arg); | ||
84 | #endif | ||
85 | |||
86 | switch ( cmd ) | ||
87 | { | ||
88 | case ANSLCD_CLEAR: | ||
89 | anslcd_write_byte_ctrl ( 0x38 ); | ||
90 | anslcd_write_byte_ctrl ( 0x0f ); | ||
91 | anslcd_write_byte_ctrl ( 0x06 ); | ||
92 | anslcd_write_byte_ctrl ( 0x01 ); | ||
93 | anslcd_write_byte_ctrl ( 0x02 ); | ||
94 | return 0; | ||
95 | case ANSLCD_SENDCTRL: | ||
96 | temp = (char __user *) arg; | ||
97 | __get_user(ch, temp); | ||
98 | for (; ch; temp++) { /* FIXME: This is ugly, but should work, as a \0 byte is not a valid command code */ | ||
99 | anslcd_write_byte_ctrl ( ch ); | ||
100 | __get_user(ch, temp); | ||
101 | } | ||
102 | return 0; | ||
103 | case ANSLCD_SETSHORTDELAY: | ||
104 | if (!capable(CAP_SYS_ADMIN)) | ||
105 | return -EACCES; | ||
106 | anslcd_short_delay=arg; | ||
107 | return 0; | ||
108 | case ANSLCD_SETLONGDELAY: | ||
109 | if (!capable(CAP_SYS_ADMIN)) | ||
110 | return -EACCES; | ||
111 | anslcd_long_delay=arg; | ||
112 | return 0; | ||
113 | default: | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static int __pmac | ||
119 | anslcd_open( struct inode * inode, struct file * file ) | ||
120 | { | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | struct file_operations anslcd_fops = { | ||
125 | .write = anslcd_write, | ||
126 | .ioctl = anslcd_ioctl, | ||
127 | .open = anslcd_open, | ||
128 | }; | ||
129 | |||
130 | static struct miscdevice anslcd_dev = { | ||
131 | ANSLCD_MINOR, | ||
132 | "anslcd", | ||
133 | &anslcd_fops | ||
134 | }; | ||
135 | |||
136 | const char anslcd_logo[] = "********************" /* Line #1 */ | ||
137 | "* LINUX! *" /* Line #3 */ | ||
138 | "* Welcome to *" /* Line #2 */ | ||
139 | "********************"; /* Line #4 */ | ||
140 | |||
141 | static int __init | ||
142 | anslcd_init(void) | ||
143 | { | ||
144 | int a; | ||
145 | int retval; | ||
146 | struct device_node* node; | ||
147 | |||
148 | node = find_devices("lcd"); | ||
149 | if (!node || !node->parent) | ||
150 | return -ENODEV; | ||
151 | if (strcmp(node->parent->name, "gc")) | ||
152 | return -ENODEV; | ||
153 | |||
154 | anslcd_ptr = ioremap(ANSLCD_ADDR, 0x20); | ||
155 | |||
156 | retval = misc_register(&anslcd_dev); | ||
157 | if(retval < 0){ | ||
158 | printk(KERN_INFO "LCD: misc_register failed\n"); | ||
159 | iounmap(anslcd_ptr); | ||
160 | return retval; | ||
161 | } | ||
162 | |||
163 | #ifdef DEBUG | ||
164 | printk(KERN_DEBUG "LCD: init\n"); | ||
165 | #endif | ||
166 | |||
167 | anslcd_write_byte_ctrl ( 0x38 ); | ||
168 | anslcd_write_byte_ctrl ( 0x0c ); | ||
169 | anslcd_write_byte_ctrl ( 0x06 ); | ||
170 | anslcd_write_byte_ctrl ( 0x01 ); | ||
171 | anslcd_write_byte_ctrl ( 0x02 ); | ||
172 | for(a=0;a<80;a++) { | ||
173 | anslcd_write_byte_data(anslcd_logo[a]); | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void __exit | ||
179 | anslcd_exit(void) | ||
180 | { | ||
181 | misc_deregister(&anslcd_dev); | ||
182 | iounmap(anslcd_ptr); | ||
183 | } | ||
184 | |||
185 | module_init(anslcd_init); | ||
186 | module_exit(anslcd_exit); | ||
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c new file mode 100644 index 000000000000..19d3e05d6825 --- /dev/null +++ b/drivers/macintosh/apm_emu.c | |||
@@ -0,0 +1,553 @@ | |||
1 | /* APM emulation layer for PowerMac | ||
2 | * | ||
3 | * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
4 | * | ||
5 | * Lots of code inherited from apm.c, see appropriate notice in | ||
6 | * arch/i386/kernel/apm.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2, or (at your option) any | ||
11 | * later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include <linux/poll.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/stddef.h> | ||
27 | #include <linux/timer.h> | ||
28 | #include <linux/fcntl.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/stat.h> | ||
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/miscdevice.h> | ||
33 | #include <linux/apm_bios.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/sched.h> | ||
36 | #include <linux/pm.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/smp_lock.h> | ||
39 | |||
40 | #include <linux/adb.h> | ||
41 | #include <linux/pmu.h> | ||
42 | |||
43 | #include <asm/system.h> | ||
44 | #include <asm/uaccess.h> | ||
45 | #include <asm/machdep.h> | ||
46 | |||
47 | #undef DEBUG | ||
48 | |||
49 | #ifdef DEBUG | ||
50 | #define DBG(args...) printk(KERN_DEBUG args) | ||
51 | //#define DBG(args...) xmon_printf(args) | ||
52 | #else | ||
53 | #define DBG(args...) do { } while (0) | ||
54 | #endif | ||
55 | |||
56 | /* | ||
57 | * The apm_bios device is one of the misc char devices. | ||
58 | * This is its minor number. | ||
59 | */ | ||
60 | #define APM_MINOR_DEV 134 | ||
61 | |||
62 | /* | ||
63 | * Maximum number of events stored | ||
64 | */ | ||
65 | #define APM_MAX_EVENTS 20 | ||
66 | |||
67 | #define FAKE_APM_BIOS_VERSION 0x0101 | ||
68 | |||
69 | #define APM_USER_NOTIFY_TIMEOUT (5*HZ) | ||
70 | |||
71 | /* | ||
72 | * The per-file APM data | ||
73 | */ | ||
74 | struct apm_user { | ||
75 | int magic; | ||
76 | struct apm_user * next; | ||
77 | int suser: 1; | ||
78 | int suspend_waiting: 1; | ||
79 | int suspends_pending; | ||
80 | int suspends_read; | ||
81 | int event_head; | ||
82 | int event_tail; | ||
83 | apm_event_t events[APM_MAX_EVENTS]; | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * The magic number in apm_user | ||
88 | */ | ||
89 | #define APM_BIOS_MAGIC 0x4101 | ||
90 | |||
91 | /* | ||
92 | * Local variables | ||
93 | */ | ||
94 | static int suspends_pending; | ||
95 | |||
96 | static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); | ||
97 | static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); | ||
98 | static struct apm_user * user_list; | ||
99 | |||
100 | static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when); | ||
101 | static struct pmu_sleep_notifier apm_sleep_notifier = { | ||
102 | apm_notify_sleep, | ||
103 | SLEEP_LEVEL_USERLAND, | ||
104 | }; | ||
105 | |||
106 | static char driver_version[] = "0.5"; /* no spaces */ | ||
107 | |||
108 | #ifdef DEBUG | ||
109 | static char * apm_event_name[] = { | ||
110 | "system standby", | ||
111 | "system suspend", | ||
112 | "normal resume", | ||
113 | "critical resume", | ||
114 | "low battery", | ||
115 | "power status change", | ||
116 | "update time", | ||
117 | "critical suspend", | ||
118 | "user standby", | ||
119 | "user suspend", | ||
120 | "system standby resume", | ||
121 | "capabilities change" | ||
122 | }; | ||
123 | #define NR_APM_EVENT_NAME \ | ||
124 | (sizeof(apm_event_name) / sizeof(apm_event_name[0])) | ||
125 | |||
126 | #endif | ||
127 | |||
128 | static int queue_empty(struct apm_user *as) | ||
129 | { | ||
130 | return as->event_head == as->event_tail; | ||
131 | } | ||
132 | |||
133 | static apm_event_t get_queued_event(struct apm_user *as) | ||
134 | { | ||
135 | as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; | ||
136 | return as->events[as->event_tail]; | ||
137 | } | ||
138 | |||
139 | static void queue_event(apm_event_t event, struct apm_user *sender) | ||
140 | { | ||
141 | struct apm_user * as; | ||
142 | |||
143 | DBG("apm_emu: queue_event(%s)\n", apm_event_name[event-1]); | ||
144 | if (user_list == NULL) | ||
145 | return; | ||
146 | for (as = user_list; as != NULL; as = as->next) { | ||
147 | if (as == sender) | ||
148 | continue; | ||
149 | as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; | ||
150 | if (as->event_head == as->event_tail) { | ||
151 | static int notified; | ||
152 | |||
153 | if (notified++ == 0) | ||
154 | printk(KERN_ERR "apm_emu: an event queue overflowed\n"); | ||
155 | as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; | ||
156 | } | ||
157 | as->events[as->event_head] = event; | ||
158 | if (!as->suser) | ||
159 | continue; | ||
160 | switch (event) { | ||
161 | case APM_SYS_SUSPEND: | ||
162 | case APM_USER_SUSPEND: | ||
163 | as->suspends_pending++; | ||
164 | suspends_pending++; | ||
165 | break; | ||
166 | case APM_NORMAL_RESUME: | ||
167 | as->suspend_waiting = 0; | ||
168 | break; | ||
169 | } | ||
170 | } | ||
171 | wake_up_interruptible(&apm_waitqueue); | ||
172 | } | ||
173 | |||
174 | static int check_apm_user(struct apm_user *as, const char *func) | ||
175 | { | ||
176 | if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { | ||
177 | printk(KERN_ERR "apm_emu: %s passed bad filp\n", func); | ||
178 | return 1; | ||
179 | } | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) | ||
184 | { | ||
185 | struct apm_user * as; | ||
186 | size_t i; | ||
187 | apm_event_t event; | ||
188 | DECLARE_WAITQUEUE(wait, current); | ||
189 | |||
190 | as = fp->private_data; | ||
191 | if (check_apm_user(as, "read")) | ||
192 | return -EIO; | ||
193 | if (count < sizeof(apm_event_t)) | ||
194 | return -EINVAL; | ||
195 | if (queue_empty(as)) { | ||
196 | if (fp->f_flags & O_NONBLOCK) | ||
197 | return -EAGAIN; | ||
198 | add_wait_queue(&apm_waitqueue, &wait); | ||
199 | repeat: | ||
200 | set_current_state(TASK_INTERRUPTIBLE); | ||
201 | if (queue_empty(as) && !signal_pending(current)) { | ||
202 | schedule(); | ||
203 | goto repeat; | ||
204 | } | ||
205 | set_current_state(TASK_RUNNING); | ||
206 | remove_wait_queue(&apm_waitqueue, &wait); | ||
207 | } | ||
208 | i = count; | ||
209 | while ((i >= sizeof(event)) && !queue_empty(as)) { | ||
210 | event = get_queued_event(as); | ||
211 | DBG("apm_emu: do_read, returning: %s\n", apm_event_name[event-1]); | ||
212 | if (copy_to_user(buf, &event, sizeof(event))) { | ||
213 | if (i < count) | ||
214 | break; | ||
215 | return -EFAULT; | ||
216 | } | ||
217 | switch (event) { | ||
218 | case APM_SYS_SUSPEND: | ||
219 | case APM_USER_SUSPEND: | ||
220 | as->suspends_read++; | ||
221 | break; | ||
222 | } | ||
223 | buf += sizeof(event); | ||
224 | i -= sizeof(event); | ||
225 | } | ||
226 | if (i < count) | ||
227 | return count - i; | ||
228 | if (signal_pending(current)) | ||
229 | return -ERESTARTSYS; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static unsigned int do_poll(struct file *fp, poll_table * wait) | ||
234 | { | ||
235 | struct apm_user * as; | ||
236 | |||
237 | as = fp->private_data; | ||
238 | if (check_apm_user(as, "poll")) | ||
239 | return 0; | ||
240 | poll_wait(fp, &apm_waitqueue, wait); | ||
241 | if (!queue_empty(as)) | ||
242 | return POLLIN | POLLRDNORM; | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int do_ioctl(struct inode * inode, struct file *filp, | ||
247 | u_int cmd, u_long arg) | ||
248 | { | ||
249 | struct apm_user * as; | ||
250 | DECLARE_WAITQUEUE(wait, current); | ||
251 | |||
252 | as = filp->private_data; | ||
253 | if (check_apm_user(as, "ioctl")) | ||
254 | return -EIO; | ||
255 | if (!as->suser) | ||
256 | return -EPERM; | ||
257 | switch (cmd) { | ||
258 | case APM_IOC_SUSPEND: | ||
259 | /* If a suspend message was sent to userland, we | ||
260 | * consider this as a confirmation message | ||
261 | */ | ||
262 | if (as->suspends_read > 0) { | ||
263 | as->suspends_read--; | ||
264 | as->suspends_pending--; | ||
265 | suspends_pending--; | ||
266 | } else { | ||
267 | // Route to PMU suspend ? | ||
268 | break; | ||
269 | } | ||
270 | as->suspend_waiting = 1; | ||
271 | add_wait_queue(&apm_waitqueue, &wait); | ||
272 | DBG("apm_emu: ioctl waking up sleep waiter !\n"); | ||
273 | wake_up(&apm_suspend_waitqueue); | ||
274 | mb(); | ||
275 | while(as->suspend_waiting && !signal_pending(current)) { | ||
276 | set_current_state(TASK_INTERRUPTIBLE); | ||
277 | schedule(); | ||
278 | } | ||
279 | set_current_state(TASK_RUNNING); | ||
280 | remove_wait_queue(&apm_waitqueue, &wait); | ||
281 | break; | ||
282 | default: | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int do_release(struct inode * inode, struct file * filp) | ||
289 | { | ||
290 | struct apm_user * as; | ||
291 | |||
292 | as = filp->private_data; | ||
293 | if (check_apm_user(as, "release")) | ||
294 | return 0; | ||
295 | filp->private_data = NULL; | ||
296 | lock_kernel(); | ||
297 | if (as->suspends_pending > 0) { | ||
298 | suspends_pending -= as->suspends_pending; | ||
299 | if (suspends_pending <= 0) | ||
300 | wake_up(&apm_suspend_waitqueue); | ||
301 | } | ||
302 | if (user_list == as) | ||
303 | user_list = as->next; | ||
304 | else { | ||
305 | struct apm_user * as1; | ||
306 | |||
307 | for (as1 = user_list; | ||
308 | (as1 != NULL) && (as1->next != as); | ||
309 | as1 = as1->next) | ||
310 | ; | ||
311 | if (as1 == NULL) | ||
312 | printk(KERN_ERR "apm: filp not in user list\n"); | ||
313 | else | ||
314 | as1->next = as->next; | ||
315 | } | ||
316 | unlock_kernel(); | ||
317 | kfree(as); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int do_open(struct inode * inode, struct file * filp) | ||
322 | { | ||
323 | struct apm_user * as; | ||
324 | |||
325 | as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); | ||
326 | if (as == NULL) { | ||
327 | printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", | ||
328 | sizeof(*as)); | ||
329 | return -ENOMEM; | ||
330 | } | ||
331 | as->magic = APM_BIOS_MAGIC; | ||
332 | as->event_tail = as->event_head = 0; | ||
333 | as->suspends_pending = 0; | ||
334 | as->suspends_read = 0; | ||
335 | /* | ||
336 | * XXX - this is a tiny bit broken, when we consider BSD | ||
337 | * process accounting. If the device is opened by root, we | ||
338 | * instantly flag that we used superuser privs. Who knows, | ||
339 | * we might close the device immediately without doing a | ||
340 | * privileged operation -- cevans | ||
341 | */ | ||
342 | as->suser = capable(CAP_SYS_ADMIN); | ||
343 | as->next = user_list; | ||
344 | user_list = as; | ||
345 | filp->private_data = as; | ||
346 | |||
347 | DBG("apm_emu: opened by %s, suser: %d\n", current->comm, (int)as->suser); | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | /* Wait for all clients to ack the suspend request. APM API | ||
353 | * doesn't provide a way to NAK, but this could be added | ||
354 | * here. | ||
355 | */ | ||
356 | static int wait_all_suspend(void) | ||
357 | { | ||
358 | DECLARE_WAITQUEUE(wait, current); | ||
359 | |||
360 | add_wait_queue(&apm_suspend_waitqueue, &wait); | ||
361 | DBG("apm_emu: wait_all_suspend(), suspends_pending: %d\n", suspends_pending); | ||
362 | while(suspends_pending > 0) { | ||
363 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
364 | schedule(); | ||
365 | } | ||
366 | set_current_state(TASK_RUNNING); | ||
367 | remove_wait_queue(&apm_suspend_waitqueue, &wait); | ||
368 | |||
369 | DBG("apm_emu: wait_all_suspend() - complete !\n"); | ||
370 | |||
371 | return 1; | ||
372 | } | ||
373 | |||
374 | static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when) | ||
375 | { | ||
376 | switch(when) { | ||
377 | case PBOOK_SLEEP_REQUEST: | ||
378 | queue_event(APM_SYS_SUSPEND, NULL); | ||
379 | if (!wait_all_suspend()) | ||
380 | return PBOOK_SLEEP_REFUSE; | ||
381 | break; | ||
382 | case PBOOK_SLEEP_REJECT: | ||
383 | case PBOOK_WAKE: | ||
384 | queue_event(APM_NORMAL_RESUME, NULL); | ||
385 | break; | ||
386 | } | ||
387 | return PBOOK_SLEEP_OK; | ||
388 | } | ||
389 | |||
390 | #define APM_CRITICAL 10 | ||
391 | #define APM_LOW 30 | ||
392 | |||
393 | static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length) | ||
394 | { | ||
395 | /* Arguments, with symbols from linux/apm_bios.h. Information is | ||
396 | from the Get Power Status (0x0a) call unless otherwise noted. | ||
397 | |||
398 | 0) Linux driver version (this will change if format changes) | ||
399 | 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. | ||
400 | 2) APM flags from APM Installation Check (0x00): | ||
401 | bit 0: APM_16_BIT_SUPPORT | ||
402 | bit 1: APM_32_BIT_SUPPORT | ||
403 | bit 2: APM_IDLE_SLOWS_CLOCK | ||
404 | bit 3: APM_BIOS_DISABLED | ||
405 | bit 4: APM_BIOS_DISENGAGED | ||
406 | 3) AC line status | ||
407 | 0x00: Off-line | ||
408 | 0x01: On-line | ||
409 | 0x02: On backup power (BIOS >= 1.1 only) | ||
410 | 0xff: Unknown | ||
411 | 4) Battery status | ||
412 | 0x00: High | ||
413 | 0x01: Low | ||
414 | 0x02: Critical | ||
415 | 0x03: Charging | ||
416 | 0x04: Selected battery not present (BIOS >= 1.2 only) | ||
417 | 0xff: Unknown | ||
418 | 5) Battery flag | ||
419 | bit 0: High | ||
420 | bit 1: Low | ||
421 | bit 2: Critical | ||
422 | bit 3: Charging | ||
423 | bit 7: No system battery | ||
424 | 0xff: Unknown | ||
425 | 6) Remaining battery life (percentage of charge): | ||
426 | 0-100: valid | ||
427 | -1: Unknown | ||
428 | 7) Remaining battery life (time units): | ||
429 | Number of remaining minutes or seconds | ||
430 | -1: Unknown | ||
431 | 8) min = minutes; sec = seconds */ | ||
432 | |||
433 | unsigned short ac_line_status = 0xff; | ||
434 | unsigned short battery_status = 0xff; | ||
435 | unsigned short battery_flag = 0xff; | ||
436 | int percentage = -1; | ||
437 | int time_units = -1; | ||
438 | int real_count = 0; | ||
439 | int i; | ||
440 | char * p = buf; | ||
441 | char charging = 0; | ||
442 | long charge = -1; | ||
443 | long amperage = 0; | ||
444 | unsigned long btype = 0; | ||
445 | |||
446 | ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0); | ||
447 | for (i=0; i<pmu_battery_count; i++) { | ||
448 | if (pmu_batteries[i].flags & PMU_BATT_PRESENT) { | ||
449 | if (percentage < 0) | ||
450 | percentage = 0; | ||
451 | if (charge < 0) | ||
452 | charge = 0; | ||
453 | percentage += (pmu_batteries[i].charge * 100) / | ||
454 | pmu_batteries[i].max_charge; | ||
455 | charge += pmu_batteries[i].charge; | ||
456 | amperage += pmu_batteries[i].amperage; | ||
457 | if (btype == 0) | ||
458 | btype = (pmu_batteries[i].flags & PMU_BATT_TYPE_MASK); | ||
459 | real_count++; | ||
460 | if ((pmu_batteries[i].flags & PMU_BATT_CHARGING)) | ||
461 | charging++; | ||
462 | } | ||
463 | } | ||
464 | if (real_count) { | ||
465 | if (amperage < 0) { | ||
466 | if (btype == PMU_BATT_TYPE_SMART) | ||
467 | time_units = (charge * 59) / (amperage * -1); | ||
468 | else | ||
469 | time_units = (charge * 16440) / (amperage * -60); | ||
470 | } | ||
471 | percentage /= real_count; | ||
472 | if (charging > 0) { | ||
473 | battery_status = 0x03; | ||
474 | battery_flag = 0x08; | ||
475 | } else if (percentage <= APM_CRITICAL) { | ||
476 | battery_status = 0x02; | ||
477 | battery_flag = 0x04; | ||
478 | } else if (percentage <= APM_LOW) { | ||
479 | battery_status = 0x01; | ||
480 | battery_flag = 0x02; | ||
481 | } else { | ||
482 | battery_status = 0x00; | ||
483 | battery_flag = 0x01; | ||
484 | } | ||
485 | } | ||
486 | p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", | ||
487 | driver_version, | ||
488 | (FAKE_APM_BIOS_VERSION >> 8) & 0xff, | ||
489 | FAKE_APM_BIOS_VERSION & 0xff, | ||
490 | 0, | ||
491 | ac_line_status, | ||
492 | battery_status, | ||
493 | battery_flag, | ||
494 | percentage, | ||
495 | time_units, | ||
496 | "min"); | ||
497 | |||
498 | return p - buf; | ||
499 | } | ||
500 | |||
501 | static struct file_operations apm_bios_fops = { | ||
502 | .owner = THIS_MODULE, | ||
503 | .read = do_read, | ||
504 | .poll = do_poll, | ||
505 | .ioctl = do_ioctl, | ||
506 | .open = do_open, | ||
507 | .release = do_release, | ||
508 | }; | ||
509 | |||
510 | static struct miscdevice apm_device = { | ||
511 | APM_MINOR_DEV, | ||
512 | "apm_bios", | ||
513 | &apm_bios_fops | ||
514 | }; | ||
515 | |||
516 | static int __init apm_emu_init(void) | ||
517 | { | ||
518 | struct proc_dir_entry *apm_proc; | ||
519 | |||
520 | if (sys_ctrler != SYS_CTRLER_PMU) { | ||
521 | printk(KERN_INFO "apm_emu: Requires a machine with a PMU.\n"); | ||
522 | return -ENODEV; | ||
523 | } | ||
524 | |||
525 | apm_proc = create_proc_info_entry("apm", 0, NULL, apm_emu_get_info); | ||
526 | if (apm_proc) | ||
527 | apm_proc->owner = THIS_MODULE; | ||
528 | |||
529 | misc_register(&apm_device); | ||
530 | |||
531 | pmu_register_sleep_notifier(&apm_sleep_notifier); | ||
532 | |||
533 | printk(KERN_INFO "apm_emu: APM Emulation %s initialized.\n", driver_version); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static void __exit apm_emu_exit(void) | ||
539 | { | ||
540 | pmu_unregister_sleep_notifier(&apm_sleep_notifier); | ||
541 | misc_deregister(&apm_device); | ||
542 | remove_proc_entry("apm", NULL); | ||
543 | |||
544 | printk(KERN_INFO "apm_emu: APM Emulation removed.\n"); | ||
545 | } | ||
546 | |||
547 | module_init(apm_emu_init); | ||
548 | module_exit(apm_emu_exit); | ||
549 | |||
550 | MODULE_AUTHOR("Benjamin Herrenschmidt"); | ||
551 | MODULE_DESCRIPTION("APM emulation layer for PowerMac"); | ||
552 | MODULE_LICENSE("GPL"); | ||
553 | |||
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c new file mode 100644 index 000000000000..5ad3a5a9eb7f --- /dev/null +++ b/drivers/macintosh/mac_hid.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * drivers/macintosh/mac_hid.c | ||
3 | * | ||
4 | * HID support stuff for Macintosh computers. | ||
5 | * | ||
6 | * Copyright (C) 2000 Franz Sirl. | ||
7 | * | ||
8 | * This file will soon be removed in favor of an uinput userspace tool. | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | #include <linux/sysctl.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | |||
19 | static struct input_dev emumousebtn; | ||
20 | static void emumousebtn_input_register(void); | ||
21 | static int mouse_emulate_buttons = 0; | ||
22 | static int mouse_button2_keycode = KEY_RIGHTCTRL; /* right control key */ | ||
23 | static int mouse_button3_keycode = KEY_RIGHTALT; /* right option key */ | ||
24 | static int mouse_last_keycode = 0; | ||
25 | |||
26 | #if defined(CONFIG_SYSCTL) | ||
27 | /* file(s) in /proc/sys/dev/mac_hid */ | ||
28 | ctl_table mac_hid_files[] = { | ||
29 | { | ||
30 | .ctl_name = DEV_MAC_HID_MOUSE_BUTTON_EMULATION, | ||
31 | .procname = "mouse_button_emulation", | ||
32 | .data = &mouse_emulate_buttons, | ||
33 | .maxlen = sizeof(int), | ||
34 | .mode = 0644, | ||
35 | .proc_handler = &proc_dointvec, | ||
36 | }, | ||
37 | { | ||
38 | .ctl_name = DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE, | ||
39 | .procname = "mouse_button2_keycode", | ||
40 | .data = &mouse_button2_keycode, | ||
41 | .maxlen = sizeof(int), | ||
42 | .mode = 0644, | ||
43 | .proc_handler = &proc_dointvec, | ||
44 | }, | ||
45 | { | ||
46 | .ctl_name = DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE, | ||
47 | .procname = "mouse_button3_keycode", | ||
48 | .data = &mouse_button3_keycode, | ||
49 | .maxlen = sizeof(int), | ||
50 | .mode = 0644, | ||
51 | .proc_handler = &proc_dointvec, | ||
52 | }, | ||
53 | { .ctl_name = 0 } | ||
54 | }; | ||
55 | |||
56 | /* dir in /proc/sys/dev */ | ||
57 | ctl_table mac_hid_dir[] = { | ||
58 | { | ||
59 | .ctl_name = DEV_MAC_HID, | ||
60 | .procname = "mac_hid", | ||
61 | .maxlen = 0, | ||
62 | .mode = 0555, | ||
63 | .child = mac_hid_files, | ||
64 | }, | ||
65 | { .ctl_name = 0 } | ||
66 | }; | ||
67 | |||
68 | /* /proc/sys/dev itself, in case that is not there yet */ | ||
69 | ctl_table mac_hid_root_dir[] = { | ||
70 | { | ||
71 | .ctl_name = CTL_DEV, | ||
72 | .procname = "dev", | ||
73 | .maxlen = 0, | ||
74 | .mode = 0555, | ||
75 | .child = mac_hid_dir, | ||
76 | }, | ||
77 | { .ctl_name = 0 } | ||
78 | }; | ||
79 | |||
80 | static struct ctl_table_header *mac_hid_sysctl_header; | ||
81 | |||
82 | #endif /* endif CONFIG_SYSCTL */ | ||
83 | |||
84 | int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down) | ||
85 | { | ||
86 | switch (caller) { | ||
87 | case 1: | ||
88 | /* Called from keyboard.c */ | ||
89 | if (mouse_emulate_buttons | ||
90 | && (keycode == mouse_button2_keycode | ||
91 | || keycode == mouse_button3_keycode)) { | ||
92 | if (mouse_emulate_buttons == 1) { | ||
93 | input_report_key(&emumousebtn, | ||
94 | keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT, | ||
95 | down); | ||
96 | input_sync(&emumousebtn); | ||
97 | return 1; | ||
98 | } | ||
99 | mouse_last_keycode = down ? keycode : 0; | ||
100 | } | ||
101 | break; | ||
102 | } | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons); | ||
107 | |||
108 | static void emumousebtn_input_register(void) | ||
109 | { | ||
110 | emumousebtn.name = "Macintosh mouse button emulation"; | ||
111 | |||
112 | init_input_dev(&emumousebtn); | ||
113 | |||
114 | emumousebtn.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
115 | emumousebtn.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
116 | emumousebtn.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
117 | |||
118 | emumousebtn.id.bustype = BUS_ADB; | ||
119 | emumousebtn.id.vendor = 0x0001; | ||
120 | emumousebtn.id.product = 0x0001; | ||
121 | emumousebtn.id.version = 0x0100; | ||
122 | |||
123 | input_register_device(&emumousebtn); | ||
124 | |||
125 | printk(KERN_INFO "input: Macintosh mouse button emulation\n"); | ||
126 | } | ||
127 | |||
128 | int __init mac_hid_init(void) | ||
129 | { | ||
130 | |||
131 | emumousebtn_input_register(); | ||
132 | |||
133 | #if defined(CONFIG_SYSCTL) | ||
134 | mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1); | ||
135 | #endif /* CONFIG_SYSCTL */ | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | device_initcall(mac_hid_init); | ||
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c new file mode 100644 index 000000000000..cf6a6f2248ac --- /dev/null +++ b/drivers/macintosh/macio-adb.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Driver for the ADB controller in the Mac I/O (Hydra) chip. | ||
3 | */ | ||
4 | #include <stdarg.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/errno.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <asm/prom.h> | ||
13 | #include <linux/adb.h> | ||
14 | #include <asm/io.h> | ||
15 | #include <asm/pgtable.h> | ||
16 | #include <asm/hydra.h> | ||
17 | #include <asm/irq.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <linux/init.h> | ||
20 | |||
21 | struct preg { | ||
22 | unsigned char r; | ||
23 | char pad[15]; | ||
24 | }; | ||
25 | |||
26 | struct adb_regs { | ||
27 | struct preg intr; | ||
28 | struct preg data[9]; | ||
29 | struct preg intr_enb; | ||
30 | struct preg dcount; | ||
31 | struct preg error; | ||
32 | struct preg ctrl; | ||
33 | struct preg autopoll; | ||
34 | struct preg active_hi; | ||
35 | struct preg active_lo; | ||
36 | struct preg test; | ||
37 | }; | ||
38 | |||
39 | /* Bits in intr and intr_enb registers */ | ||
40 | #define DFB 1 /* data from bus */ | ||
41 | #define TAG 2 /* transfer access grant */ | ||
42 | |||
43 | /* Bits in dcount register */ | ||
44 | #define HMB 0x0f /* how many bytes */ | ||
45 | #define APD 0x10 /* auto-poll data */ | ||
46 | |||
47 | /* Bits in error register */ | ||
48 | #define NRE 1 /* no response error */ | ||
49 | #define DLE 2 /* data lost error */ | ||
50 | |||
51 | /* Bits in ctrl register */ | ||
52 | #define TAR 1 /* transfer access request */ | ||
53 | #define DTB 2 /* data to bus */ | ||
54 | #define CRE 4 /* command response expected */ | ||
55 | #define ADB_RST 8 /* ADB reset */ | ||
56 | |||
57 | /* Bits in autopoll register */ | ||
58 | #define APE 1 /* autopoll enable */ | ||
59 | |||
60 | static volatile struct adb_regs __iomem *adb; | ||
61 | static struct adb_request *current_req, *last_req; | ||
62 | static DEFINE_SPINLOCK(macio_lock); | ||
63 | |||
64 | static int macio_probe(void); | ||
65 | static int macio_init(void); | ||
66 | static irqreturn_t macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs); | ||
67 | static int macio_send_request(struct adb_request *req, int sync); | ||
68 | static int macio_adb_autopoll(int devs); | ||
69 | static void macio_adb_poll(void); | ||
70 | static int macio_adb_reset_bus(void); | ||
71 | |||
72 | struct adb_driver macio_adb_driver = { | ||
73 | "MACIO", | ||
74 | macio_probe, | ||
75 | macio_init, | ||
76 | macio_send_request, | ||
77 | /*macio_write,*/ | ||
78 | macio_adb_autopoll, | ||
79 | macio_adb_poll, | ||
80 | macio_adb_reset_bus | ||
81 | }; | ||
82 | |||
83 | int macio_probe(void) | ||
84 | { | ||
85 | return find_compatible_devices("adb", "chrp,adb0")? 0: -ENODEV; | ||
86 | } | ||
87 | |||
88 | int macio_init(void) | ||
89 | { | ||
90 | struct device_node *adbs; | ||
91 | |||
92 | adbs = find_compatible_devices("adb", "chrp,adb0"); | ||
93 | if (adbs == 0) | ||
94 | return -ENXIO; | ||
95 | |||
96 | #if 0 | ||
97 | { int i; | ||
98 | |||
99 | printk("macio_adb_init: node = %p, addrs =", adbs->node); | ||
100 | for (i = 0; i < adbs->n_addrs; ++i) | ||
101 | printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); | ||
102 | printk(", intrs ="); | ||
103 | for (i = 0; i < adbs->n_intrs; ++i) | ||
104 | printk(" %x", adbs->intrs[i].line); | ||
105 | printk("\n"); } | ||
106 | #endif | ||
107 | |||
108 | adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); | ||
109 | |||
110 | out_8(&adb->ctrl.r, 0); | ||
111 | out_8(&adb->intr.r, 0); | ||
112 | out_8(&adb->error.r, 0); | ||
113 | out_8(&adb->active_hi.r, 0xff); /* for now, set all devices active */ | ||
114 | out_8(&adb->active_lo.r, 0xff); | ||
115 | out_8(&adb->autopoll.r, APE); | ||
116 | |||
117 | if (request_irq(adbs->intrs[0].line, macio_adb_interrupt, | ||
118 | 0, "ADB", (void *)0)) { | ||
119 | printk(KERN_ERR "ADB: can't get irq %d\n", | ||
120 | adbs->intrs[0].line); | ||
121 | return -EAGAIN; | ||
122 | } | ||
123 | out_8(&adb->intr_enb.r, DFB | TAG); | ||
124 | |||
125 | printk("adb: mac-io driver 1.0 for unified ADB\n"); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int macio_adb_autopoll(int devs) | ||
131 | { | ||
132 | unsigned long flags; | ||
133 | |||
134 | spin_lock_irqsave(&macio_lock, flags); | ||
135 | out_8(&adb->active_hi.r, devs >> 8); | ||
136 | out_8(&adb->active_lo.r, devs); | ||
137 | out_8(&adb->autopoll.r, devs? APE: 0); | ||
138 | spin_unlock_irqrestore(&macio_lock, flags); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int macio_adb_reset_bus(void) | ||
143 | { | ||
144 | unsigned long flags; | ||
145 | int timeout = 1000000; | ||
146 | |||
147 | /* Hrm... we may want to not lock interrupts for so | ||
148 | * long ... oh well, who uses that chip anyway ? :) | ||
149 | * That function will be seldomly used during boot | ||
150 | * on rare machines, so... | ||
151 | */ | ||
152 | spin_lock_irqsave(&macio_lock, flags); | ||
153 | out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | ADB_RST); | ||
154 | while ((in_8(&adb->ctrl.r) & ADB_RST) != 0) { | ||
155 | if (--timeout == 0) { | ||
156 | out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) & ~ADB_RST); | ||
157 | return -1; | ||
158 | } | ||
159 | } | ||
160 | spin_unlock_irqrestore(&macio_lock, flags); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /* Send an ADB command */ | ||
165 | static int macio_send_request(struct adb_request *req, int sync) | ||
166 | { | ||
167 | unsigned long flags; | ||
168 | int i; | ||
169 | |||
170 | if (req->data[0] != ADB_PACKET) | ||
171 | return -EINVAL; | ||
172 | |||
173 | for (i = 0; i < req->nbytes - 1; ++i) | ||
174 | req->data[i] = req->data[i+1]; | ||
175 | --req->nbytes; | ||
176 | |||
177 | req->next = NULL; | ||
178 | req->sent = 0; | ||
179 | req->complete = 0; | ||
180 | req->reply_len = 0; | ||
181 | |||
182 | spin_lock_irqsave(&macio_lock, flags); | ||
183 | if (current_req != 0) { | ||
184 | last_req->next = req; | ||
185 | last_req = req; | ||
186 | } else { | ||
187 | current_req = last_req = req; | ||
188 | out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR); | ||
189 | } | ||
190 | spin_unlock_irqrestore(&macio_lock, flags); | ||
191 | |||
192 | if (sync) { | ||
193 | while (!req->complete) | ||
194 | macio_adb_poll(); | ||
195 | } | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static irqreturn_t macio_adb_interrupt(int irq, void *arg, | ||
201 | struct pt_regs *regs) | ||
202 | { | ||
203 | int i, n, err; | ||
204 | struct adb_request *req = NULL; | ||
205 | unsigned char ibuf[16]; | ||
206 | int ibuf_len = 0; | ||
207 | int complete = 0; | ||
208 | int autopoll = 0; | ||
209 | int handled = 0; | ||
210 | |||
211 | spin_lock(&macio_lock); | ||
212 | if (in_8(&adb->intr.r) & TAG) { | ||
213 | handled = 1; | ||
214 | if ((req = current_req) != 0) { | ||
215 | /* put the current request in */ | ||
216 | for (i = 0; i < req->nbytes; ++i) | ||
217 | out_8(&adb->data[i].r, req->data[i]); | ||
218 | out_8(&adb->dcount.r, req->nbytes & HMB); | ||
219 | req->sent = 1; | ||
220 | if (req->reply_expected) { | ||
221 | out_8(&adb->ctrl.r, DTB + CRE); | ||
222 | } else { | ||
223 | out_8(&adb->ctrl.r, DTB); | ||
224 | current_req = req->next; | ||
225 | complete = 1; | ||
226 | if (current_req) | ||
227 | out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR); | ||
228 | } | ||
229 | } | ||
230 | out_8(&adb->intr.r, 0); | ||
231 | } | ||
232 | |||
233 | if (in_8(&adb->intr.r) & DFB) { | ||
234 | handled = 1; | ||
235 | err = in_8(&adb->error.r); | ||
236 | if (current_req && current_req->sent) { | ||
237 | /* this is the response to a command */ | ||
238 | req = current_req; | ||
239 | if (err == 0) { | ||
240 | req->reply_len = in_8(&adb->dcount.r) & HMB; | ||
241 | for (i = 0; i < req->reply_len; ++i) | ||
242 | req->reply[i] = in_8(&adb->data[i].r); | ||
243 | } | ||
244 | current_req = req->next; | ||
245 | complete = 1; | ||
246 | if (current_req) | ||
247 | out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR); | ||
248 | } else if (err == 0) { | ||
249 | /* autopoll data */ | ||
250 | n = in_8(&adb->dcount.r) & HMB; | ||
251 | for (i = 0; i < n; ++i) | ||
252 | ibuf[i] = in_8(&adb->data[i].r); | ||
253 | ibuf_len = n; | ||
254 | autopoll = (in_8(&adb->dcount.r) & APD) != 0; | ||
255 | } | ||
256 | out_8(&adb->error.r, 0); | ||
257 | out_8(&adb->intr.r, 0); | ||
258 | } | ||
259 | spin_unlock(&macio_lock); | ||
260 | if (complete && req) { | ||
261 | void (*done)(struct adb_request *) = req->done; | ||
262 | mb(); | ||
263 | req->complete = 1; | ||
264 | /* Here, we assume that if the request has a done member, the | ||
265 | * struct request will survive to setting req->complete to 1 | ||
266 | */ | ||
267 | if (done) | ||
268 | (*done)(req); | ||
269 | } | ||
270 | if (ibuf_len) | ||
271 | adb_input(ibuf, ibuf_len, regs, autopoll); | ||
272 | |||
273 | return IRQ_RETVAL(handled); | ||
274 | } | ||
275 | |||
276 | static void macio_adb_poll(void) | ||
277 | { | ||
278 | unsigned long flags; | ||
279 | |||
280 | local_irq_save(flags); | ||
281 | if (in_8(&adb->intr.r) != 0) | ||
282 | macio_adb_interrupt(0, NULL, NULL); | ||
283 | local_irq_restore(flags); | ||
284 | } | ||
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c new file mode 100644 index 000000000000..3a609ecd251b --- /dev/null +++ b/drivers/macintosh/macio_asic.c | |||
@@ -0,0 +1,636 @@ | |||
1 | /* | ||
2 | * Bus & driver management routines for devices within | ||
3 | * a MacIO ASIC. Interface to new driver model mostly | ||
4 | * stolen from the PCI version. | ||
5 | * | ||
6 | * TODO: | ||
7 | * | ||
8 | * - Don't probe below media bay by default, but instead provide | ||
9 | * some hooks for media bay to dynamically add/remove it's own | ||
10 | * sub-devices. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/pci_ids.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/macio.h> | ||
22 | #include <asm/pmac_feature.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/pci-bridge.h> | ||
25 | |||
26 | #undef DEBUG | ||
27 | |||
28 | #define MAX_NODE_NAME_SIZE (BUS_ID_SIZE - 12) | ||
29 | |||
30 | static struct macio_chip *macio_on_hold; | ||
31 | |||
32 | static int macio_bus_match(struct device *dev, struct device_driver *drv) | ||
33 | { | ||
34 | struct macio_dev * macio_dev = to_macio_device(dev); | ||
35 | struct macio_driver * macio_drv = to_macio_driver(drv); | ||
36 | const struct of_match * matches = macio_drv->match_table; | ||
37 | |||
38 | if (!matches) | ||
39 | return 0; | ||
40 | |||
41 | return of_match_device(matches, &macio_dev->ofdev) != NULL; | ||
42 | } | ||
43 | |||
44 | struct macio_dev *macio_dev_get(struct macio_dev *dev) | ||
45 | { | ||
46 | struct device *tmp; | ||
47 | |||
48 | if (!dev) | ||
49 | return NULL; | ||
50 | tmp = get_device(&dev->ofdev.dev); | ||
51 | if (tmp) | ||
52 | return to_macio_device(tmp); | ||
53 | else | ||
54 | return NULL; | ||
55 | } | ||
56 | |||
57 | void macio_dev_put(struct macio_dev *dev) | ||
58 | { | ||
59 | if (dev) | ||
60 | put_device(&dev->ofdev.dev); | ||
61 | } | ||
62 | |||
63 | |||
64 | static int macio_device_probe(struct device *dev) | ||
65 | { | ||
66 | int error = -ENODEV; | ||
67 | struct macio_driver *drv; | ||
68 | struct macio_dev *macio_dev; | ||
69 | const struct of_match *match; | ||
70 | |||
71 | drv = to_macio_driver(dev->driver); | ||
72 | macio_dev = to_macio_device(dev); | ||
73 | |||
74 | if (!drv->probe) | ||
75 | return error; | ||
76 | |||
77 | macio_dev_get(macio_dev); | ||
78 | |||
79 | match = of_match_device(drv->match_table, &macio_dev->ofdev); | ||
80 | if (match) | ||
81 | error = drv->probe(macio_dev, match); | ||
82 | if (error) | ||
83 | macio_dev_put(macio_dev); | ||
84 | |||
85 | return error; | ||
86 | } | ||
87 | |||
88 | static int macio_device_remove(struct device *dev) | ||
89 | { | ||
90 | struct macio_dev * macio_dev = to_macio_device(dev); | ||
91 | struct macio_driver * drv = to_macio_driver(dev->driver); | ||
92 | |||
93 | if (dev->driver && drv->remove) | ||
94 | drv->remove(macio_dev); | ||
95 | macio_dev_put(macio_dev); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static void macio_device_shutdown(struct device *dev) | ||
101 | { | ||
102 | struct macio_dev * macio_dev = to_macio_device(dev); | ||
103 | struct macio_driver * drv = to_macio_driver(dev->driver); | ||
104 | |||
105 | if (dev->driver && drv->shutdown) | ||
106 | drv->shutdown(macio_dev); | ||
107 | } | ||
108 | |||
109 | static int macio_device_suspend(struct device *dev, u32 state) | ||
110 | { | ||
111 | struct macio_dev * macio_dev = to_macio_device(dev); | ||
112 | struct macio_driver * drv = to_macio_driver(dev->driver); | ||
113 | |||
114 | if (dev->driver && drv->suspend) | ||
115 | return drv->suspend(macio_dev, state); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int macio_device_resume(struct device * dev) | ||
120 | { | ||
121 | struct macio_dev * macio_dev = to_macio_device(dev); | ||
122 | struct macio_driver * drv = to_macio_driver(dev->driver); | ||
123 | |||
124 | if (dev->driver && drv->resume) | ||
125 | return drv->resume(macio_dev); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | struct bus_type macio_bus_type = { | ||
130 | .name = "macio", | ||
131 | .match = macio_bus_match, | ||
132 | .suspend = macio_device_suspend, | ||
133 | .resume = macio_device_resume, | ||
134 | }; | ||
135 | |||
136 | static int __init macio_bus_driver_init(void) | ||
137 | { | ||
138 | return bus_register(&macio_bus_type); | ||
139 | } | ||
140 | |||
141 | postcore_initcall(macio_bus_driver_init); | ||
142 | |||
143 | |||
144 | /** | ||
145 | * macio_release_dev - free a macio device structure when all users of it are finished. | ||
146 | * @dev: device that's been disconnected | ||
147 | * | ||
148 | * Will be called only by the device core when all users of this macio device are | ||
149 | * done. This currently means never as we don't hot remove any macio device yet, | ||
150 | * though that will happen with mediabay based devices in a later implementation. | ||
151 | */ | ||
152 | static void macio_release_dev(struct device *dev) | ||
153 | { | ||
154 | struct macio_dev *mdev; | ||
155 | |||
156 | mdev = to_macio_device(dev); | ||
157 | kfree(mdev); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * macio_resource_quirks - tweak or skip some resources for a device | ||
162 | * @np: pointer to the device node | ||
163 | * @res: resulting resource | ||
164 | * @index: index of resource in node | ||
165 | * | ||
166 | * If this routine returns non-null, then the resource is completely | ||
167 | * skipped. | ||
168 | */ | ||
169 | static int macio_resource_quirks(struct device_node *np, struct resource *res, int index) | ||
170 | { | ||
171 | if (res->flags & IORESOURCE_MEM) { | ||
172 | /* Grand Central has too large resource 0 on some machines */ | ||
173 | if (index == 0 && !strcmp(np->name, "gc")) { | ||
174 | np->addrs[0].size = 0x20000; | ||
175 | res->end = res->start + 0x1ffff; | ||
176 | } | ||
177 | /* Airport has bogus resource 2 */ | ||
178 | if (index >= 2 && !strcmp(np->name, "radio")) | ||
179 | return 1; | ||
180 | /* DBDMAs may have bogus sizes */ | ||
181 | if ((res->start & 0x0001f000) == 0x00008000) { | ||
182 | np->addrs[index].size = 0x100; | ||
183 | res->end = res->start + 0xff; | ||
184 | } | ||
185 | /* ESCC parent eats child resources. We could have added a level of hierarchy, | ||
186 | * but I don't really feel the need for it */ | ||
187 | if (!strcmp(np->name, "escc")) | ||
188 | return 1; | ||
189 | /* ESCC has bogus resources >= 3 */ | ||
190 | if (index >= 3 && !(strcmp(np->name, "ch-a") && strcmp(np->name, "ch-b"))) | ||
191 | return 1; | ||
192 | /* Media bay has too many resources, keep only first one */ | ||
193 | if (index > 0 && !strcmp(np->name, "media-bay")) | ||
194 | return 1; | ||
195 | /* Some older IDE resources have bogus sizes */ | ||
196 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && | ||
197 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { | ||
198 | if (index == 0 && np->addrs[0].size > 0x1000) { | ||
199 | np->addrs[0].size = 0x1000; | ||
200 | res->end = res->start + 0xfff; | ||
201 | } | ||
202 | if (index == 1 && np->addrs[1].size > 0x100) { | ||
203 | np->addrs[1].size = 0x100; | ||
204 | res->end = res->start + 0xff; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | |||
212 | /** | ||
213 | * macio_add_one_device - Add one device from OF node to the device tree | ||
214 | * @chip: pointer to the macio_chip holding the device | ||
215 | * @np: pointer to the device node in the OF tree | ||
216 | * @in_bay: set to 1 if device is part of a media-bay | ||
217 | * | ||
218 | * When media-bay is changed to hotswap drivers, this function will | ||
219 | * be exposed to the bay driver some way... | ||
220 | */ | ||
221 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct device *parent, | ||
222 | struct device_node *np, struct macio_dev *in_bay, | ||
223 | struct resource *parent_res) | ||
224 | { | ||
225 | struct macio_dev *dev; | ||
226 | int i, j; | ||
227 | u32 *reg; | ||
228 | |||
229 | if (np == NULL) | ||
230 | return NULL; | ||
231 | |||
232 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
233 | if (!dev) | ||
234 | return NULL; | ||
235 | memset(dev, 0, sizeof(*dev)); | ||
236 | |||
237 | dev->bus = &chip->lbus; | ||
238 | dev->media_bay = in_bay; | ||
239 | dev->ofdev.node = np; | ||
240 | dev->ofdev.dma_mask = 0xffffffffUL; | ||
241 | dev->ofdev.dev.dma_mask = &dev->ofdev.dma_mask; | ||
242 | dev->ofdev.dev.parent = parent; | ||
243 | dev->ofdev.dev.bus = &macio_bus_type; | ||
244 | dev->ofdev.dev.release = macio_release_dev; | ||
245 | |||
246 | #ifdef DEBUG | ||
247 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", | ||
248 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); | ||
249 | #endif | ||
250 | |||
251 | /* MacIO itself has a different reg, we use it's PCI base */ | ||
252 | if (np == chip->of_node) { | ||
253 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", chip->lbus.index, | ||
254 | #ifdef CONFIG_PCI | ||
255 | pci_resource_start(chip->lbus.pdev, 0), | ||
256 | #else | ||
257 | 0, /* NuBus may want to do something better here */ | ||
258 | #endif | ||
259 | MAX_NODE_NAME_SIZE, np->name); | ||
260 | } else { | ||
261 | reg = (u32 *)get_property(np, "reg", NULL); | ||
262 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, | ||
263 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); | ||
264 | } | ||
265 | |||
266 | /* For now, we use pre-parsed entries in the device-tree for | ||
267 | * interrupt routing and addresses, but we should change that | ||
268 | * to dynamically parsed entries and so get rid of most of the | ||
269 | * clutter in struct device_node | ||
270 | */ | ||
271 | for (i = j = 0; i < np->n_intrs; i++) { | ||
272 | struct resource *res = &dev->interrupt[j]; | ||
273 | |||
274 | if (j >= MACIO_DEV_COUNT_IRQS) | ||
275 | break; | ||
276 | res->start = np->intrs[i].line; | ||
277 | res->flags = IORESOURCE_IO; | ||
278 | if (np->intrs[j].sense) | ||
279 | res->flags |= IORESOURCE_IRQ_LOWLEVEL; | ||
280 | else | ||
281 | res->flags |= IORESOURCE_IRQ_HIGHEDGE; | ||
282 | res->name = dev->ofdev.dev.bus_id; | ||
283 | if (macio_resource_quirks(np, res, i)) | ||
284 | memset(res, 0, sizeof(struct resource)); | ||
285 | else | ||
286 | j++; | ||
287 | } | ||
288 | dev->n_interrupts = j; | ||
289 | for (i = j = 0; i < np->n_addrs; i++) { | ||
290 | struct resource *res = &dev->resource[j]; | ||
291 | |||
292 | if (j >= MACIO_DEV_COUNT_RESOURCES) | ||
293 | break; | ||
294 | res->start = np->addrs[i].address; | ||
295 | res->end = np->addrs[i].address + np->addrs[i].size - 1; | ||
296 | res->flags = IORESOURCE_MEM; | ||
297 | res->name = dev->ofdev.dev.bus_id; | ||
298 | if (macio_resource_quirks(np, res, i)) | ||
299 | memset(res, 0, sizeof(struct resource)); | ||
300 | else { | ||
301 | j++; | ||
302 | /* Currently, we consider failure as harmless, this may | ||
303 | * change in the future, once I've found all the device | ||
304 | * tree bugs in older machines & worked around them | ||
305 | */ | ||
306 | if (insert_resource(parent_res, res)) | ||
307 | printk(KERN_WARNING "Can't request resource %d for MacIO" | ||
308 | " device %s\n", i, dev->ofdev.dev.bus_id); | ||
309 | } | ||
310 | } | ||
311 | dev->n_resources = j; | ||
312 | |||
313 | if (of_device_register(&dev->ofdev) != 0) { | ||
314 | printk(KERN_DEBUG"macio: device registration error for %s!\n", | ||
315 | dev->ofdev.dev.bus_id); | ||
316 | kfree(dev); | ||
317 | return NULL; | ||
318 | } | ||
319 | |||
320 | return dev; | ||
321 | } | ||
322 | |||
323 | static int macio_skip_device(struct device_node *np) | ||
324 | { | ||
325 | if (strncmp(np->name, "battery", 7) == 0) | ||
326 | return 1; | ||
327 | if (strncmp(np->name, "escc-legacy", 11) == 0) | ||
328 | return 1; | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * macio_pci_add_devices - Adds sub-devices of mac-io to the device tree | ||
334 | * @chip: pointer to the macio_chip holding the devices | ||
335 | * | ||
336 | * This function will do the job of extracting devices from the | ||
337 | * Open Firmware device tree, build macio_dev structures and add | ||
338 | * them to the Linux device tree. | ||
339 | * | ||
340 | * For now, childs of media-bay are added now as well. This will | ||
341 | * change rsn though. | ||
342 | */ | ||
343 | static void macio_pci_add_devices(struct macio_chip *chip) | ||
344 | { | ||
345 | struct device_node *np, *pnode; | ||
346 | struct macio_dev *rdev, *mdev, *mbdev = NULL, *sdev = NULL; | ||
347 | struct device *parent = NULL; | ||
348 | struct resource *root_res = &iomem_resource; | ||
349 | |||
350 | /* Add a node for the macio bus itself */ | ||
351 | #ifdef CONFIG_PCI | ||
352 | if (chip->lbus.pdev) { | ||
353 | parent = &chip->lbus.pdev->dev; | ||
354 | root_res = &chip->lbus.pdev->resource[0]; | ||
355 | } | ||
356 | #endif | ||
357 | pnode = of_node_get(chip->of_node); | ||
358 | if (pnode == NULL) | ||
359 | return; | ||
360 | |||
361 | /* Add macio itself to hierarchy */ | ||
362 | rdev = macio_add_one_device(chip, parent, pnode, NULL, root_res); | ||
363 | if (rdev == NULL) | ||
364 | return; | ||
365 | root_res = &rdev->resource[0]; | ||
366 | |||
367 | /* First scan 1st level */ | ||
368 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { | ||
369 | if (!macio_skip_device(np)) { | ||
370 | of_node_get(np); | ||
371 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, root_res); | ||
372 | if (mdev == NULL) | ||
373 | of_node_put(np); | ||
374 | else if (strncmp(np->name, "media-bay", 9) == 0) | ||
375 | mbdev = mdev; | ||
376 | else if (strncmp(np->name, "escc", 4) == 0) | ||
377 | sdev = mdev; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* Add media bay devices if any */ | ||
382 | if (mbdev) | ||
383 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) != NULL;) | ||
384 | if (!macio_skip_device(np)) { | ||
385 | of_node_get(np); | ||
386 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, mbdev, | ||
387 | root_res) == NULL) | ||
388 | of_node_put(np); | ||
389 | } | ||
390 | /* Add serial ports if any */ | ||
391 | if (sdev) { | ||
392 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) != NULL;) | ||
393 | if (!macio_skip_device(np)) { | ||
394 | of_node_get(np); | ||
395 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, NULL, | ||
396 | root_res) == NULL) | ||
397 | of_node_put(np); | ||
398 | } | ||
399 | } | ||
400 | } | ||
401 | |||
402 | |||
403 | /** | ||
404 | * macio_register_driver - Registers a new MacIO device driver | ||
405 | * @drv: pointer to the driver definition structure | ||
406 | */ | ||
407 | int macio_register_driver(struct macio_driver *drv) | ||
408 | { | ||
409 | int count = 0; | ||
410 | |||
411 | /* initialize common driver fields */ | ||
412 | drv->driver.name = drv->name; | ||
413 | drv->driver.bus = &macio_bus_type; | ||
414 | drv->driver.probe = macio_device_probe; | ||
415 | drv->driver.remove = macio_device_remove; | ||
416 | drv->driver.shutdown = macio_device_shutdown; | ||
417 | |||
418 | /* register with core */ | ||
419 | count = driver_register(&drv->driver); | ||
420 | return count ? count : 1; | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * macio_unregister_driver - Unregisters a new MacIO device driver | ||
425 | * @drv: pointer to the driver definition structure | ||
426 | */ | ||
427 | void macio_unregister_driver(struct macio_driver *drv) | ||
428 | { | ||
429 | driver_unregister(&drv->driver); | ||
430 | } | ||
431 | |||
432 | /** | ||
433 | * macio_request_resource - Request an MMIO resource | ||
434 | * @dev: pointer to the device holding the resource | ||
435 | * @resource_no: resource number to request | ||
436 | * @name: resource name | ||
437 | * | ||
438 | * Mark memory region number @resource_no associated with MacIO | ||
439 | * device @dev as being reserved by owner @name. Do not access | ||
440 | * any address inside the memory regions unless this call returns | ||
441 | * successfully. | ||
442 | * | ||
443 | * Returns 0 on success, or %EBUSY on error. A warning | ||
444 | * message is also printed on failure. | ||
445 | */ | ||
446 | int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name) | ||
447 | { | ||
448 | if (macio_resource_len(dev, resource_no) == 0) | ||
449 | return 0; | ||
450 | |||
451 | if (!request_mem_region(macio_resource_start(dev, resource_no), | ||
452 | macio_resource_len(dev, resource_no), | ||
453 | name)) | ||
454 | goto err_out; | ||
455 | |||
456 | return 0; | ||
457 | |||
458 | err_out: | ||
459 | printk (KERN_WARNING "MacIO: Unable to reserve resource #%d:%lx@%lx" | ||
460 | " for device %s\n", | ||
461 | resource_no, | ||
462 | macio_resource_len(dev, resource_no), | ||
463 | macio_resource_start(dev, resource_no), | ||
464 | dev->ofdev.dev.bus_id); | ||
465 | return -EBUSY; | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * macio_release_resource - Release an MMIO resource | ||
470 | * @dev: pointer to the device holding the resource | ||
471 | * @resource_no: resource number to release | ||
472 | */ | ||
473 | void macio_release_resource(struct macio_dev *dev, int resource_no) | ||
474 | { | ||
475 | if (macio_resource_len(dev, resource_no) == 0) | ||
476 | return; | ||
477 | release_mem_region(macio_resource_start(dev, resource_no), | ||
478 | macio_resource_len(dev, resource_no)); | ||
479 | } | ||
480 | |||
481 | /** | ||
482 | * macio_request_resources - Reserve all memory resources | ||
483 | * @dev: MacIO device whose resources are to be reserved | ||
484 | * @name: Name to be associated with resource. | ||
485 | * | ||
486 | * Mark all memory regions associated with MacIO device @dev as | ||
487 | * being reserved by owner @name. Do not access any address inside | ||
488 | * the memory regions unless this call returns successfully. | ||
489 | * | ||
490 | * Returns 0 on success, or %EBUSY on error. A warning | ||
491 | * message is also printed on failure. | ||
492 | */ | ||
493 | int macio_request_resources(struct macio_dev *dev, const char *name) | ||
494 | { | ||
495 | int i; | ||
496 | |||
497 | for (i = 0; i < dev->n_resources; i++) | ||
498 | if (macio_request_resource(dev, i, name)) | ||
499 | goto err_out; | ||
500 | return 0; | ||
501 | |||
502 | err_out: | ||
503 | while(--i >= 0) | ||
504 | macio_release_resource(dev, i); | ||
505 | |||
506 | return -EBUSY; | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * macio_release_resources - Release reserved memory resources | ||
511 | * @dev: MacIO device whose resources were previously reserved | ||
512 | */ | ||
513 | |||
514 | void macio_release_resources(struct macio_dev *dev) | ||
515 | { | ||
516 | int i; | ||
517 | |||
518 | for (i = 0; i < dev->n_resources; i++) | ||
519 | macio_release_resource(dev, i); | ||
520 | } | ||
521 | |||
522 | |||
523 | #ifdef CONFIG_PCI | ||
524 | |||
525 | static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
526 | { | ||
527 | struct device_node* np; | ||
528 | struct macio_chip* chip; | ||
529 | |||
530 | if (ent->vendor != PCI_VENDOR_ID_APPLE) | ||
531 | return -ENODEV; | ||
532 | |||
533 | /* Note regarding refcounting: We assume pci_device_to_OF_node() is ported | ||
534 | * to new OF APIs and returns a node with refcount incremented. This isn't | ||
535 | * the case today, but on the other hand ppc32 doesn't do refcounting. This | ||
536 | * will have to be fixed when going to ppc64. --BenH. | ||
537 | */ | ||
538 | np = pci_device_to_OF_node(pdev); | ||
539 | if (np == NULL) | ||
540 | return -ENODEV; | ||
541 | |||
542 | /* This assumption is wrong, fix that here for now until I fix the arch */ | ||
543 | of_node_get(np); | ||
544 | |||
545 | /* We also assume that pmac_feature will have done a get() on nodes stored | ||
546 | * in the macio chips array | ||
547 | */ | ||
548 | chip = macio_find(np, macio_unknown); | ||
549 | of_node_put(np); | ||
550 | if (chip == NULL) | ||
551 | return -ENODEV; | ||
552 | |||
553 | /* XXX Need locking ??? */ | ||
554 | if (chip->lbus.pdev == NULL) { | ||
555 | chip->lbus.pdev = pdev; | ||
556 | chip->lbus.chip = chip; | ||
557 | pci_set_drvdata(pdev, &chip->lbus); | ||
558 | pci_set_master(pdev); | ||
559 | } | ||
560 | |||
561 | printk(KERN_INFO "MacIO PCI driver attached to %s chipset\n", | ||
562 | chip->name); | ||
563 | |||
564 | /* | ||
565 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines | ||
566 | * have 2 macio ASICs. I must probe the "main" one first or IDE ordering | ||
567 | * will be incorrect. So I put on "hold" the second one since it seem to | ||
568 | * appear first on PCI | ||
569 | */ | ||
570 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) | ||
571 | if (macio_chips[0].lbus.pdev == NULL) { | ||
572 | macio_on_hold = chip; | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | macio_pci_add_devices(chip); | ||
577 | if (macio_on_hold && macio_chips[0].lbus.pdev != NULL) { | ||
578 | macio_pci_add_devices(macio_on_hold); | ||
579 | macio_on_hold = NULL; | ||
580 | } | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static void __devexit macio_pci_remove(struct pci_dev* pdev) | ||
586 | { | ||
587 | panic("removing of macio-asic not supported !\n"); | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | * MacIO is matched against any Apple ID, it's probe() function | ||
592 | * will then decide wether it applies or not | ||
593 | */ | ||
594 | static const struct pci_device_id __devinitdata pci_ids [] = { { | ||
595 | .vendor = PCI_VENDOR_ID_APPLE, | ||
596 | .device = PCI_ANY_ID, | ||
597 | .subvendor = PCI_ANY_ID, | ||
598 | .subdevice = PCI_ANY_ID, | ||
599 | |||
600 | }, { /* end: all zeroes */ } | ||
601 | }; | ||
602 | MODULE_DEVICE_TABLE (pci, pci_ids); | ||
603 | |||
604 | /* pci driver glue; this is a "new style" PCI driver module */ | ||
605 | static struct pci_driver macio_pci_driver = { | ||
606 | .name = (char *) "macio", | ||
607 | .id_table = pci_ids, | ||
608 | |||
609 | .probe = macio_pci_probe, | ||
610 | .remove = macio_pci_remove, | ||
611 | }; | ||
612 | |||
613 | #endif /* CONFIG_PCI */ | ||
614 | |||
615 | static int __init macio_module_init (void) | ||
616 | { | ||
617 | #ifdef CONFIG_PCI | ||
618 | int rc; | ||
619 | |||
620 | rc = pci_register_driver(&macio_pci_driver); | ||
621 | if (rc) | ||
622 | return rc; | ||
623 | #endif /* CONFIG_PCI */ | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | module_init(macio_module_init); | ||
628 | |||
629 | EXPORT_SYMBOL(macio_register_driver); | ||
630 | EXPORT_SYMBOL(macio_unregister_driver); | ||
631 | EXPORT_SYMBOL(macio_dev_get); | ||
632 | EXPORT_SYMBOL(macio_dev_put); | ||
633 | EXPORT_SYMBOL(macio_request_resource); | ||
634 | EXPORT_SYMBOL(macio_release_resource); | ||
635 | EXPORT_SYMBOL(macio_request_resources); | ||
636 | EXPORT_SYMBOL(macio_release_resources); | ||
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c new file mode 100644 index 000000000000..0be3ac6cc169 --- /dev/null +++ b/drivers/macintosh/macserial.c | |||
@@ -0,0 +1,3036 @@ | |||
1 | /* | ||
2 | * macserial.c: Serial port driver for Power Macintoshes. | ||
3 | * | ||
4 | * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. | ||
5 | * | ||
6 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | ||
7 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
8 | * | ||
9 | * Receive DMA code by Takashi Oe <toe@unlserve.unl.edu>. | ||
10 | * | ||
11 | * $Id: macserial.c,v 1.24.2.4 1999/10/19 04:36:42 paulus Exp $ | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/signal.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <linux/tty.h> | ||
23 | #include <linux/tty_flip.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/fcntl.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/init.h> | ||
31 | #ifdef CONFIG_SERIAL_CONSOLE | ||
32 | #include <linux/console.h> | ||
33 | #endif | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/bitops.h> | ||
36 | |||
37 | #include <asm/sections.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/pgtable.h> | ||
40 | #include <asm/irq.h> | ||
41 | #include <asm/prom.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/segment.h> | ||
44 | #include <asm/machdep.h> | ||
45 | #include <asm/pmac_feature.h> | ||
46 | #include <linux/adb.h> | ||
47 | #include <linux/pmu.h> | ||
48 | #ifdef CONFIG_KGDB | ||
49 | #include <asm/kgdb.h> | ||
50 | #endif | ||
51 | #include <asm/dbdma.h> | ||
52 | |||
53 | #include "macserial.h" | ||
54 | |||
55 | #ifdef CONFIG_PMAC_PBOOK | ||
56 | static int serial_notify_sleep(struct pmu_sleep_notifier *self, int when); | ||
57 | static struct pmu_sleep_notifier serial_sleep_notifier = { | ||
58 | serial_notify_sleep, | ||
59 | SLEEP_LEVEL_MISC, | ||
60 | }; | ||
61 | #endif | ||
62 | |||
63 | #define SUPPORT_SERIAL_DMA | ||
64 | #define MACSERIAL_VERSION "2.0" | ||
65 | |||
66 | /* | ||
67 | * It would be nice to dynamically allocate everything that | ||
68 | * depends on NUM_SERIAL, so we could support any number of | ||
69 | * Z8530s, but for now... | ||
70 | */ | ||
71 | #define NUM_SERIAL 2 /* Max number of ZS chips supported */ | ||
72 | #define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ | ||
73 | |||
74 | /* On PowerMacs, the hardware takes care of the SCC recovery time, | ||
75 | but we need the eieio to make sure that the accesses occur | ||
76 | in the order we want. */ | ||
77 | #define RECOVERY_DELAY eieio() | ||
78 | |||
79 | static struct tty_driver *serial_driver; | ||
80 | |||
81 | struct mac_zschannel zs_channels[NUM_CHANNELS]; | ||
82 | |||
83 | struct mac_serial zs_soft[NUM_CHANNELS]; | ||
84 | int zs_channels_found; | ||
85 | struct mac_serial *zs_chain; /* list of all channels */ | ||
86 | |||
87 | struct tty_struct zs_ttys[NUM_CHANNELS]; | ||
88 | |||
89 | static int is_powerbook; | ||
90 | |||
91 | #ifdef CONFIG_SERIAL_CONSOLE | ||
92 | static struct console sercons; | ||
93 | #endif | ||
94 | |||
95 | #ifdef CONFIG_KGDB | ||
96 | struct mac_zschannel *zs_kgdbchan; | ||
97 | static unsigned char scc_inittab[] = { | ||
98 | 9, 0x80, /* reset A side (CHRA) */ | ||
99 | 13, 0, /* set baud rate divisor */ | ||
100 | 12, 1, | ||
101 | 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ | ||
102 | 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ | ||
103 | 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ | ||
104 | 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ | ||
105 | 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ | ||
106 | }; | ||
107 | #endif | ||
108 | #define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */ | ||
109 | |||
110 | /* serial subtype definitions */ | ||
111 | #define SERIAL_TYPE_NORMAL 1 | ||
112 | |||
113 | /* number of characters left in xmit buffer before we ask for more */ | ||
114 | #define WAKEUP_CHARS 256 | ||
115 | |||
116 | /* | ||
117 | * Debugging. | ||
118 | */ | ||
119 | #undef SERIAL_DEBUG_INTR | ||
120 | #undef SERIAL_DEBUG_OPEN | ||
121 | #undef SERIAL_DEBUG_FLOW | ||
122 | #undef SERIAL_DEBUG_POWER | ||
123 | #undef SERIAL_DEBUG_THROTTLE | ||
124 | #undef SERIAL_DEBUG_STOP | ||
125 | #undef SERIAL_DEBUG_BAUDS | ||
126 | |||
127 | #define RS_STROBE_TIME 10 | ||
128 | #define RS_ISR_PASS_LIMIT 256 | ||
129 | |||
130 | #define _INLINE_ inline | ||
131 | |||
132 | #ifdef SERIAL_DEBUG_OPEN | ||
133 | #define OPNDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) | ||
134 | #else | ||
135 | #define OPNDBG(fmt, arg...) do { } while (0) | ||
136 | #endif | ||
137 | #ifdef SERIAL_DEBUG_POWER | ||
138 | #define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) | ||
139 | #else | ||
140 | #define PWRDBG(fmt, arg...) do { } while (0) | ||
141 | #endif | ||
142 | #ifdef SERIAL_DEBUG_BAUDS | ||
143 | #define BAUDBG(fmt, arg...) printk(fmt , ## arg) | ||
144 | #else | ||
145 | #define BAUDBG(fmt, arg...) do { } while (0) | ||
146 | #endif | ||
147 | |||
148 | static void probe_sccs(void); | ||
149 | static void change_speed(struct mac_serial *info, struct termios *old); | ||
150 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout); | ||
151 | static int set_scc_power(struct mac_serial * info, int state); | ||
152 | static int setup_scc(struct mac_serial * info); | ||
153 | static void dbdma_reset(volatile struct dbdma_regs *dma); | ||
154 | static void dbdma_flush(volatile struct dbdma_regs *dma); | ||
155 | static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs); | ||
156 | static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs); | ||
157 | static void dma_init(struct mac_serial * info); | ||
158 | static void rxdma_start(struct mac_serial * info, int curr); | ||
159 | static void rxdma_to_tty(struct mac_serial * info); | ||
160 | |||
161 | /* | ||
162 | * tmp_buf is used as a temporary buffer by serial_write. We need to | ||
163 | * lock it in case the copy_from_user blocks while swapping in a page, | ||
164 | * and some other program tries to do a serial write at the same time. | ||
165 | * Since the lock will only come under contention when the system is | ||
166 | * swapping and available memory is low, it makes sense to share one | ||
167 | * buffer across all the serial ports, since it significantly saves | ||
168 | * memory if large numbers of serial ports are open. | ||
169 | */ | ||
170 | static unsigned char *tmp_buf; | ||
171 | static DECLARE_MUTEX(tmp_buf_sem); | ||
172 | |||
173 | |||
174 | static inline int __pmac | ||
175 | serial_paranoia_check(struct mac_serial *info, | ||
176 | char *name, const char *routine) | ||
177 | { | ||
178 | #ifdef SERIAL_PARANOIA_CHECK | ||
179 | static const char badmagic[] = KERN_WARNING | ||
180 | "Warning: bad magic number for serial struct %s in %s\n"; | ||
181 | static const char badinfo[] = KERN_WARNING | ||
182 | "Warning: null mac_serial for %s in %s\n"; | ||
183 | |||
184 | if (!info) { | ||
185 | printk(badinfo, name, routine); | ||
186 | return 1; | ||
187 | } | ||
188 | if (info->magic != SERIAL_MAGIC) { | ||
189 | printk(badmagic, name, routine); | ||
190 | return 1; | ||
191 | } | ||
192 | #endif | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * Reading and writing Z8530 registers. | ||
198 | */ | ||
199 | static inline unsigned char __pmac read_zsreg(struct mac_zschannel *channel, | ||
200 | unsigned char reg) | ||
201 | { | ||
202 | unsigned char retval; | ||
203 | unsigned long flags; | ||
204 | |||
205 | /* | ||
206 | * We have to make this atomic. | ||
207 | */ | ||
208 | spin_lock_irqsave(&channel->lock, flags); | ||
209 | if (reg != 0) { | ||
210 | *channel->control = reg; | ||
211 | RECOVERY_DELAY; | ||
212 | } | ||
213 | retval = *channel->control; | ||
214 | RECOVERY_DELAY; | ||
215 | spin_unlock_irqrestore(&channel->lock, flags); | ||
216 | return retval; | ||
217 | } | ||
218 | |||
219 | static inline void __pmac write_zsreg(struct mac_zschannel *channel, | ||
220 | unsigned char reg, unsigned char value) | ||
221 | { | ||
222 | unsigned long flags; | ||
223 | |||
224 | spin_lock_irqsave(&channel->lock, flags); | ||
225 | if (reg != 0) { | ||
226 | *channel->control = reg; | ||
227 | RECOVERY_DELAY; | ||
228 | } | ||
229 | *channel->control = value; | ||
230 | RECOVERY_DELAY; | ||
231 | spin_unlock_irqrestore(&channel->lock, flags); | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | static inline unsigned char __pmac read_zsdata(struct mac_zschannel *channel) | ||
236 | { | ||
237 | unsigned char retval; | ||
238 | |||
239 | retval = *channel->data; | ||
240 | RECOVERY_DELAY; | ||
241 | return retval; | ||
242 | } | ||
243 | |||
244 | static inline void write_zsdata(struct mac_zschannel *channel, | ||
245 | unsigned char value) | ||
246 | { | ||
247 | *channel->data = value; | ||
248 | RECOVERY_DELAY; | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | static inline void load_zsregs(struct mac_zschannel *channel, | ||
253 | unsigned char *regs) | ||
254 | { | ||
255 | ZS_CLEARERR(channel); | ||
256 | ZS_CLEARFIFO(channel); | ||
257 | /* Load 'em up */ | ||
258 | write_zsreg(channel, R4, regs[R4]); | ||
259 | write_zsreg(channel, R10, regs[R10]); | ||
260 | write_zsreg(channel, R3, regs[R3] & ~RxENABLE); | ||
261 | write_zsreg(channel, R5, regs[R5] & ~TxENAB); | ||
262 | write_zsreg(channel, R1, regs[R1]); | ||
263 | write_zsreg(channel, R9, regs[R9]); | ||
264 | write_zsreg(channel, R11, regs[R11]); | ||
265 | write_zsreg(channel, R12, regs[R12]); | ||
266 | write_zsreg(channel, R13, regs[R13]); | ||
267 | write_zsreg(channel, R14, regs[R14]); | ||
268 | write_zsreg(channel, R15, regs[R15]); | ||
269 | write_zsreg(channel, R3, regs[R3]); | ||
270 | write_zsreg(channel, R5, regs[R5]); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* Sets or clears DTR/RTS on the requested line */ | ||
275 | static inline void zs_rtsdtr(struct mac_serial *ss, int set) | ||
276 | { | ||
277 | if (set) | ||
278 | ss->curregs[5] |= (RTS | DTR); | ||
279 | else | ||
280 | ss->curregs[5] &= ~(RTS | DTR); | ||
281 | write_zsreg(ss->zs_channel, 5, ss->curregs[5]); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | /* Utility routines for the Zilog */ | ||
286 | static inline int get_zsbaud(struct mac_serial *ss) | ||
287 | { | ||
288 | struct mac_zschannel *channel = ss->zs_channel; | ||
289 | int brg; | ||
290 | |||
291 | if ((ss->curregs[R11] & TCBR) == 0) { | ||
292 | /* higher rates don't use the baud rate generator */ | ||
293 | return (ss->curregs[R4] & X32CLK)? ZS_CLOCK/32: ZS_CLOCK/16; | ||
294 | } | ||
295 | /* The baud rate is split up between two 8-bit registers in | ||
296 | * what is termed 'BRG time constant' format in my docs for | ||
297 | * the chip, it is a function of the clk rate the chip is | ||
298 | * receiving which happens to be constant. | ||
299 | */ | ||
300 | brg = (read_zsreg(channel, 13) << 8); | ||
301 | brg |= read_zsreg(channel, 12); | ||
302 | return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); | ||
303 | } | ||
304 | |||
305 | /* On receive, this clears errors and the receiver interrupts */ | ||
306 | static inline void rs_recv_clear(struct mac_zschannel *zsc) | ||
307 | { | ||
308 | write_zsreg(zsc, 0, ERR_RES); | ||
309 | write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * Reset a Descriptor-Based DMA channel. | ||
314 | */ | ||
315 | static void dbdma_reset(volatile struct dbdma_regs *dma) | ||
316 | { | ||
317 | int i; | ||
318 | |||
319 | out_le32(&dma->control, (WAKE|FLUSH|PAUSE|RUN) << 16); | ||
320 | |||
321 | /* | ||
322 | * Yes this looks peculiar, but apparently it needs to be this | ||
323 | * way on some machines. (We need to make sure the DBDMA | ||
324 | * engine has actually got the write above and responded | ||
325 | * to it. - paulus) | ||
326 | */ | ||
327 | for (i = 200; i > 0; --i) | ||
328 | if (ld_le32(&dma->status) & RUN) | ||
329 | udelay(1); | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * Tells a DBDMA channel to stop and write any buffered data | ||
334 | * it might have to memory. | ||
335 | */ | ||
336 | static _INLINE_ void dbdma_flush(volatile struct dbdma_regs *dma) | ||
337 | { | ||
338 | int i = 0; | ||
339 | |||
340 | out_le32(&dma->control, (FLUSH << 16) | FLUSH); | ||
341 | while (((in_le32(&dma->status) & FLUSH) != 0) && (i++ < 100)) | ||
342 | udelay(1); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * ---------------------------------------------------------------------- | ||
347 | * | ||
348 | * Here starts the interrupt handling routines. All of the following | ||
349 | * subroutines are declared as inline and are folded into | ||
350 | * rs_interrupt(). They were separated out for readability's sake. | ||
351 | * | ||
352 | * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 | ||
353 | * ----------------------------------------------------------------------- | ||
354 | */ | ||
355 | |||
356 | /* | ||
357 | * This routine is used by the interrupt handler to schedule | ||
358 | * processing in the software interrupt portion of the driver. | ||
359 | */ | ||
360 | static _INLINE_ void rs_sched_event(struct mac_serial *info, | ||
361 | int event) | ||
362 | { | ||
363 | info->event |= 1 << event; | ||
364 | schedule_work(&info->tqueue); | ||
365 | } | ||
366 | |||
367 | /* Work out the flag value for a z8530 status value. */ | ||
368 | static _INLINE_ int stat_to_flag(int stat) | ||
369 | { | ||
370 | int flag; | ||
371 | |||
372 | if (stat & Rx_OVR) { | ||
373 | flag = TTY_OVERRUN; | ||
374 | } else if (stat & FRM_ERR) { | ||
375 | flag = TTY_FRAME; | ||
376 | } else if (stat & PAR_ERR) { | ||
377 | flag = TTY_PARITY; | ||
378 | } else | ||
379 | flag = 0; | ||
380 | return flag; | ||
381 | } | ||
382 | |||
383 | static _INLINE_ void receive_chars(struct mac_serial *info, | ||
384 | struct pt_regs *regs) | ||
385 | { | ||
386 | struct tty_struct *tty = info->tty; | ||
387 | unsigned char ch, stat, flag; | ||
388 | |||
389 | while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { | ||
390 | |||
391 | stat = read_zsreg(info->zs_channel, R1); | ||
392 | ch = read_zsdata(info->zs_channel); | ||
393 | |||
394 | #ifdef CONFIG_KGDB | ||
395 | if (info->kgdb_channel) { | ||
396 | if (ch == 0x03 || ch == '$') | ||
397 | breakpoint(); | ||
398 | if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) | ||
399 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
400 | return; | ||
401 | } | ||
402 | #endif | ||
403 | if (!tty) | ||
404 | continue; | ||
405 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) | ||
406 | tty_flip_buffer_push(tty); | ||
407 | |||
408 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
409 | static int flip_buf_ovf; | ||
410 | if (++flip_buf_ovf <= 1) | ||
411 | printk(KERN_WARNING "FB. overflow: %d\n", | ||
412 | flip_buf_ovf); | ||
413 | break; | ||
414 | } | ||
415 | tty->flip.count++; | ||
416 | { | ||
417 | static int flip_max_cnt; | ||
418 | if (flip_max_cnt < tty->flip.count) | ||
419 | flip_max_cnt = tty->flip.count; | ||
420 | } | ||
421 | flag = stat_to_flag(stat); | ||
422 | if (flag) | ||
423 | /* reset the error indication */ | ||
424 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
425 | *tty->flip.flag_buf_ptr++ = flag; | ||
426 | *tty->flip.char_buf_ptr++ = ch; | ||
427 | } | ||
428 | if (tty) | ||
429 | tty_flip_buffer_push(tty); | ||
430 | } | ||
431 | |||
432 | static void transmit_chars(struct mac_serial *info) | ||
433 | { | ||
434 | if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) | ||
435 | return; | ||
436 | info->tx_active = 0; | ||
437 | |||
438 | if (info->x_char && !info->power_wait) { | ||
439 | /* Send next char */ | ||
440 | write_zsdata(info->zs_channel, info->x_char); | ||
441 | info->x_char = 0; | ||
442 | info->tx_active = 1; | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped | ||
447 | || info->power_wait) { | ||
448 | write_zsreg(info->zs_channel, 0, RES_Tx_P); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | /* Send char */ | ||
453 | write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]); | ||
454 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); | ||
455 | info->xmit_cnt--; | ||
456 | info->tx_active = 1; | ||
457 | |||
458 | if (info->xmit_cnt < WAKEUP_CHARS) | ||
459 | rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); | ||
460 | } | ||
461 | |||
462 | static void powerup_done(unsigned long data) | ||
463 | { | ||
464 | struct mac_serial *info = (struct mac_serial *) data; | ||
465 | unsigned long flags; | ||
466 | |||
467 | spin_lock_irqsave(&info->lock, flags); | ||
468 | info->power_wait = 0; | ||
469 | transmit_chars(info); | ||
470 | spin_unlock_irqrestore(&info->lock, flags); | ||
471 | } | ||
472 | |||
473 | static _INLINE_ void status_handle(struct mac_serial *info) | ||
474 | { | ||
475 | unsigned char status; | ||
476 | |||
477 | /* Get status from Read Register 0 */ | ||
478 | status = read_zsreg(info->zs_channel, 0); | ||
479 | |||
480 | /* Check for DCD transitions */ | ||
481 | if (((status ^ info->read_reg_zero) & DCD) != 0 | ||
482 | && info->tty && !C_CLOCAL(info->tty)) { | ||
483 | if (status & DCD) { | ||
484 | wake_up_interruptible(&info->open_wait); | ||
485 | } else { | ||
486 | if (info->tty) | ||
487 | tty_hangup(info->tty); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /* Check for CTS transitions */ | ||
492 | if (info->tty && C_CRTSCTS(info->tty)) { | ||
493 | /* | ||
494 | * For some reason, on the Power Macintosh, | ||
495 | * it seems that the CTS bit is 1 when CTS is | ||
496 | * *negated* and 0 when it is asserted. | ||
497 | * The DCD bit doesn't seem to be inverted | ||
498 | * like this. | ||
499 | */ | ||
500 | if ((status & CTS) == 0) { | ||
501 | if (info->tx_stopped) { | ||
502 | #ifdef SERIAL_DEBUG_FLOW | ||
503 | printk(KERN_DEBUG "CTS up\n"); | ||
504 | #endif | ||
505 | info->tx_stopped = 0; | ||
506 | if (!info->tx_active) | ||
507 | transmit_chars(info); | ||
508 | } | ||
509 | } else { | ||
510 | #ifdef SERIAL_DEBUG_FLOW | ||
511 | printk(KERN_DEBUG "CTS down\n"); | ||
512 | #endif | ||
513 | info->tx_stopped = 1; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | /* Clear status condition... */ | ||
518 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); | ||
519 | info->read_reg_zero = status; | ||
520 | } | ||
521 | |||
522 | static _INLINE_ void receive_special_dma(struct mac_serial *info) | ||
523 | { | ||
524 | unsigned char stat, flag; | ||
525 | volatile struct dbdma_regs *rd = &info->rx->dma; | ||
526 | int where = RX_BUF_SIZE; | ||
527 | |||
528 | spin_lock(&info->rx_dma_lock); | ||
529 | if ((ld_le32(&rd->status) & ACTIVE) != 0) | ||
530 | dbdma_flush(rd); | ||
531 | if (in_le32(&rd->cmdptr) | ||
532 | == virt_to_bus(info->rx_cmds[info->rx_cbuf] + 1)) | ||
533 | where -= in_le16(&info->rx->res_count); | ||
534 | where--; | ||
535 | |||
536 | stat = read_zsreg(info->zs_channel, R1); | ||
537 | |||
538 | flag = stat_to_flag(stat); | ||
539 | if (flag) { | ||
540 | info->rx_flag_buf[info->rx_cbuf][where] = flag; | ||
541 | /* reset the error indication */ | ||
542 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
543 | } | ||
544 | |||
545 | spin_unlock(&info->rx_dma_lock); | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * This is the serial driver's generic interrupt routine | ||
550 | */ | ||
551 | static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | ||
552 | { | ||
553 | struct mac_serial *info = (struct mac_serial *) dev_id; | ||
554 | unsigned char zs_intreg; | ||
555 | int shift; | ||
556 | unsigned long flags; | ||
557 | int handled = 0; | ||
558 | |||
559 | if (!(info->flags & ZILOG_INITIALIZED)) { | ||
560 | printk(KERN_WARNING "rs_interrupt: irq %d, port not " | ||
561 | "initialized\n", irq); | ||
562 | disable_irq(irq); | ||
563 | return IRQ_NONE; | ||
564 | } | ||
565 | |||
566 | /* NOTE: The read register 3, which holds the irq status, | ||
567 | * does so for both channels on each chip. Although | ||
568 | * the status value itself must be read from the A | ||
569 | * channel and is only valid when read from channel A. | ||
570 | * Yes... broken hardware... | ||
571 | */ | ||
572 | #define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) | ||
573 | |||
574 | if (info->zs_chan_a == info->zs_channel) | ||
575 | shift = 3; /* Channel A */ | ||
576 | else | ||
577 | shift = 0; /* Channel B */ | ||
578 | |||
579 | spin_lock_irqsave(&info->lock, flags); | ||
580 | for (;;) { | ||
581 | zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; | ||
582 | #ifdef SERIAL_DEBUG_INTR | ||
583 | printk(KERN_DEBUG "rs_interrupt: irq %d, zs_intreg 0x%x\n", | ||
584 | irq, (int)zs_intreg); | ||
585 | #endif | ||
586 | |||
587 | if ((zs_intreg & CHAN_IRQMASK) == 0) | ||
588 | break; | ||
589 | handled = 1; | ||
590 | |||
591 | if (zs_intreg & CHBRxIP) { | ||
592 | /* If we are doing DMA, we only ask for interrupts | ||
593 | on characters with errors or special conditions. */ | ||
594 | if (info->dma_initted) | ||
595 | receive_special_dma(info); | ||
596 | else | ||
597 | receive_chars(info, regs); | ||
598 | } | ||
599 | if (zs_intreg & CHBTxIP) | ||
600 | transmit_chars(info); | ||
601 | if (zs_intreg & CHBEXT) | ||
602 | status_handle(info); | ||
603 | } | ||
604 | spin_unlock_irqrestore(&info->lock, flags); | ||
605 | return IRQ_RETVAL(handled); | ||
606 | } | ||
607 | |||
608 | /* Transmit DMA interrupt - not used at present */ | ||
609 | static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
610 | { | ||
611 | return IRQ_HANDLED; | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * Receive DMA interrupt. | ||
616 | */ | ||
617 | static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
618 | { | ||
619 | struct mac_serial *info = (struct mac_serial *) dev_id; | ||
620 | volatile struct dbdma_cmd *cd; | ||
621 | |||
622 | if (!info->dma_initted) | ||
623 | return IRQ_NONE; | ||
624 | spin_lock(&info->rx_dma_lock); | ||
625 | /* First, confirm that this interrupt is, indeed, coming */ | ||
626 | /* from Rx DMA */ | ||
627 | cd = info->rx_cmds[info->rx_cbuf] + 2; | ||
628 | if ((in_le16(&cd->xfer_status) & (RUN | ACTIVE)) != (RUN | ACTIVE)) { | ||
629 | spin_unlock(&info->rx_dma_lock); | ||
630 | return IRQ_NONE; | ||
631 | } | ||
632 | if (info->rx_fbuf != RX_NO_FBUF) { | ||
633 | info->rx_cbuf = info->rx_fbuf; | ||
634 | if (++info->rx_fbuf == info->rx_nbuf) | ||
635 | info->rx_fbuf = 0; | ||
636 | if (info->rx_fbuf == info->rx_ubuf) | ||
637 | info->rx_fbuf = RX_NO_FBUF; | ||
638 | } | ||
639 | spin_unlock(&info->rx_dma_lock); | ||
640 | return IRQ_HANDLED; | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * ------------------------------------------------------------------- | ||
645 | * Here ends the serial interrupt routines. | ||
646 | * ------------------------------------------------------------------- | ||
647 | */ | ||
648 | |||
649 | /* | ||
650 | * ------------------------------------------------------------ | ||
651 | * rs_stop() and rs_start() | ||
652 | * | ||
653 | * This routines are called before setting or resetting tty->stopped. | ||
654 | * ------------------------------------------------------------ | ||
655 | */ | ||
656 | static void rs_stop(struct tty_struct *tty) | ||
657 | { | ||
658 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
659 | |||
660 | #ifdef SERIAL_DEBUG_STOP | ||
661 | printk(KERN_DEBUG "rs_stop %ld....\n", | ||
662 | tty->ldisc.chars_in_buffer(tty)); | ||
663 | #endif | ||
664 | |||
665 | if (serial_paranoia_check(info, tty->name, "rs_stop")) | ||
666 | return; | ||
667 | |||
668 | #if 0 | ||
669 | spin_lock_irqsave(&info->lock, flags); | ||
670 | if (info->curregs[5] & TxENAB) { | ||
671 | info->curregs[5] &= ~TxENAB; | ||
672 | info->pendregs[5] &= ~TxENAB; | ||
673 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
674 | } | ||
675 | spin_unlock_irqrestore(&info->lock, flags); | ||
676 | #endif | ||
677 | } | ||
678 | |||
679 | static void rs_start(struct tty_struct *tty) | ||
680 | { | ||
681 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
682 | unsigned long flags; | ||
683 | |||
684 | #ifdef SERIAL_DEBUG_STOP | ||
685 | printk(KERN_DEBUG "rs_start %ld....\n", | ||
686 | tty->ldisc.chars_in_buffer(tty)); | ||
687 | #endif | ||
688 | |||
689 | if (serial_paranoia_check(info, tty->name, "rs_start")) | ||
690 | return; | ||
691 | |||
692 | spin_lock_irqsave(&info->lock, flags); | ||
693 | #if 0 | ||
694 | if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { | ||
695 | info->curregs[5] |= TxENAB; | ||
696 | info->pendregs[5] = info->curregs[5]; | ||
697 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
698 | } | ||
699 | #else | ||
700 | if (info->xmit_cnt && info->xmit_buf && !info->tx_active) { | ||
701 | transmit_chars(info); | ||
702 | } | ||
703 | #endif | ||
704 | spin_unlock_irqrestore(&info->lock, flags); | ||
705 | } | ||
706 | |||
707 | static void do_softint(void *private_) | ||
708 | { | ||
709 | struct mac_serial *info = (struct mac_serial *) private_; | ||
710 | struct tty_struct *tty; | ||
711 | |||
712 | tty = info->tty; | ||
713 | if (!tty) | ||
714 | return; | ||
715 | |||
716 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) | ||
717 | tty_wakeup(tty); | ||
718 | } | ||
719 | |||
720 | static int startup(struct mac_serial * info) | ||
721 | { | ||
722 | int delay; | ||
723 | |||
724 | OPNDBG("startup() (ttyS%d, irq %d)\n", info->line, info->irq); | ||
725 | |||
726 | if (info->flags & ZILOG_INITIALIZED) { | ||
727 | OPNDBG(" -> already inited\n"); | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | if (!info->xmit_buf) { | ||
732 | info->xmit_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL); | ||
733 | if (!info->xmit_buf) | ||
734 | return -ENOMEM; | ||
735 | } | ||
736 | |||
737 | OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq); | ||
738 | |||
739 | delay = set_scc_power(info, 1); | ||
740 | |||
741 | setup_scc(info); | ||
742 | |||
743 | if (delay) { | ||
744 | unsigned long flags; | ||
745 | |||
746 | /* delay is in ms */ | ||
747 | spin_lock_irqsave(&info->lock, flags); | ||
748 | info->power_wait = 1; | ||
749 | mod_timer(&info->powerup_timer, | ||
750 | jiffies + (delay * HZ + 999) / 1000); | ||
751 | spin_unlock_irqrestore(&info->lock, flags); | ||
752 | } | ||
753 | |||
754 | OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq); | ||
755 | |||
756 | info->flags |= ZILOG_INITIALIZED; | ||
757 | enable_irq(info->irq); | ||
758 | if (info->dma_initted) { | ||
759 | enable_irq(info->rx_dma_irq); | ||
760 | } | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static _INLINE_ void rxdma_start(struct mac_serial * info, int curr) | ||
766 | { | ||
767 | volatile struct dbdma_regs *rd = &info->rx->dma; | ||
768 | volatile struct dbdma_cmd *cd = info->rx_cmds[curr]; | ||
769 | |||
770 | //printk(KERN_DEBUG "SCC: rxdma_start\n"); | ||
771 | |||
772 | st_le32(&rd->cmdptr, virt_to_bus(cd)); | ||
773 | out_le32(&rd->control, (RUN << 16) | RUN); | ||
774 | } | ||
775 | |||
776 | static void rxdma_to_tty(struct mac_serial *info) | ||
777 | { | ||
778 | struct tty_struct *tty = info->tty; | ||
779 | volatile struct dbdma_regs *rd = &info->rx->dma; | ||
780 | unsigned long flags; | ||
781 | int residue, available, space, do_queue; | ||
782 | |||
783 | if (!tty) | ||
784 | return; | ||
785 | |||
786 | do_queue = 0; | ||
787 | spin_lock_irqsave(&info->rx_dma_lock, flags); | ||
788 | more: | ||
789 | space = TTY_FLIPBUF_SIZE - tty->flip.count; | ||
790 | if (!space) { | ||
791 | do_queue++; | ||
792 | goto out; | ||
793 | } | ||
794 | residue = 0; | ||
795 | if (info->rx_ubuf == info->rx_cbuf) { | ||
796 | if ((ld_le32(&rd->status) & ACTIVE) != 0) { | ||
797 | dbdma_flush(rd); | ||
798 | if (in_le32(&rd->cmdptr) | ||
799 | == virt_to_bus(info->rx_cmds[info->rx_cbuf]+1)) | ||
800 | residue = in_le16(&info->rx->res_count); | ||
801 | } | ||
802 | } | ||
803 | available = RX_BUF_SIZE - residue - info->rx_done_bytes; | ||
804 | if (available > space) | ||
805 | available = space; | ||
806 | if (available) { | ||
807 | memcpy(tty->flip.char_buf_ptr, | ||
808 | info->rx_char_buf[info->rx_ubuf] + info->rx_done_bytes, | ||
809 | available); | ||
810 | memcpy(tty->flip.flag_buf_ptr, | ||
811 | info->rx_flag_buf[info->rx_ubuf] + info->rx_done_bytes, | ||
812 | available); | ||
813 | tty->flip.char_buf_ptr += available; | ||
814 | tty->flip.count += available; | ||
815 | tty->flip.flag_buf_ptr += available; | ||
816 | memset(info->rx_flag_buf[info->rx_ubuf] + info->rx_done_bytes, | ||
817 | 0, available); | ||
818 | info->rx_done_bytes += available; | ||
819 | do_queue++; | ||
820 | } | ||
821 | if (info->rx_done_bytes == RX_BUF_SIZE) { | ||
822 | volatile struct dbdma_cmd *cd = info->rx_cmds[info->rx_ubuf]; | ||
823 | |||
824 | if (info->rx_ubuf == info->rx_cbuf) | ||
825 | goto out; | ||
826 | /* mark rx_char_buf[rx_ubuf] free */ | ||
827 | st_le16(&cd->command, DBDMA_NOP); | ||
828 | cd++; | ||
829 | st_le32(&cd->cmd_dep, 0); | ||
830 | st_le32((unsigned int *)&cd->res_count, 0); | ||
831 | cd++; | ||
832 | st_le16(&cd->xfer_status, 0); | ||
833 | |||
834 | if (info->rx_fbuf == RX_NO_FBUF) { | ||
835 | info->rx_fbuf = info->rx_ubuf; | ||
836 | if (!(ld_le32(&rd->status) & ACTIVE)) { | ||
837 | dbdma_reset(&info->rx->dma); | ||
838 | rxdma_start(info, info->rx_ubuf); | ||
839 | info->rx_cbuf = info->rx_ubuf; | ||
840 | } | ||
841 | } | ||
842 | info->rx_done_bytes = 0; | ||
843 | if (++info->rx_ubuf == info->rx_nbuf) | ||
844 | info->rx_ubuf = 0; | ||
845 | if (info->rx_fbuf == info->rx_ubuf) | ||
846 | info->rx_fbuf = RX_NO_FBUF; | ||
847 | goto more; | ||
848 | } | ||
849 | out: | ||
850 | spin_unlock_irqrestore(&info->rx_dma_lock, flags); | ||
851 | if (do_queue) | ||
852 | tty_flip_buffer_push(tty); | ||
853 | } | ||
854 | |||
855 | static void poll_rxdma(unsigned long private_) | ||
856 | { | ||
857 | struct mac_serial *info = (struct mac_serial *) private_; | ||
858 | unsigned long flags; | ||
859 | |||
860 | rxdma_to_tty(info); | ||
861 | spin_lock_irqsave(&info->rx_dma_lock, flags); | ||
862 | mod_timer(&info->poll_dma_timer, RX_DMA_TIMER); | ||
863 | spin_unlock_irqrestore(&info->rx_dma_lock, flags); | ||
864 | } | ||
865 | |||
866 | static void dma_init(struct mac_serial * info) | ||
867 | { | ||
868 | int i, size; | ||
869 | volatile struct dbdma_cmd *cd; | ||
870 | unsigned char *p; | ||
871 | |||
872 | info->rx_nbuf = 8; | ||
873 | |||
874 | /* various mem set up */ | ||
875 | size = sizeof(struct dbdma_cmd) * (3 * info->rx_nbuf + 2) | ||
876 | + (RX_BUF_SIZE * 2 + sizeof(*info->rx_cmds) | ||
877 | + sizeof(*info->rx_char_buf) + sizeof(*info->rx_flag_buf)) | ||
878 | * info->rx_nbuf; | ||
879 | info->dma_priv = kmalloc(size, GFP_KERNEL | GFP_DMA); | ||
880 | if (info->dma_priv == NULL) | ||
881 | return; | ||
882 | memset(info->dma_priv, 0, size); | ||
883 | |||
884 | info->rx_cmds = (volatile struct dbdma_cmd **)info->dma_priv; | ||
885 | info->rx_char_buf = (unsigned char **) (info->rx_cmds + info->rx_nbuf); | ||
886 | info->rx_flag_buf = info->rx_char_buf + info->rx_nbuf; | ||
887 | p = (unsigned char *) (info->rx_flag_buf + info->rx_nbuf); | ||
888 | for (i = 0; i < info->rx_nbuf; i++, p += RX_BUF_SIZE) | ||
889 | info->rx_char_buf[i] = p; | ||
890 | for (i = 0; i < info->rx_nbuf; i++, p += RX_BUF_SIZE) | ||
891 | info->rx_flag_buf[i] = p; | ||
892 | |||
893 | /* a bit of DMA programming */ | ||
894 | cd = info->rx_cmds[0] = (volatile struct dbdma_cmd *) DBDMA_ALIGN(p); | ||
895 | st_le16(&cd->command, DBDMA_NOP); | ||
896 | cd++; | ||
897 | st_le16(&cd->req_count, RX_BUF_SIZE); | ||
898 | st_le16(&cd->command, INPUT_MORE); | ||
899 | st_le32(&cd->phy_addr, virt_to_bus(info->rx_char_buf[0])); | ||
900 | cd++; | ||
901 | st_le16(&cd->req_count, 4); | ||
902 | st_le16(&cd->command, STORE_WORD | INTR_ALWAYS); | ||
903 | st_le32(&cd->phy_addr, virt_to_bus(cd-2)); | ||
904 | st_le32(&cd->cmd_dep, DBDMA_STOP); | ||
905 | for (i = 1; i < info->rx_nbuf; i++) { | ||
906 | info->rx_cmds[i] = ++cd; | ||
907 | st_le16(&cd->command, DBDMA_NOP); | ||
908 | cd++; | ||
909 | st_le16(&cd->req_count, RX_BUF_SIZE); | ||
910 | st_le16(&cd->command, INPUT_MORE); | ||
911 | st_le32(&cd->phy_addr, virt_to_bus(info->rx_char_buf[i])); | ||
912 | cd++; | ||
913 | st_le16(&cd->req_count, 4); | ||
914 | st_le16(&cd->command, STORE_WORD | INTR_ALWAYS); | ||
915 | st_le32(&cd->phy_addr, virt_to_bus(cd-2)); | ||
916 | st_le32(&cd->cmd_dep, DBDMA_STOP); | ||
917 | } | ||
918 | cd++; | ||
919 | st_le16(&cd->command, DBDMA_NOP | BR_ALWAYS); | ||
920 | st_le32(&cd->cmd_dep, virt_to_bus(info->rx_cmds[0])); | ||
921 | |||
922 | /* setup DMA to our liking */ | ||
923 | dbdma_reset(&info->rx->dma); | ||
924 | st_le32(&info->rx->dma.intr_sel, 0x10001); | ||
925 | st_le32(&info->rx->dma.br_sel, 0x10001); | ||
926 | out_le32(&info->rx->dma.wait_sel, 0x10001); | ||
927 | |||
928 | /* set various flags */ | ||
929 | info->rx_ubuf = 0; | ||
930 | info->rx_cbuf = 0; | ||
931 | info->rx_fbuf = info->rx_ubuf + 1; | ||
932 | if (info->rx_fbuf == info->rx_nbuf) | ||
933 | info->rx_fbuf = RX_NO_FBUF; | ||
934 | info->rx_done_bytes = 0; | ||
935 | |||
936 | /* setup polling */ | ||
937 | init_timer(&info->poll_dma_timer); | ||
938 | info->poll_dma_timer.function = (void *)&poll_rxdma; | ||
939 | info->poll_dma_timer.data = (unsigned long)info; | ||
940 | |||
941 | info->dma_initted = 1; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * FixZeroBug....Works around a bug in the SCC receving channel. | ||
946 | * Taken from Darwin code, 15 Sept. 2000 -DanM | ||
947 | * | ||
948 | * The following sequence prevents a problem that is seen with O'Hare ASICs | ||
949 | * (most versions -- also with some Heathrow and Hydra ASICs) where a zero | ||
950 | * at the input to the receiver becomes 'stuck' and locks up the receiver. | ||
951 | * This problem can occur as a result of a zero bit at the receiver input | ||
952 | * coincident with any of the following events: | ||
953 | * | ||
954 | * The SCC is initialized (hardware or software). | ||
955 | * A framing error is detected. | ||
956 | * The clocking option changes from synchronous or X1 asynchronous | ||
957 | * clocking to X16, X32, or X64 asynchronous clocking. | ||
958 | * The decoding mode is changed among NRZ, NRZI, FM0, or FM1. | ||
959 | * | ||
960 | * This workaround attempts to recover from the lockup condition by placing | ||
961 | * the SCC in synchronous loopback mode with a fast clock before programming | ||
962 | * any of the asynchronous modes. | ||
963 | */ | ||
964 | static void fix_zero_bug_scc(struct mac_serial * info) | ||
965 | { | ||
966 | write_zsreg(info->zs_channel, 9, | ||
967 | (info->zs_channel == info->zs_chan_a? CHRA: CHRB)); | ||
968 | udelay(10); | ||
969 | write_zsreg(info->zs_channel, 9, | ||
970 | ((info->zs_channel == info->zs_chan_a? CHRA: CHRB) | NV)); | ||
971 | |||
972 | write_zsreg(info->zs_channel, 4, (X1CLK | EXTSYNC)); | ||
973 | |||
974 | /* I think this is wrong....but, I just copying code.... | ||
975 | */ | ||
976 | write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE)); | ||
977 | |||
978 | write_zsreg(info->zs_channel, 5, (8 & ~TxENAB)); | ||
979 | write_zsreg(info->zs_channel, 9, NV); /* Didn't we already do this? */ | ||
980 | write_zsreg(info->zs_channel, 11, (RCBR | TCBR)); | ||
981 | write_zsreg(info->zs_channel, 12, 0); | ||
982 | write_zsreg(info->zs_channel, 13, 0); | ||
983 | write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR)); | ||
984 | write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR | BRENABL)); | ||
985 | write_zsreg(info->zs_channel, 3, (8 | RxENABLE)); | ||
986 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); | ||
987 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); /* to kill some time */ | ||
988 | |||
989 | /* The channel should be OK now, but it is probably receiving | ||
990 | * loopback garbage. | ||
991 | * Switch to asynchronous mode, disable the receiver, | ||
992 | * and discard everything in the receive buffer. | ||
993 | */ | ||
994 | write_zsreg(info->zs_channel, 9, NV); | ||
995 | write_zsreg(info->zs_channel, 4, PAR_ENA); | ||
996 | write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE)); | ||
997 | |||
998 | while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) { | ||
999 | (void)read_zsreg(info->zs_channel, 8); | ||
1000 | write_zsreg(info->zs_channel, 0, RES_EXT_INT); | ||
1001 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | static int setup_scc(struct mac_serial * info) | ||
1006 | { | ||
1007 | unsigned long flags; | ||
1008 | |||
1009 | OPNDBG("setting up ttyS%d SCC...\n", info->line); | ||
1010 | |||
1011 | spin_lock_irqsave(&info->lock, flags); | ||
1012 | |||
1013 | /* Nice buggy HW ... */ | ||
1014 | fix_zero_bug_scc(info); | ||
1015 | |||
1016 | /* | ||
1017 | * Reset the chip. | ||
1018 | */ | ||
1019 | write_zsreg(info->zs_channel, 9, | ||
1020 | (info->zs_channel == info->zs_chan_a? CHRA: CHRB)); | ||
1021 | udelay(10); | ||
1022 | write_zsreg(info->zs_channel, 9, 0); | ||
1023 | |||
1024 | /* | ||
1025 | * Clear the receive FIFO. | ||
1026 | */ | ||
1027 | ZS_CLEARFIFO(info->zs_channel); | ||
1028 | info->xmit_fifo_size = 1; | ||
1029 | |||
1030 | /* | ||
1031 | * Reset DMAs | ||
1032 | */ | ||
1033 | if (info->has_dma) | ||
1034 | dma_init(info); | ||
1035 | |||
1036 | /* | ||
1037 | * Clear the interrupt registers. | ||
1038 | */ | ||
1039 | write_zsreg(info->zs_channel, 0, ERR_RES); | ||
1040 | write_zsreg(info->zs_channel, 0, RES_H_IUS); | ||
1041 | |||
1042 | /* | ||
1043 | * Turn on RTS and DTR. | ||
1044 | */ | ||
1045 | if (!info->is_irda) | ||
1046 | zs_rtsdtr(info, 1); | ||
1047 | |||
1048 | /* | ||
1049 | * Finally, enable sequencing and interrupts | ||
1050 | */ | ||
1051 | if (!info->dma_initted) { | ||
1052 | /* interrupt on ext/status changes, all received chars, | ||
1053 | transmit ready */ | ||
1054 | info->curregs[1] = (info->curregs[1] & ~0x18) | ||
1055 | | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); | ||
1056 | } else { | ||
1057 | /* interrupt on ext/status changes, W/Req pin is | ||
1058 | receive DMA request */ | ||
1059 | info->curregs[1] = (info->curregs[1] & ~(0x18 | TxINT_ENAB)) | ||
1060 | | (EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN); | ||
1061 | write_zsreg(info->zs_channel, 1, info->curregs[1]); | ||
1062 | /* enable W/Req pin */ | ||
1063 | info->curregs[1] |= WT_RDY_ENAB; | ||
1064 | write_zsreg(info->zs_channel, 1, info->curregs[1]); | ||
1065 | /* enable interrupts on transmit ready and receive errors */ | ||
1066 | info->curregs[1] |= INT_ERR_Rx | TxINT_ENAB; | ||
1067 | } | ||
1068 | info->pendregs[1] = info->curregs[1]; | ||
1069 | info->curregs[3] |= (RxENABLE | Rx8); | ||
1070 | info->pendregs[3] = info->curregs[3]; | ||
1071 | info->curregs[5] |= (TxENAB | Tx8); | ||
1072 | info->pendregs[5] = info->curregs[5]; | ||
1073 | info->curregs[9] |= (NV | MIE); | ||
1074 | info->pendregs[9] = info->curregs[9]; | ||
1075 | write_zsreg(info->zs_channel, 3, info->curregs[3]); | ||
1076 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1077 | write_zsreg(info->zs_channel, 9, info->curregs[9]); | ||
1078 | |||
1079 | if (info->tty) | ||
1080 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
1081 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1082 | |||
1083 | spin_unlock_irqrestore(&info->lock, flags); | ||
1084 | |||
1085 | /* | ||
1086 | * Set the speed of the serial port | ||
1087 | */ | ||
1088 | change_speed(info, 0); | ||
1089 | |||
1090 | /* Save the current value of RR0 */ | ||
1091 | info->read_reg_zero = read_zsreg(info->zs_channel, 0); | ||
1092 | |||
1093 | if (info->dma_initted) { | ||
1094 | spin_lock_irqsave(&info->rx_dma_lock, flags); | ||
1095 | rxdma_start(info, 0); | ||
1096 | info->poll_dma_timer.expires = RX_DMA_TIMER; | ||
1097 | add_timer(&info->poll_dma_timer); | ||
1098 | spin_unlock_irqrestore(&info->rx_dma_lock, flags); | ||
1099 | } | ||
1100 | |||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | /* | ||
1105 | * This routine will shutdown a serial port; interrupts are disabled, and | ||
1106 | * DTR is dropped if the hangup on close termio flag is on. | ||
1107 | */ | ||
1108 | static void shutdown(struct mac_serial * info) | ||
1109 | { | ||
1110 | OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line, | ||
1111 | info->irq); | ||
1112 | |||
1113 | if (!(info->flags & ZILOG_INITIALIZED)) { | ||
1114 | OPNDBG("(already shutdown)\n"); | ||
1115 | return; | ||
1116 | } | ||
1117 | |||
1118 | if (info->has_dma) { | ||
1119 | del_timer(&info->poll_dma_timer); | ||
1120 | dbdma_reset(info->tx_dma); | ||
1121 | dbdma_reset(&info->rx->dma); | ||
1122 | disable_irq(info->tx_dma_irq); | ||
1123 | disable_irq(info->rx_dma_irq); | ||
1124 | } | ||
1125 | disable_irq(info->irq); | ||
1126 | |||
1127 | info->pendregs[1] = info->curregs[1] = 0; | ||
1128 | write_zsreg(info->zs_channel, 1, 0); /* no interrupts */ | ||
1129 | |||
1130 | info->curregs[3] &= ~RxENABLE; | ||
1131 | info->pendregs[3] = info->curregs[3]; | ||
1132 | write_zsreg(info->zs_channel, 3, info->curregs[3]); | ||
1133 | |||
1134 | info->curregs[5] &= ~TxENAB; | ||
1135 | if (!info->tty || C_HUPCL(info->tty)) | ||
1136 | info->curregs[5] &= ~DTR; | ||
1137 | info->pendregs[5] = info->curregs[5]; | ||
1138 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1139 | |||
1140 | if (info->tty) | ||
1141 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
1142 | |||
1143 | set_scc_power(info, 0); | ||
1144 | |||
1145 | if (info->xmit_buf) { | ||
1146 | free_page((unsigned long) info->xmit_buf); | ||
1147 | info->xmit_buf = 0; | ||
1148 | } | ||
1149 | |||
1150 | if (info->has_dma && info->dma_priv) { | ||
1151 | kfree(info->dma_priv); | ||
1152 | info->dma_priv = NULL; | ||
1153 | info->dma_initted = 0; | ||
1154 | } | ||
1155 | |||
1156 | memset(info->curregs, 0, sizeof(info->curregs)); | ||
1157 | memset(info->pendregs, 0, sizeof(info->pendregs)); | ||
1158 | |||
1159 | info->flags &= ~ZILOG_INITIALIZED; | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
1163 | * Turn power on or off to the SCC and associated stuff | ||
1164 | * (port drivers, modem, IR port, etc.) | ||
1165 | * Returns the number of milliseconds we should wait before | ||
1166 | * trying to use the port. | ||
1167 | */ | ||
1168 | static int set_scc_power(struct mac_serial * info, int state) | ||
1169 | { | ||
1170 | int delay = 0; | ||
1171 | |||
1172 | if (state) { | ||
1173 | PWRDBG("ttyS%d: powering up hardware\n", info->line); | ||
1174 | pmac_call_feature( | ||
1175 | PMAC_FTR_SCC_ENABLE, | ||
1176 | info->dev_node, info->port_type, 1); | ||
1177 | if (info->is_internal_modem) { | ||
1178 | pmac_call_feature( | ||
1179 | PMAC_FTR_MODEM_ENABLE, | ||
1180 | info->dev_node, 0, 1); | ||
1181 | delay = 2500; /* wait for 2.5s before using */ | ||
1182 | } else if (info->is_irda) | ||
1183 | mdelay(50); /* Do better here once the problems | ||
1184 | * with blocking have been ironed out | ||
1185 | */ | ||
1186 | } else { | ||
1187 | /* TODO: Make that depend on a timer, don't power down | ||
1188 | * immediately | ||
1189 | */ | ||
1190 | PWRDBG("ttyS%d: shutting down hardware\n", info->line); | ||
1191 | if (info->is_internal_modem) { | ||
1192 | PWRDBG("ttyS%d: shutting down modem\n", info->line); | ||
1193 | pmac_call_feature( | ||
1194 | PMAC_FTR_MODEM_ENABLE, | ||
1195 | info->dev_node, 0, 0); | ||
1196 | } | ||
1197 | pmac_call_feature( | ||
1198 | PMAC_FTR_SCC_ENABLE, | ||
1199 | info->dev_node, info->port_type, 0); | ||
1200 | } | ||
1201 | return delay; | ||
1202 | } | ||
1203 | |||
1204 | static void irda_rts_pulses(struct mac_serial *info, int w) | ||
1205 | { | ||
1206 | udelay(w); | ||
1207 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB); | ||
1208 | udelay(2); | ||
1209 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1210 | udelay(8); | ||
1211 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB); | ||
1212 | udelay(4); | ||
1213 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1214 | } | ||
1215 | |||
1216 | /* | ||
1217 | * Set the irda codec on the imac to the specified baud rate. | ||
1218 | */ | ||
1219 | static void irda_setup(struct mac_serial *info) | ||
1220 | { | ||
1221 | int code, speed, t; | ||
1222 | |||
1223 | speed = info->tty->termios->c_cflag & CBAUD; | ||
1224 | if (speed < B2400 || speed > B115200) | ||
1225 | return; | ||
1226 | code = 0x4d + B115200 - speed; | ||
1227 | |||
1228 | /* disable serial interrupts and receive DMA */ | ||
1229 | write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f); | ||
1230 | |||
1231 | /* wait for transmitter to drain */ | ||
1232 | t = 10000; | ||
1233 | while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0 | ||
1234 | || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { | ||
1235 | if (--t <= 0) { | ||
1236 | printk(KERN_ERR "transmitter didn't drain\n"); | ||
1237 | return; | ||
1238 | } | ||
1239 | udelay(10); | ||
1240 | } | ||
1241 | udelay(100); | ||
1242 | |||
1243 | /* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */ | ||
1244 | write_zsreg(info->zs_channel, 4, X16CLK | SB1); | ||
1245 | write_zsreg(info->zs_channel, 11, TCBR | RCBR); | ||
1246 | t = BPS_TO_BRG(19200, ZS_CLOCK/16); | ||
1247 | write_zsreg(info->zs_channel, 12, t); | ||
1248 | write_zsreg(info->zs_channel, 13, t >> 8); | ||
1249 | write_zsreg(info->zs_channel, 14, BRENABL); | ||
1250 | write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE); | ||
1251 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1252 | |||
1253 | /* set TxD low for ~104us and pulse RTS */ | ||
1254 | udelay(1000); | ||
1255 | write_zsdata(info->zs_channel, 0xfe); | ||
1256 | irda_rts_pulses(info, 150); | ||
1257 | irda_rts_pulses(info, 180); | ||
1258 | irda_rts_pulses(info, 50); | ||
1259 | udelay(100); | ||
1260 | |||
1261 | /* assert DTR, wait 30ms, talk to the chip */ | ||
1262 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR); | ||
1263 | mdelay(30); | ||
1264 | while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) | ||
1265 | read_zsdata(info->zs_channel); | ||
1266 | |||
1267 | write_zsdata(info->zs_channel, 1); | ||
1268 | t = 1000; | ||
1269 | while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) { | ||
1270 | if (--t <= 0) { | ||
1271 | printk(KERN_ERR "irda_setup timed out on 1st byte\n"); | ||
1272 | goto out; | ||
1273 | } | ||
1274 | udelay(10); | ||
1275 | } | ||
1276 | t = read_zsdata(info->zs_channel); | ||
1277 | if (t != 4) | ||
1278 | printk(KERN_ERR "irda_setup 1st byte = %x\n", t); | ||
1279 | |||
1280 | write_zsdata(info->zs_channel, code); | ||
1281 | t = 1000; | ||
1282 | while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) { | ||
1283 | if (--t <= 0) { | ||
1284 | printk(KERN_ERR "irda_setup timed out on 2nd byte\n"); | ||
1285 | goto out; | ||
1286 | } | ||
1287 | udelay(10); | ||
1288 | } | ||
1289 | t = read_zsdata(info->zs_channel); | ||
1290 | if (t != code) | ||
1291 | printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code); | ||
1292 | |||
1293 | /* Drop DTR again and do some more RTS pulses */ | ||
1294 | out: | ||
1295 | udelay(100); | ||
1296 | write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); | ||
1297 | irda_rts_pulses(info, 80); | ||
1298 | |||
1299 | /* We should be right to go now. We assume that load_zsregs | ||
1300 | will get called soon to load up the correct baud rate etc. */ | ||
1301 | info->curregs[5] = (info->curregs[5] | RTS) & ~DTR; | ||
1302 | info->pendregs[5] = info->curregs[5]; | ||
1303 | } | ||
1304 | |||
1305 | /* | ||
1306 | * This routine is called to set the UART divisor registers to match | ||
1307 | * the specified baud rate for a serial port. | ||
1308 | */ | ||
1309 | static void change_speed(struct mac_serial *info, struct termios *old_termios) | ||
1310 | { | ||
1311 | unsigned cflag; | ||
1312 | int bits; | ||
1313 | int brg, baud; | ||
1314 | unsigned long flags; | ||
1315 | |||
1316 | if (!info->tty || !info->tty->termios) | ||
1317 | return; | ||
1318 | |||
1319 | cflag = info->tty->termios->c_cflag; | ||
1320 | baud = tty_get_baud_rate(info->tty); | ||
1321 | if (baud == 0) { | ||
1322 | if (old_termios) { | ||
1323 | info->tty->termios->c_cflag &= ~CBAUD; | ||
1324 | info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); | ||
1325 | cflag = info->tty->termios->c_cflag; | ||
1326 | baud = tty_get_baud_rate(info->tty); | ||
1327 | } | ||
1328 | else | ||
1329 | baud = info->zs_baud; | ||
1330 | } | ||
1331 | if (baud > 230400) | ||
1332 | baud = 230400; | ||
1333 | else if (baud == 0) | ||
1334 | baud = 38400; | ||
1335 | |||
1336 | spin_lock_irqsave(&info->lock, flags); | ||
1337 | info->zs_baud = baud; | ||
1338 | info->clk_divisor = 16; | ||
1339 | |||
1340 | BAUDBG(KERN_DEBUG "set speed to %d bds, ", baud); | ||
1341 | |||
1342 | switch (baud) { | ||
1343 | case ZS_CLOCK/16: /* 230400 */ | ||
1344 | info->curregs[4] = X16CLK; | ||
1345 | info->curregs[11] = 0; | ||
1346 | break; | ||
1347 | case ZS_CLOCK/32: /* 115200 */ | ||
1348 | info->curregs[4] = X32CLK; | ||
1349 | info->curregs[11] = 0; | ||
1350 | break; | ||
1351 | default: | ||
1352 | info->curregs[4] = X16CLK; | ||
1353 | info->curregs[11] = TCBR | RCBR; | ||
1354 | brg = BPS_TO_BRG(baud, ZS_CLOCK/info->clk_divisor); | ||
1355 | info->curregs[12] = (brg & 255); | ||
1356 | info->curregs[13] = ((brg >> 8) & 255); | ||
1357 | info->curregs[14] = BRENABL; | ||
1358 | } | ||
1359 | |||
1360 | /* byte size and parity */ | ||
1361 | info->curregs[3] &= ~RxNBITS_MASK; | ||
1362 | info->curregs[5] &= ~TxNBITS_MASK; | ||
1363 | switch (cflag & CSIZE) { | ||
1364 | case CS5: | ||
1365 | info->curregs[3] |= Rx5; | ||
1366 | info->curregs[5] |= Tx5; | ||
1367 | BAUDBG("5 bits, "); | ||
1368 | bits = 7; | ||
1369 | break; | ||
1370 | case CS6: | ||
1371 | info->curregs[3] |= Rx6; | ||
1372 | info->curregs[5] |= Tx6; | ||
1373 | BAUDBG("6 bits, "); | ||
1374 | bits = 8; | ||
1375 | break; | ||
1376 | case CS7: | ||
1377 | info->curregs[3] |= Rx7; | ||
1378 | info->curregs[5] |= Tx7; | ||
1379 | BAUDBG("7 bits, "); | ||
1380 | bits = 9; | ||
1381 | break; | ||
1382 | case CS8: | ||
1383 | default: /* defaults to 8 bits */ | ||
1384 | info->curregs[3] |= Rx8; | ||
1385 | info->curregs[5] |= Tx8; | ||
1386 | BAUDBG("8 bits, "); | ||
1387 | bits = 10; | ||
1388 | break; | ||
1389 | } | ||
1390 | info->pendregs[3] = info->curregs[3]; | ||
1391 | info->pendregs[5] = info->curregs[5]; | ||
1392 | |||
1393 | info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); | ||
1394 | if (cflag & CSTOPB) { | ||
1395 | info->curregs[4] |= SB2; | ||
1396 | bits++; | ||
1397 | BAUDBG("2 stop, "); | ||
1398 | } else { | ||
1399 | info->curregs[4] |= SB1; | ||
1400 | BAUDBG("1 stop, "); | ||
1401 | } | ||
1402 | if (cflag & PARENB) { | ||
1403 | bits++; | ||
1404 | info->curregs[4] |= PAR_ENA; | ||
1405 | BAUDBG("parity, "); | ||
1406 | } | ||
1407 | if (!(cflag & PARODD)) { | ||
1408 | info->curregs[4] |= PAR_EVEN; | ||
1409 | } | ||
1410 | info->pendregs[4] = info->curregs[4]; | ||
1411 | |||
1412 | if (!(cflag & CLOCAL)) { | ||
1413 | if (!(info->curregs[15] & DCDIE)) | ||
1414 | info->read_reg_zero = read_zsreg(info->zs_channel, 0); | ||
1415 | info->curregs[15] |= DCDIE; | ||
1416 | } else | ||
1417 | info->curregs[15] &= ~DCDIE; | ||
1418 | if (cflag & CRTSCTS) { | ||
1419 | info->curregs[15] |= CTSIE; | ||
1420 | if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) | ||
1421 | info->tx_stopped = 1; | ||
1422 | } else { | ||
1423 | info->curregs[15] &= ~CTSIE; | ||
1424 | info->tx_stopped = 0; | ||
1425 | } | ||
1426 | info->pendregs[15] = info->curregs[15]; | ||
1427 | |||
1428 | /* Calc timeout value. This is pretty broken with high baud rates with HZ=100. | ||
1429 | This code would love a larger HZ and a >1 fifo size, but this is not | ||
1430 | a priority. The resulting value must be >HZ/2 | ||
1431 | */ | ||
1432 | info->timeout = ((info->xmit_fifo_size*HZ*bits) / baud); | ||
1433 | info->timeout += HZ/50+1; /* Add .02 seconds of slop */ | ||
1434 | |||
1435 | BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ, | ||
1436 | (int)info->baud_base); | ||
1437 | |||
1438 | /* set the irda codec to the right rate */ | ||
1439 | if (info->is_irda) | ||
1440 | irda_setup(info); | ||
1441 | |||
1442 | /* Load up the new values */ | ||
1443 | load_zsregs(info->zs_channel, info->curregs); | ||
1444 | |||
1445 | spin_unlock_irqrestore(&info->lock, flags); | ||
1446 | } | ||
1447 | |||
1448 | static void rs_flush_chars(struct tty_struct *tty) | ||
1449 | { | ||
1450 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1451 | unsigned long flags; | ||
1452 | |||
1453 | if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) | ||
1454 | return; | ||
1455 | |||
1456 | spin_lock_irqsave(&info->lock, flags); | ||
1457 | if (!(info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped || | ||
1458 | !info->xmit_buf)) | ||
1459 | /* Enable transmitter */ | ||
1460 | transmit_chars(info); | ||
1461 | spin_unlock_irqrestore(&info->lock, flags); | ||
1462 | } | ||
1463 | |||
1464 | static int rs_write(struct tty_struct * tty, | ||
1465 | const unsigned char *buf, int count) | ||
1466 | { | ||
1467 | int c, ret = 0; | ||
1468 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1469 | unsigned long flags; | ||
1470 | |||
1471 | if (serial_paranoia_check(info, tty->name, "rs_write")) | ||
1472 | return 0; | ||
1473 | |||
1474 | if (!tty || !info->xmit_buf || !tmp_buf) | ||
1475 | return 0; | ||
1476 | |||
1477 | while (1) { | ||
1478 | spin_lock_irqsave(&info->lock, flags); | ||
1479 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
1480 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
1481 | if (c <= 0) { | ||
1482 | spin_unlock_irqrestore(&info->lock, flags); | ||
1483 | break; | ||
1484 | } | ||
1485 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1486 | info->xmit_head = ((info->xmit_head + c) & | ||
1487 | (SERIAL_XMIT_SIZE-1)); | ||
1488 | info->xmit_cnt += c; | ||
1489 | spin_unlock_irqrestore(&info->lock, flags); | ||
1490 | buf += c; | ||
1491 | count -= c; | ||
1492 | ret += c; | ||
1493 | } | ||
1494 | spin_lock_irqsave(&info->lock, flags); | ||
1495 | if (info->xmit_cnt && !tty->stopped && !info->tx_stopped | ||
1496 | && !info->tx_active) | ||
1497 | transmit_chars(info); | ||
1498 | spin_unlock_irqrestore(&info->lock, flags); | ||
1499 | return ret; | ||
1500 | } | ||
1501 | |||
1502 | static int rs_write_room(struct tty_struct *tty) | ||
1503 | { | ||
1504 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1505 | int ret; | ||
1506 | |||
1507 | if (serial_paranoia_check(info, tty->name, "rs_write_room")) | ||
1508 | return 0; | ||
1509 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | ||
1510 | if (ret < 0) | ||
1511 | ret = 0; | ||
1512 | return ret; | ||
1513 | } | ||
1514 | |||
1515 | static int rs_chars_in_buffer(struct tty_struct *tty) | ||
1516 | { | ||
1517 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1518 | |||
1519 | if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) | ||
1520 | return 0; | ||
1521 | return info->xmit_cnt; | ||
1522 | } | ||
1523 | |||
1524 | static void rs_flush_buffer(struct tty_struct *tty) | ||
1525 | { | ||
1526 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1527 | unsigned long flags; | ||
1528 | |||
1529 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | ||
1530 | return; | ||
1531 | spin_lock_irqsave(&info->lock, flags); | ||
1532 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1533 | spin_unlock_irqrestore(&info->lock, flags); | ||
1534 | tty_wakeup(tty); | ||
1535 | } | ||
1536 | |||
1537 | /* | ||
1538 | * ------------------------------------------------------------ | ||
1539 | * rs_throttle() | ||
1540 | * | ||
1541 | * This routine is called by the upper-layer tty layer to signal that | ||
1542 | * incoming characters should be throttled. | ||
1543 | * ------------------------------------------------------------ | ||
1544 | */ | ||
1545 | static void rs_throttle(struct tty_struct * tty) | ||
1546 | { | ||
1547 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1548 | unsigned long flags; | ||
1549 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1550 | printk(KERN_DEBUG "throttle %ld....\n",tty->ldisc.chars_in_buffer(tty)); | ||
1551 | #endif | ||
1552 | |||
1553 | if (serial_paranoia_check(info, tty->name, "rs_throttle")) | ||
1554 | return; | ||
1555 | |||
1556 | if (I_IXOFF(tty)) { | ||
1557 | spin_lock_irqsave(&info->lock, flags); | ||
1558 | info->x_char = STOP_CHAR(tty); | ||
1559 | if (!info->tx_active) | ||
1560 | transmit_chars(info); | ||
1561 | spin_unlock_irqrestore(&info->lock, flags); | ||
1562 | } | ||
1563 | |||
1564 | if (C_CRTSCTS(tty)) { | ||
1565 | /* | ||
1566 | * Here we want to turn off the RTS line. On Macintoshes, | ||
1567 | * the external serial ports using a DIN-8 or DIN-9 | ||
1568 | * connector only have the DTR line (which is usually | ||
1569 | * wired to both RTS and DTR on an external modem in | ||
1570 | * the cable). RTS doesn't go out to the serial port | ||
1571 | * socket, it acts as an output enable for the transmit | ||
1572 | * data line. So in this case we don't drop RTS. | ||
1573 | * | ||
1574 | * Macs with internal modems generally do have both RTS | ||
1575 | * and DTR wired to the modem, so in that case we do | ||
1576 | * drop RTS. | ||
1577 | */ | ||
1578 | if (info->is_internal_modem) { | ||
1579 | spin_lock_irqsave(&info->lock, flags); | ||
1580 | info->curregs[5] &= ~RTS; | ||
1581 | info->pendregs[5] &= ~RTS; | ||
1582 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1583 | spin_unlock_irqrestore(&info->lock, flags); | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1587 | #ifdef CDTRCTS | ||
1588 | if (tty->termios->c_cflag & CDTRCTS) { | ||
1589 | spin_lock_irqsave(&info->lock, flags); | ||
1590 | info->curregs[5] &= ~DTR; | ||
1591 | info->pendregs[5] &= ~DTR; | ||
1592 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1593 | spin_unlock_irqrestore(&info->lock, flags); | ||
1594 | } | ||
1595 | #endif /* CDTRCTS */ | ||
1596 | } | ||
1597 | |||
1598 | static void rs_unthrottle(struct tty_struct * tty) | ||
1599 | { | ||
1600 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1601 | unsigned long flags; | ||
1602 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1603 | printk(KERN_DEBUG "unthrottle %s: %d....\n", | ||
1604 | tty->ldisc.chars_in_buffer(tty)); | ||
1605 | #endif | ||
1606 | |||
1607 | if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) | ||
1608 | return; | ||
1609 | |||
1610 | if (I_IXOFF(tty)) { | ||
1611 | spin_lock_irqsave(&info->lock, flags); | ||
1612 | if (info->x_char) | ||
1613 | info->x_char = 0; | ||
1614 | else { | ||
1615 | info->x_char = START_CHAR(tty); | ||
1616 | if (!info->tx_active) | ||
1617 | transmit_chars(info); | ||
1618 | } | ||
1619 | spin_unlock_irqrestore(&info->lock, flags); | ||
1620 | } | ||
1621 | |||
1622 | if (C_CRTSCTS(tty) && info->is_internal_modem) { | ||
1623 | /* Assert RTS line */ | ||
1624 | spin_lock_irqsave(&info->lock, flags); | ||
1625 | info->curregs[5] |= RTS; | ||
1626 | info->pendregs[5] |= RTS; | ||
1627 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1628 | spin_unlock_irqrestore(&info->lock, flags); | ||
1629 | } | ||
1630 | |||
1631 | #ifdef CDTRCTS | ||
1632 | if (tty->termios->c_cflag & CDTRCTS) { | ||
1633 | /* Assert DTR line */ | ||
1634 | spin_lock_irqsave(&info->lock, flags); | ||
1635 | info->curregs[5] |= DTR; | ||
1636 | info->pendregs[5] |= DTR; | ||
1637 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1638 | spin_unlock_irqrestore(&info->lock, flags); | ||
1639 | } | ||
1640 | #endif | ||
1641 | } | ||
1642 | |||
1643 | /* | ||
1644 | * ------------------------------------------------------------ | ||
1645 | * rs_ioctl() and friends | ||
1646 | * ------------------------------------------------------------ | ||
1647 | */ | ||
1648 | |||
1649 | static int get_serial_info(struct mac_serial * info, | ||
1650 | struct serial_struct __user * retinfo) | ||
1651 | { | ||
1652 | struct serial_struct tmp; | ||
1653 | |||
1654 | if (!retinfo) | ||
1655 | return -EFAULT; | ||
1656 | memset(&tmp, 0, sizeof(tmp)); | ||
1657 | tmp.type = info->type; | ||
1658 | tmp.line = info->line; | ||
1659 | tmp.port = info->port; | ||
1660 | tmp.irq = info->irq; | ||
1661 | tmp.flags = info->flags; | ||
1662 | tmp.baud_base = info->baud_base; | ||
1663 | tmp.close_delay = info->close_delay; | ||
1664 | tmp.closing_wait = info->closing_wait; | ||
1665 | tmp.custom_divisor = info->custom_divisor; | ||
1666 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) | ||
1667 | return -EFAULT; | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1671 | static int set_serial_info(struct mac_serial * info, | ||
1672 | struct serial_struct __user * new_info) | ||
1673 | { | ||
1674 | struct serial_struct new_serial; | ||
1675 | struct mac_serial old_info; | ||
1676 | int retval = 0; | ||
1677 | |||
1678 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | ||
1679 | return -EFAULT; | ||
1680 | old_info = *info; | ||
1681 | |||
1682 | if (!capable(CAP_SYS_ADMIN)) { | ||
1683 | if ((new_serial.baud_base != info->baud_base) || | ||
1684 | (new_serial.type != info->type) || | ||
1685 | (new_serial.close_delay != info->close_delay) || | ||
1686 | ((new_serial.flags & ~ZILOG_USR_MASK) != | ||
1687 | (info->flags & ~ZILOG_USR_MASK))) | ||
1688 | return -EPERM; | ||
1689 | info->flags = ((info->flags & ~ZILOG_USR_MASK) | | ||
1690 | (new_serial.flags & ZILOG_USR_MASK)); | ||
1691 | info->custom_divisor = new_serial.custom_divisor; | ||
1692 | goto check_and_exit; | ||
1693 | } | ||
1694 | |||
1695 | if (info->count > 1) | ||
1696 | return -EBUSY; | ||
1697 | |||
1698 | /* | ||
1699 | * OK, past this point, all the error checking has been done. | ||
1700 | * At this point, we start making changes..... | ||
1701 | */ | ||
1702 | |||
1703 | info->baud_base = new_serial.baud_base; | ||
1704 | info->flags = ((info->flags & ~ZILOG_FLAGS) | | ||
1705 | (new_serial.flags & ZILOG_FLAGS)); | ||
1706 | info->type = new_serial.type; | ||
1707 | info->close_delay = new_serial.close_delay; | ||
1708 | info->closing_wait = new_serial.closing_wait; | ||
1709 | |||
1710 | check_and_exit: | ||
1711 | if (info->flags & ZILOG_INITIALIZED) | ||
1712 | retval = setup_scc(info); | ||
1713 | return retval; | ||
1714 | } | ||
1715 | |||
1716 | /* | ||
1717 | * get_lsr_info - get line status register info | ||
1718 | * | ||
1719 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
1720 | * is emptied. On bus types like RS485, the transmitter must | ||
1721 | * release the bus after transmitting. This must be done when | ||
1722 | * the transmit shift register is empty, not be done when the | ||
1723 | * transmit holding register is empty. This functionality | ||
1724 | * allows an RS485 driver to be written in user space. | ||
1725 | */ | ||
1726 | static int get_lsr_info(struct mac_serial * info, unsigned int *value) | ||
1727 | { | ||
1728 | unsigned char status; | ||
1729 | unsigned long flags; | ||
1730 | |||
1731 | spin_lock_irqsave(&info->lock, flags); | ||
1732 | status = read_zsreg(info->zs_channel, 0); | ||
1733 | spin_unlock_irqrestore(&info->lock, flags); | ||
1734 | status = (status & Tx_BUF_EMP)? TIOCSER_TEMT: 0; | ||
1735 | return put_user(status,value); | ||
1736 | } | ||
1737 | |||
1738 | static int rs_tiocmget(struct tty_struct *tty, struct file *file) | ||
1739 | { | ||
1740 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1741 | unsigned char control, status; | ||
1742 | unsigned long flags; | ||
1743 | |||
1744 | #ifdef CONFIG_KGDB | ||
1745 | if (info->kgdb_channel) | ||
1746 | return -ENODEV; | ||
1747 | #endif | ||
1748 | if (serial_paranoia_check(info, tty->name, __FUNCTION__)) | ||
1749 | return -ENODEV; | ||
1750 | |||
1751 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1752 | return -EIO; | ||
1753 | |||
1754 | spin_lock_irqsave(&info->lock, flags); | ||
1755 | control = info->curregs[5]; | ||
1756 | status = read_zsreg(info->zs_channel, 0); | ||
1757 | spin_unlock_irqrestore(&info->lock, flags); | ||
1758 | return ((control & RTS) ? TIOCM_RTS: 0) | ||
1759 | | ((control & DTR) ? TIOCM_DTR: 0) | ||
1760 | | ((status & DCD) ? TIOCM_CAR: 0) | ||
1761 | | ((status & CTS) ? 0: TIOCM_CTS); | ||
1762 | } | ||
1763 | |||
1764 | static int rs_tiocmset(struct tty_struct *tty, struct file *file, | ||
1765 | unsigned int set, unsigned int clear) | ||
1766 | { | ||
1767 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1768 | unsigned int arg, bits; | ||
1769 | unsigned long flags; | ||
1770 | |||
1771 | #ifdef CONFIG_KGDB | ||
1772 | if (info->kgdb_channel) | ||
1773 | return -ENODEV; | ||
1774 | #endif | ||
1775 | if (serial_paranoia_check(info, tty->name, __FUNCTION__)) | ||
1776 | return -ENODEV; | ||
1777 | |||
1778 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1779 | return -EIO; | ||
1780 | |||
1781 | spin_lock_irqsave(&info->lock, flags); | ||
1782 | if (set & TIOCM_RTS) | ||
1783 | info->curregs[5] |= RTS; | ||
1784 | if (set & TIOCM_DTR) | ||
1785 | info->curregs[5] |= DTR; | ||
1786 | if (clear & TIOCM_RTS) | ||
1787 | info->curregs[5] &= ~RTS; | ||
1788 | if (clear & TIOCM_DTR) | ||
1789 | info->curregs[5] &= ~DTR; | ||
1790 | |||
1791 | info->pendregs[5] = info->curregs[5]; | ||
1792 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1793 | spin_unlock_irqrestore(&info->lock, flags); | ||
1794 | return 0; | ||
1795 | } | ||
1796 | |||
1797 | /* | ||
1798 | * rs_break - turn transmit break condition on/off | ||
1799 | */ | ||
1800 | static void rs_break(struct tty_struct *tty, int break_state) | ||
1801 | { | ||
1802 | struct mac_serial *info = (struct mac_serial *) tty->driver_data; | ||
1803 | unsigned long flags; | ||
1804 | |||
1805 | if (serial_paranoia_check(info, tty->name, "rs_break")) | ||
1806 | return; | ||
1807 | |||
1808 | spin_lock_irqsave(&info->lock, flags); | ||
1809 | if (break_state == -1) | ||
1810 | info->curregs[5] |= SND_BRK; | ||
1811 | else | ||
1812 | info->curregs[5] &= ~SND_BRK; | ||
1813 | write_zsreg(info->zs_channel, 5, info->curregs[5]); | ||
1814 | spin_unlock_irqrestore(&info->lock, flags); | ||
1815 | } | ||
1816 | |||
1817 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | ||
1818 | unsigned int cmd, unsigned long arg) | ||
1819 | { | ||
1820 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1821 | |||
1822 | #ifdef CONFIG_KGDB | ||
1823 | if (info->kgdb_channel) | ||
1824 | return -ENODEV; | ||
1825 | #endif | ||
1826 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | ||
1827 | return -ENODEV; | ||
1828 | |||
1829 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1830 | (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) { | ||
1831 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1832 | return -EIO; | ||
1833 | } | ||
1834 | |||
1835 | switch (cmd) { | ||
1836 | case TIOCGSERIAL: | ||
1837 | return get_serial_info(info, | ||
1838 | (struct serial_struct __user *) arg); | ||
1839 | case TIOCSSERIAL: | ||
1840 | return set_serial_info(info, | ||
1841 | (struct serial_struct __user *) arg); | ||
1842 | case TIOCSERGETLSR: /* Get line status register */ | ||
1843 | return get_lsr_info(info, (unsigned int *) arg); | ||
1844 | |||
1845 | case TIOCSERGSTRUCT: | ||
1846 | if (copy_to_user((struct mac_serial __user *) arg, | ||
1847 | info, sizeof(struct mac_serial))) | ||
1848 | return -EFAULT; | ||
1849 | return 0; | ||
1850 | |||
1851 | default: | ||
1852 | return -ENOIOCTLCMD; | ||
1853 | } | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) | ||
1858 | { | ||
1859 | struct mac_serial *info = (struct mac_serial *)tty->driver_data; | ||
1860 | int was_stopped; | ||
1861 | |||
1862 | if (tty->termios->c_cflag == old_termios->c_cflag) | ||
1863 | return; | ||
1864 | was_stopped = info->tx_stopped; | ||
1865 | |||
1866 | change_speed(info, old_termios); | ||
1867 | |||
1868 | if (was_stopped && !info->tx_stopped) { | ||
1869 | tty->hw_stopped = 0; | ||
1870 | rs_start(tty); | ||
1871 | } | ||
1872 | } | ||
1873 | |||
1874 | /* | ||
1875 | * ------------------------------------------------------------ | ||
1876 | * rs_close() | ||
1877 | * | ||
1878 | * This routine is called when the serial port gets closed. | ||
1879 | * Wait for the last remaining data to be sent. | ||
1880 | * ------------------------------------------------------------ | ||
1881 | */ | ||
1882 | static void rs_close(struct tty_struct *tty, struct file * filp) | ||
1883 | { | ||
1884 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
1885 | unsigned long flags; | ||
1886 | |||
1887 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | ||
1888 | return; | ||
1889 | |||
1890 | spin_lock_irqsave(&info->lock, flags); | ||
1891 | |||
1892 | if (tty_hung_up_p(filp)) { | ||
1893 | spin_unlock_irqrestore(&info->lock, flags); | ||
1894 | return; | ||
1895 | } | ||
1896 | |||
1897 | OPNDBG("rs_close ttyS%d, count = %d\n", info->line, info->count); | ||
1898 | if ((tty->count == 1) && (info->count != 1)) { | ||
1899 | /* | ||
1900 | * Uh, oh. tty->count is 1, which means that the tty | ||
1901 | * structure will be freed. Info->count should always | ||
1902 | * be one in these conditions. If it's greater than | ||
1903 | * one, we've got real problems, since it means the | ||
1904 | * serial port won't be shutdown. | ||
1905 | */ | ||
1906 | printk(KERN_ERR "rs_close: bad serial port count; tty->count " | ||
1907 | "is 1, info->count is %d\n", info->count); | ||
1908 | info->count = 1; | ||
1909 | } | ||
1910 | if (--info->count < 0) { | ||
1911 | printk(KERN_ERR "rs_close: bad serial port count for " | ||
1912 | "ttyS%d: %d\n", info->line, info->count); | ||
1913 | info->count = 0; | ||
1914 | } | ||
1915 | if (info->count) { | ||
1916 | spin_unlock_irqrestore(&info->lock, flags); | ||
1917 | return; | ||
1918 | } | ||
1919 | info->flags |= ZILOG_CLOSING; | ||
1920 | /* | ||
1921 | * Now we wait for the transmit buffer to clear; and we notify | ||
1922 | * the line discipline to only process XON/XOFF characters. | ||
1923 | */ | ||
1924 | OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait); | ||
1925 | tty->closing = 1; | ||
1926 | if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) { | ||
1927 | spin_unlock_irqrestore(&info->lock, flags); | ||
1928 | tty_wait_until_sent(tty, info->closing_wait); | ||
1929 | spin_lock_irqsave(&info->lock, flags); | ||
1930 | } | ||
1931 | |||
1932 | /* | ||
1933 | * At this point we stop accepting input. To do this, we | ||
1934 | * disable the receiver and receive interrupts. | ||
1935 | */ | ||
1936 | info->curregs[3] &= ~RxENABLE; | ||
1937 | info->pendregs[3] = info->curregs[3]; | ||
1938 | write_zsreg(info->zs_channel, 3, info->curregs[3]); | ||
1939 | info->curregs[1] &= ~(0x18); /* disable any rx ints */ | ||
1940 | info->pendregs[1] = info->curregs[1]; | ||
1941 | write_zsreg(info->zs_channel, 1, info->curregs[1]); | ||
1942 | ZS_CLEARFIFO(info->zs_channel); | ||
1943 | if (info->flags & ZILOG_INITIALIZED) { | ||
1944 | /* | ||
1945 | * Before we drop DTR, make sure the SCC transmitter | ||
1946 | * has completely drained. | ||
1947 | */ | ||
1948 | OPNDBG("waiting end of Rx...\n"); | ||
1949 | spin_unlock_irqrestore(&info->lock, flags); | ||
1950 | rs_wait_until_sent(tty, info->timeout); | ||
1951 | spin_lock_irqsave(&info->lock, flags); | ||
1952 | } | ||
1953 | |||
1954 | shutdown(info); | ||
1955 | /* restore flags now since shutdown() will have disabled this port's | ||
1956 | specific irqs */ | ||
1957 | spin_unlock_irqrestore(&info->lock, flags); | ||
1958 | |||
1959 | if (tty->driver->flush_buffer) | ||
1960 | tty->driver->flush_buffer(tty); | ||
1961 | tty_ldisc_flush(tty); | ||
1962 | tty->closing = 0; | ||
1963 | info->event = 0; | ||
1964 | info->tty = 0; | ||
1965 | |||
1966 | if (info->blocked_open) { | ||
1967 | if (info->close_delay) { | ||
1968 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
1969 | } | ||
1970 | wake_up_interruptible(&info->open_wait); | ||
1971 | } | ||
1972 | info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING); | ||
1973 | wake_up_interruptible(&info->close_wait); | ||
1974 | } | ||
1975 | |||
1976 | /* | ||
1977 | * rs_wait_until_sent() --- wait until the transmitter is empty | ||
1978 | */ | ||
1979 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | ||
1980 | { | ||
1981 | struct mac_serial *info = (struct mac_serial *) tty->driver_data; | ||
1982 | unsigned long orig_jiffies, char_time; | ||
1983 | |||
1984 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | ||
1985 | return; | ||
1986 | |||
1987 | /* printk("rs_wait_until_sent, timeout:%d, tty_stopped:%d, tx_stopped:%d\n", | ||
1988 | timeout, tty->stopped, info->tx_stopped); | ||
1989 | */ | ||
1990 | orig_jiffies = jiffies; | ||
1991 | /* | ||
1992 | * Set the check interval to be 1/5 of the estimated time to | ||
1993 | * send a single character, and make it at least 1. The check | ||
1994 | * interval should also be less than the timeout. | ||
1995 | */ | ||
1996 | if (info->timeout <= HZ/50) { | ||
1997 | printk(KERN_INFO "macserial: invalid info->timeout=%d\n", | ||
1998 | info->timeout); | ||
1999 | info->timeout = HZ/50+1; | ||
2000 | } | ||
2001 | |||
2002 | char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; | ||
2003 | char_time = char_time / 5; | ||
2004 | if (char_time > HZ) { | ||
2005 | printk(KERN_WARNING "macserial: char_time %ld >HZ !!!\n", | ||
2006 | char_time); | ||
2007 | char_time = 1; | ||
2008 | } else if (char_time == 0) | ||
2009 | char_time = 1; | ||
2010 | if (timeout) | ||
2011 | char_time = min_t(unsigned long, char_time, timeout); | ||
2012 | while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { | ||
2013 | msleep_interruptible(jiffies_to_msecs(char_time)); | ||
2014 | if (signal_pending(current)) | ||
2015 | break; | ||
2016 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
2017 | break; | ||
2018 | } | ||
2019 | current->state = TASK_RUNNING; | ||
2020 | } | ||
2021 | |||
2022 | /* | ||
2023 | * rs_hangup() --- called by tty_hangup() when a hangup is signaled. | ||
2024 | */ | ||
2025 | static void rs_hangup(struct tty_struct *tty) | ||
2026 | { | ||
2027 | struct mac_serial * info = (struct mac_serial *)tty->driver_data; | ||
2028 | |||
2029 | if (serial_paranoia_check(info, tty->name, "rs_hangup")) | ||
2030 | return; | ||
2031 | |||
2032 | rs_flush_buffer(tty); | ||
2033 | shutdown(info); | ||
2034 | info->event = 0; | ||
2035 | info->count = 0; | ||
2036 | info->flags &= ~ZILOG_NORMAL_ACTIVE; | ||
2037 | info->tty = 0; | ||
2038 | wake_up_interruptible(&info->open_wait); | ||
2039 | } | ||
2040 | |||
2041 | /* | ||
2042 | * ------------------------------------------------------------ | ||
2043 | * rs_open() and friends | ||
2044 | * ------------------------------------------------------------ | ||
2045 | */ | ||
2046 | static int block_til_ready(struct tty_struct *tty, struct file * filp, | ||
2047 | struct mac_serial *info) | ||
2048 | { | ||
2049 | DECLARE_WAITQUEUE(wait,current); | ||
2050 | int retval; | ||
2051 | int do_clocal = 0; | ||
2052 | |||
2053 | /* | ||
2054 | * If the device is in the middle of being closed, then block | ||
2055 | * until it's done, and then try again. | ||
2056 | */ | ||
2057 | if (info->flags & ZILOG_CLOSING) { | ||
2058 | interruptible_sleep_on(&info->close_wait); | ||
2059 | return -EAGAIN; | ||
2060 | } | ||
2061 | |||
2062 | /* | ||
2063 | * If non-blocking mode is set, or the port is not enabled, | ||
2064 | * then make the check up front and then exit. | ||
2065 | */ | ||
2066 | if ((filp->f_flags & O_NONBLOCK) || | ||
2067 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
2068 | info->flags |= ZILOG_NORMAL_ACTIVE; | ||
2069 | return 0; | ||
2070 | } | ||
2071 | |||
2072 | if (tty->termios->c_cflag & CLOCAL) | ||
2073 | do_clocal = 1; | ||
2074 | |||
2075 | /* | ||
2076 | * Block waiting for the carrier detect and the line to become | ||
2077 | * free (i.e., not in use by the callout). While we are in | ||
2078 | * this loop, info->count is dropped by one, so that | ||
2079 | * rs_close() knows when to free things. We restore it upon | ||
2080 | * exit, either normal or abnormal. | ||
2081 | */ | ||
2082 | retval = 0; | ||
2083 | add_wait_queue(&info->open_wait, &wait); | ||
2084 | OPNDBG("block_til_ready before block: ttyS%d, count = %d\n", | ||
2085 | info->line, info->count); | ||
2086 | spin_lock_irq(&info->lock); | ||
2087 | if (!tty_hung_up_p(filp)) | ||
2088 | info->count--; | ||
2089 | spin_unlock_irq(&info->lock); | ||
2090 | info->blocked_open++; | ||
2091 | while (1) { | ||
2092 | spin_lock_irq(&info->lock); | ||
2093 | if ((tty->termios->c_cflag & CBAUD) && | ||
2094 | !info->is_irda) | ||
2095 | zs_rtsdtr(info, 1); | ||
2096 | spin_unlock_irq(&info->lock); | ||
2097 | set_current_state(TASK_INTERRUPTIBLE); | ||
2098 | if (tty_hung_up_p(filp) || | ||
2099 | !(info->flags & ZILOG_INITIALIZED)) { | ||
2100 | retval = -EAGAIN; | ||
2101 | break; | ||
2102 | } | ||
2103 | if (!(info->flags & ZILOG_CLOSING) && | ||
2104 | (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD))) | ||
2105 | break; | ||
2106 | if (signal_pending(current)) { | ||
2107 | retval = -ERESTARTSYS; | ||
2108 | break; | ||
2109 | } | ||
2110 | OPNDBG("block_til_ready blocking: ttyS%d, count = %d\n", | ||
2111 | info->line, info->count); | ||
2112 | schedule(); | ||
2113 | } | ||
2114 | current->state = TASK_RUNNING; | ||
2115 | remove_wait_queue(&info->open_wait, &wait); | ||
2116 | if (!tty_hung_up_p(filp)) | ||
2117 | info->count++; | ||
2118 | info->blocked_open--; | ||
2119 | OPNDBG("block_til_ready after blocking: ttyS%d, count = %d\n", | ||
2120 | info->line, info->count); | ||
2121 | if (retval) | ||
2122 | return retval; | ||
2123 | info->flags |= ZILOG_NORMAL_ACTIVE; | ||
2124 | return 0; | ||
2125 | } | ||
2126 | |||
2127 | /* | ||
2128 | * This routine is called whenever a serial port is opened. It | ||
2129 | * enables interrupts for a serial port, linking in its ZILOG structure into | ||
2130 | * the IRQ chain. It also performs the serial-specific | ||
2131 | * initialization for the tty structure. | ||
2132 | */ | ||
2133 | static int rs_open(struct tty_struct *tty, struct file * filp) | ||
2134 | { | ||
2135 | struct mac_serial *info; | ||
2136 | int retval, line; | ||
2137 | unsigned long page; | ||
2138 | |||
2139 | line = tty->index; | ||
2140 | if ((line < 0) || (line >= zs_channels_found)) { | ||
2141 | return -ENODEV; | ||
2142 | } | ||
2143 | info = zs_soft + line; | ||
2144 | |||
2145 | #ifdef CONFIG_KGDB | ||
2146 | if (info->kgdb_channel) { | ||
2147 | return -ENODEV; | ||
2148 | } | ||
2149 | #endif | ||
2150 | if (serial_paranoia_check(info, tty->name, "rs_open")) | ||
2151 | return -ENODEV; | ||
2152 | OPNDBG("rs_open %s, count = %d, tty=%p\n", tty->name, | ||
2153 | info->count, tty); | ||
2154 | |||
2155 | info->count++; | ||
2156 | tty->driver_data = info; | ||
2157 | info->tty = tty; | ||
2158 | |||
2159 | if (!tmp_buf) { | ||
2160 | page = get_zeroed_page(GFP_KERNEL); | ||
2161 | if (!page) | ||
2162 | return -ENOMEM; | ||
2163 | if (tmp_buf) | ||
2164 | free_page(page); | ||
2165 | else | ||
2166 | tmp_buf = (unsigned char *) page; | ||
2167 | } | ||
2168 | |||
2169 | /* | ||
2170 | * If the port is the middle of closing, bail out now | ||
2171 | */ | ||
2172 | if (tty_hung_up_p(filp) || | ||
2173 | (info->flags & ZILOG_CLOSING)) { | ||
2174 | if (info->flags & ZILOG_CLOSING) | ||
2175 | interruptible_sleep_on(&info->close_wait); | ||
2176 | return -EAGAIN; | ||
2177 | } | ||
2178 | |||
2179 | /* | ||
2180 | * Start up serial port | ||
2181 | */ | ||
2182 | |||
2183 | retval = startup(info); | ||
2184 | if (retval) | ||
2185 | return retval; | ||
2186 | |||
2187 | retval = block_til_ready(tty, filp, info); | ||
2188 | if (retval) { | ||
2189 | OPNDBG("rs_open returning after block_til_ready with %d\n", | ||
2190 | retval); | ||
2191 | return retval; | ||
2192 | } | ||
2193 | |||
2194 | #ifdef CONFIG_SERIAL_CONSOLE | ||
2195 | if (sercons.cflag && sercons.index == line) { | ||
2196 | tty->termios->c_cflag = sercons.cflag; | ||
2197 | sercons.cflag = 0; | ||
2198 | change_speed(info, 0); | ||
2199 | } | ||
2200 | #endif | ||
2201 | |||
2202 | OPNDBG("rs_open %s successful...\n", tty->name); | ||
2203 | return 0; | ||
2204 | } | ||
2205 | |||
2206 | /* Finally, routines used to initialize the serial driver. */ | ||
2207 | |||
2208 | static void show_serial_version(void) | ||
2209 | { | ||
2210 | printk(KERN_INFO "PowerMac Z8530 serial driver version " MACSERIAL_VERSION "\n"); | ||
2211 | } | ||
2212 | |||
2213 | /* | ||
2214 | * Initialize one channel, both the mac_serial and mac_zschannel | ||
2215 | * structs. We use the dev_node field of the mac_serial struct. | ||
2216 | */ | ||
2217 | static int | ||
2218 | chan_init(struct mac_serial *zss, struct mac_zschannel *zs_chan, | ||
2219 | struct mac_zschannel *zs_chan_a) | ||
2220 | { | ||
2221 | struct device_node *ch = zss->dev_node; | ||
2222 | char *conn; | ||
2223 | int len; | ||
2224 | struct slot_names_prop { | ||
2225 | int count; | ||
2226 | char name[1]; | ||
2227 | } *slots; | ||
2228 | |||
2229 | zss->irq = ch->intrs[0].line; | ||
2230 | zss->has_dma = 0; | ||
2231 | #if !defined(CONFIG_KGDB) && defined(SUPPORT_SERIAL_DMA) | ||
2232 | if (ch->n_addrs >= 3 && ch->n_intrs == 3) | ||
2233 | zss->has_dma = 1; | ||
2234 | #endif | ||
2235 | zss->dma_initted = 0; | ||
2236 | |||
2237 | zs_chan->control = (volatile unsigned char *) | ||
2238 | ioremap(ch->addrs[0].address, 0x1000); | ||
2239 | zs_chan->data = zs_chan->control + 0x10; | ||
2240 | spin_lock_init(&zs_chan->lock); | ||
2241 | zs_chan->parent = zss; | ||
2242 | zss->zs_channel = zs_chan; | ||
2243 | zss->zs_chan_a = zs_chan_a; | ||
2244 | |||
2245 | /* setup misc varariables */ | ||
2246 | zss->kgdb_channel = 0; | ||
2247 | |||
2248 | /* For now, we assume you either have a slot-names property | ||
2249 | * with "Modem" in it, or your channel is compatible with | ||
2250 | * "cobalt". Might need additional fixups | ||
2251 | */ | ||
2252 | zss->is_internal_modem = device_is_compatible(ch, "cobalt"); | ||
2253 | conn = get_property(ch, "AAPL,connector", &len); | ||
2254 | zss->is_irda = conn && (strcmp(conn, "infrared") == 0); | ||
2255 | zss->port_type = PMAC_SCC_ASYNC; | ||
2256 | /* 1999 Powerbook G3 has slot-names property instead */ | ||
2257 | slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len); | ||
2258 | if (slots && slots->count > 0) { | ||
2259 | if (strcmp(slots->name, "IrDA") == 0) | ||
2260 | zss->is_irda = 1; | ||
2261 | else if (strcmp(slots->name, "Modem") == 0) | ||
2262 | zss->is_internal_modem = 1; | ||
2263 | } | ||
2264 | if (zss->is_irda) | ||
2265 | zss->port_type = PMAC_SCC_IRDA; | ||
2266 | if (zss->is_internal_modem) { | ||
2267 | struct device_node* i2c_modem = find_devices("i2c-modem"); | ||
2268 | if (i2c_modem) { | ||
2269 | char* mid = get_property(i2c_modem, "modem-id", NULL); | ||
2270 | if (mid) switch(*mid) { | ||
2271 | case 0x04 : | ||
2272 | case 0x05 : | ||
2273 | case 0x07 : | ||
2274 | case 0x08 : | ||
2275 | case 0x0b : | ||
2276 | case 0x0c : | ||
2277 | zss->port_type = PMAC_SCC_I2S1; | ||
2278 | } | ||
2279 | printk(KERN_INFO "macserial: i2c-modem detected, id: %d\n", | ||
2280 | mid ? (*mid) : 0); | ||
2281 | } else { | ||
2282 | printk(KERN_INFO "macserial: serial modem detected\n"); | ||
2283 | } | ||
2284 | } | ||
2285 | |||
2286 | while (zss->has_dma) { | ||
2287 | zss->dma_priv = NULL; | ||
2288 | /* it seems that the last two addresses are the | ||
2289 | DMA controllers */ | ||
2290 | zss->tx_dma = (volatile struct dbdma_regs *) | ||
2291 | ioremap(ch->addrs[ch->n_addrs - 2].address, 0x100); | ||
2292 | zss->rx = (volatile struct mac_dma *) | ||
2293 | ioremap(ch->addrs[ch->n_addrs - 1].address, 0x100); | ||
2294 | zss->tx_dma_irq = ch->intrs[1].line; | ||
2295 | zss->rx_dma_irq = ch->intrs[2].line; | ||
2296 | spin_lock_init(&zss->rx_dma_lock); | ||
2297 | break; | ||
2298 | } | ||
2299 | |||
2300 | init_timer(&zss->powerup_timer); | ||
2301 | zss->powerup_timer.function = powerup_done; | ||
2302 | zss->powerup_timer.data = (unsigned long) zss; | ||
2303 | return 0; | ||
2304 | } | ||
2305 | |||
2306 | /* | ||
2307 | * /proc fs routines. TODO: Add status lines & error stats | ||
2308 | */ | ||
2309 | static inline int | ||
2310 | line_info(char *buf, struct mac_serial *info) | ||
2311 | { | ||
2312 | int ret=0; | ||
2313 | unsigned char* connector; | ||
2314 | int lenp; | ||
2315 | |||
2316 | ret += sprintf(buf, "%d: port:0x%X irq:%d", info->line, info->port, info->irq); | ||
2317 | |||
2318 | connector = get_property(info->dev_node, "AAPL,connector", &lenp); | ||
2319 | if (connector) | ||
2320 | ret+=sprintf(buf+ret," con:%s ", connector); | ||
2321 | if (info->is_internal_modem) { | ||
2322 | if (!connector) | ||
2323 | ret+=sprintf(buf+ret," con:"); | ||
2324 | ret+=sprintf(buf+ret,"%s", " (internal modem)"); | ||
2325 | } | ||
2326 | if (info->is_irda) { | ||
2327 | if (!connector) | ||
2328 | ret+=sprintf(buf+ret," con:"); | ||
2329 | ret+=sprintf(buf+ret,"%s", " (IrDA)"); | ||
2330 | } | ||
2331 | ret+=sprintf(buf+ret,"\n"); | ||
2332 | |||
2333 | return ret; | ||
2334 | } | ||
2335 | |||
2336 | int macserial_read_proc(char *page, char **start, off_t off, int count, | ||
2337 | int *eof, void *data) | ||
2338 | { | ||
2339 | int l, len = 0; | ||
2340 | off_t begin = 0; | ||
2341 | struct mac_serial *info; | ||
2342 | |||
2343 | len += sprintf(page, "serinfo:1.0 driver:" MACSERIAL_VERSION "\n"); | ||
2344 | for (info = zs_chain; info && len < 4000; info = info->zs_next) { | ||
2345 | l = line_info(page + len, info); | ||
2346 | len += l; | ||
2347 | if (len+begin > off+count) | ||
2348 | goto done; | ||
2349 | if (len+begin < off) { | ||
2350 | begin += len; | ||
2351 | len = 0; | ||
2352 | } | ||
2353 | } | ||
2354 | *eof = 1; | ||
2355 | done: | ||
2356 | if (off >= len+begin) | ||
2357 | return 0; | ||
2358 | *start = page + (off-begin); | ||
2359 | return ((count < begin+len-off) ? count : begin+len-off); | ||
2360 | } | ||
2361 | |||
2362 | /* Ask the PROM how many Z8530s we have and initialize their zs_channels */ | ||
2363 | static void | ||
2364 | probe_sccs(void) | ||
2365 | { | ||
2366 | struct device_node *dev, *ch; | ||
2367 | struct mac_serial **pp; | ||
2368 | int n, chip, nchan; | ||
2369 | struct mac_zschannel *zs_chan; | ||
2370 | int chan_a_index; | ||
2371 | |||
2372 | n = 0; | ||
2373 | pp = &zs_chain; | ||
2374 | zs_chan = zs_channels; | ||
2375 | for (dev = find_devices("escc"); dev != 0; dev = dev->next) { | ||
2376 | nchan = 0; | ||
2377 | chip = n; | ||
2378 | if (n >= NUM_CHANNELS) { | ||
2379 | printk(KERN_WARNING "Sorry, can't use %s: no more " | ||
2380 | "channels\n", dev->full_name); | ||
2381 | continue; | ||
2382 | } | ||
2383 | chan_a_index = 0; | ||
2384 | for (ch = dev->child; ch != 0; ch = ch->sibling) { | ||
2385 | if (nchan >= 2) { | ||
2386 | printk(KERN_WARNING "SCC: Only 2 channels per " | ||
2387 | "chip are supported\n"); | ||
2388 | break; | ||
2389 | } | ||
2390 | if (ch->n_addrs < 1 || (ch ->n_intrs < 1)) { | ||
2391 | printk("Can't use %s: %d addrs %d intrs\n", | ||
2392 | ch->full_name, ch->n_addrs, ch->n_intrs); | ||
2393 | continue; | ||
2394 | } | ||
2395 | |||
2396 | /* The channel with the higher address | ||
2397 | will be the A side. */ | ||
2398 | if (nchan > 0 && | ||
2399 | ch->addrs[0].address | ||
2400 | > zs_soft[n-1].dev_node->addrs[0].address) | ||
2401 | chan_a_index = 1; | ||
2402 | |||
2403 | /* minimal initialization for now */ | ||
2404 | zs_soft[n].dev_node = ch; | ||
2405 | *pp = &zs_soft[n]; | ||
2406 | pp = &zs_soft[n].zs_next; | ||
2407 | ++nchan; | ||
2408 | ++n; | ||
2409 | } | ||
2410 | if (nchan == 0) | ||
2411 | continue; | ||
2412 | |||
2413 | /* set up A side */ | ||
2414 | if (chan_init(&zs_soft[chip + chan_a_index], zs_chan, zs_chan)) | ||
2415 | continue; | ||
2416 | ++zs_chan; | ||
2417 | |||
2418 | /* set up B side, if it exists */ | ||
2419 | if (nchan > 1) | ||
2420 | if (chan_init(&zs_soft[chip + 1 - chan_a_index], | ||
2421 | zs_chan, zs_chan - 1)) | ||
2422 | continue; | ||
2423 | ++zs_chan; | ||
2424 | } | ||
2425 | *pp = 0; | ||
2426 | |||
2427 | zs_channels_found = n; | ||
2428 | #ifdef CONFIG_PMAC_PBOOK | ||
2429 | if (n) | ||
2430 | pmu_register_sleep_notifier(&serial_sleep_notifier); | ||
2431 | #endif /* CONFIG_PMAC_PBOOK */ | ||
2432 | } | ||
2433 | |||
2434 | static struct tty_operations serial_ops = { | ||
2435 | .open = rs_open, | ||
2436 | .close = rs_close, | ||
2437 | .write = rs_write, | ||
2438 | .flush_chars = rs_flush_chars, | ||
2439 | .write_room = rs_write_room, | ||
2440 | .chars_in_buffer = rs_chars_in_buffer, | ||
2441 | .flush_buffer = rs_flush_buffer, | ||
2442 | .ioctl = rs_ioctl, | ||
2443 | .throttle = rs_throttle, | ||
2444 | .unthrottle = rs_unthrottle, | ||
2445 | .set_termios = rs_set_termios, | ||
2446 | .stop = rs_stop, | ||
2447 | .start = rs_start, | ||
2448 | .hangup = rs_hangup, | ||
2449 | .break_ctl = rs_break, | ||
2450 | .wait_until_sent = rs_wait_until_sent, | ||
2451 | .read_proc = macserial_read_proc, | ||
2452 | .tiocmget = rs_tiocmget, | ||
2453 | .tiocmset = rs_tiocmset, | ||
2454 | }; | ||
2455 | |||
2456 | static int macserial_init(void) | ||
2457 | { | ||
2458 | int channel, i; | ||
2459 | struct mac_serial *info; | ||
2460 | |||
2461 | /* Find out how many Z8530 SCCs we have */ | ||
2462 | if (zs_chain == 0) | ||
2463 | probe_sccs(); | ||
2464 | |||
2465 | serial_driver = alloc_tty_driver(zs_channels_found); | ||
2466 | if (!serial_driver) | ||
2467 | return -ENOMEM; | ||
2468 | |||
2469 | /* XXX assume it's a powerbook if we have a via-pmu | ||
2470 | * | ||
2471 | * This is OK for core99 machines as well. | ||
2472 | */ | ||
2473 | is_powerbook = find_devices("via-pmu") != 0; | ||
2474 | |||
2475 | /* Register the interrupt handler for each one | ||
2476 | * We also request the OF resources here as probe_sccs() | ||
2477 | * might be called too early for that | ||
2478 | */ | ||
2479 | for (i = 0; i < zs_channels_found; ++i) { | ||
2480 | struct device_node* ch = zs_soft[i].dev_node; | ||
2481 | if (!request_OF_resource(ch, 0, NULL)) { | ||
2482 | printk(KERN_ERR "macserial: can't request IO resource !\n"); | ||
2483 | put_tty_driver(serial_driver); | ||
2484 | return -ENODEV; | ||
2485 | } | ||
2486 | if (zs_soft[i].has_dma) { | ||
2487 | if (!request_OF_resource(ch, ch->n_addrs - 2, " (tx dma)")) { | ||
2488 | printk(KERN_ERR "macserial: can't request TX DMA resource !\n"); | ||
2489 | zs_soft[i].has_dma = 0; | ||
2490 | goto no_dma; | ||
2491 | } | ||
2492 | if (!request_OF_resource(ch, ch->n_addrs - 1, " (rx dma)")) { | ||
2493 | release_OF_resource(ch, ch->n_addrs - 2); | ||
2494 | printk(KERN_ERR "macserial: can't request RX DMA resource !\n"); | ||
2495 | zs_soft[i].has_dma = 0; | ||
2496 | goto no_dma; | ||
2497 | } | ||
2498 | if (request_irq(zs_soft[i].tx_dma_irq, rs_txdma_irq, 0, | ||
2499 | "SCC-txdma", &zs_soft[i])) | ||
2500 | printk(KERN_ERR "macserial: can't get irq %d\n", | ||
2501 | zs_soft[i].tx_dma_irq); | ||
2502 | disable_irq(zs_soft[i].tx_dma_irq); | ||
2503 | if (request_irq(zs_soft[i].rx_dma_irq, rs_rxdma_irq, 0, | ||
2504 | "SCC-rxdma", &zs_soft[i])) | ||
2505 | printk(KERN_ERR "macserial: can't get irq %d\n", | ||
2506 | zs_soft[i].rx_dma_irq); | ||
2507 | disable_irq(zs_soft[i].rx_dma_irq); | ||
2508 | } | ||
2509 | no_dma: | ||
2510 | if (request_irq(zs_soft[i].irq, rs_interrupt, 0, | ||
2511 | "SCC", &zs_soft[i])) | ||
2512 | printk(KERN_ERR "macserial: can't get irq %d\n", | ||
2513 | zs_soft[i].irq); | ||
2514 | disable_irq(zs_soft[i].irq); | ||
2515 | } | ||
2516 | |||
2517 | show_serial_version(); | ||
2518 | |||
2519 | /* Initialize the tty_driver structure */ | ||
2520 | /* Not all of this is exactly right for us. */ | ||
2521 | |||
2522 | serial_driver->owner = THIS_MODULE; | ||
2523 | serial_driver->driver_name = "macserial"; | ||
2524 | serial_driver->devfs_name = "tts/"; | ||
2525 | serial_driver->name = "ttyS"; | ||
2526 | serial_driver->major = TTY_MAJOR; | ||
2527 | serial_driver->minor_start = 64; | ||
2528 | serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2529 | serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2530 | serial_driver->init_termios = tty_std_termios; | ||
2531 | serial_driver->init_termios.c_cflag = | ||
2532 | B38400 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2533 | serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
2534 | tty_set_operations(serial_driver, &serial_ops); | ||
2535 | |||
2536 | if (tty_register_driver(serial_driver)) | ||
2537 | printk(KERN_ERR "Error: couldn't register serial driver\n"); | ||
2538 | |||
2539 | for (channel = 0; channel < zs_channels_found; ++channel) { | ||
2540 | #ifdef CONFIG_KGDB | ||
2541 | if (zs_soft[channel].kgdb_channel) { | ||
2542 | kgdb_interruptible(1); | ||
2543 | continue; | ||
2544 | } | ||
2545 | #endif | ||
2546 | zs_soft[channel].clk_divisor = 16; | ||
2547 | /* -- we are not sure the SCC is powered ON at this point | ||
2548 | zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); | ||
2549 | */ | ||
2550 | zs_soft[channel].zs_baud = 38400; | ||
2551 | |||
2552 | /* If console serial line, then enable interrupts. */ | ||
2553 | if (zs_soft[channel].is_cons) { | ||
2554 | printk(KERN_INFO "macserial: console line, enabling " | ||
2555 | "interrupt %d\n", zs_soft[channel].irq); | ||
2556 | panic("macserial: console not supported yet !"); | ||
2557 | write_zsreg(zs_soft[channel].zs_channel, R1, | ||
2558 | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); | ||
2559 | write_zsreg(zs_soft[channel].zs_channel, R9, | ||
2560 | (NV | MIE)); | ||
2561 | } | ||
2562 | } | ||
2563 | |||
2564 | for (info = zs_chain, i = 0; info; info = info->zs_next, i++) | ||
2565 | { | ||
2566 | unsigned char* connector; | ||
2567 | int lenp; | ||
2568 | |||
2569 | #ifdef CONFIG_KGDB | ||
2570 | if (info->kgdb_channel) { | ||
2571 | continue; | ||
2572 | } | ||
2573 | #endif | ||
2574 | info->magic = SERIAL_MAGIC; | ||
2575 | info->port = (int) info->zs_channel->control; | ||
2576 | info->line = i; | ||
2577 | info->tty = 0; | ||
2578 | info->custom_divisor = 16; | ||
2579 | info->timeout = 0; | ||
2580 | info->close_delay = 50; | ||
2581 | info->closing_wait = 3000; | ||
2582 | info->x_char = 0; | ||
2583 | info->event = 0; | ||
2584 | info->count = 0; | ||
2585 | info->blocked_open = 0; | ||
2586 | INIT_WORK(&info->tqueue, do_softint, info); | ||
2587 | spin_lock_init(&info->lock); | ||
2588 | init_waitqueue_head(&info->open_wait); | ||
2589 | init_waitqueue_head(&info->close_wait); | ||
2590 | info->timeout = HZ; | ||
2591 | printk(KERN_INFO "tty%02d at 0x%08x (irq = %d)", info->line, | ||
2592 | info->port, info->irq); | ||
2593 | printk(" is a Z8530 ESCC"); | ||
2594 | connector = get_property(info->dev_node, "AAPL,connector", &lenp); | ||
2595 | if (connector) | ||
2596 | printk(", port = %s", connector); | ||
2597 | if (info->is_internal_modem) | ||
2598 | printk(" (internal modem)"); | ||
2599 | if (info->is_irda) | ||
2600 | printk(" (IrDA)"); | ||
2601 | printk("\n"); | ||
2602 | } | ||
2603 | tmp_buf = 0; | ||
2604 | |||
2605 | return 0; | ||
2606 | } | ||
2607 | |||
2608 | void macserial_cleanup(void) | ||
2609 | { | ||
2610 | int i; | ||
2611 | unsigned long flags; | ||
2612 | struct mac_serial *info; | ||
2613 | |||
2614 | for (info = zs_chain, i = 0; info; info = info->zs_next, i++) | ||
2615 | set_scc_power(info, 0); | ||
2616 | spin_lock_irqsave(&info->lock, flags); | ||
2617 | for (i = 0; i < zs_channels_found; ++i) { | ||
2618 | free_irq(zs_soft[i].irq, &zs_soft[i]); | ||
2619 | if (zs_soft[i].has_dma) { | ||
2620 | free_irq(zs_soft[i].tx_dma_irq, &zs_soft[i]); | ||
2621 | free_irq(zs_soft[i].rx_dma_irq, &zs_soft[i]); | ||
2622 | } | ||
2623 | release_OF_resource(zs_soft[i].dev_node, 0); | ||
2624 | if (zs_soft[i].has_dma) { | ||
2625 | struct device_node* ch = zs_soft[i].dev_node; | ||
2626 | release_OF_resource(ch, ch->n_addrs - 2); | ||
2627 | release_OF_resource(ch, ch->n_addrs - 1); | ||
2628 | } | ||
2629 | } | ||
2630 | spin_unlock_irqrestore(&info->lock, flags); | ||
2631 | tty_unregister_driver(serial_driver); | ||
2632 | put_tty_driver(serial_driver); | ||
2633 | |||
2634 | if (tmp_buf) { | ||
2635 | free_page((unsigned long) tmp_buf); | ||
2636 | tmp_buf = 0; | ||
2637 | } | ||
2638 | |||
2639 | #ifdef CONFIG_PMAC_PBOOK | ||
2640 | if (zs_channels_found) | ||
2641 | pmu_unregister_sleep_notifier(&serial_sleep_notifier); | ||
2642 | #endif /* CONFIG_PMAC_PBOOK */ | ||
2643 | } | ||
2644 | |||
2645 | module_init(macserial_init); | ||
2646 | module_exit(macserial_cleanup); | ||
2647 | MODULE_LICENSE("GPL"); | ||
2648 | |||
2649 | #if 0 | ||
2650 | /* | ||
2651 | * register_serial and unregister_serial allows for serial ports to be | ||
2652 | * configured at run-time, to support PCMCIA modems. | ||
2653 | */ | ||
2654 | /* PowerMac: Unused at this time, just here to make things link. */ | ||
2655 | int register_serial(struct serial_struct *req) | ||
2656 | { | ||
2657 | return -1; | ||
2658 | } | ||
2659 | |||
2660 | void unregister_serial(int line) | ||
2661 | { | ||
2662 | return; | ||
2663 | } | ||
2664 | #endif | ||
2665 | |||
2666 | /* | ||
2667 | * ------------------------------------------------------------ | ||
2668 | * Serial console driver | ||
2669 | * ------------------------------------------------------------ | ||
2670 | */ | ||
2671 | #ifdef CONFIG_SERIAL_CONSOLE | ||
2672 | |||
2673 | /* | ||
2674 | * Print a string to the serial port trying not to disturb | ||
2675 | * any possible real use of the port... | ||
2676 | */ | ||
2677 | static void serial_console_write(struct console *co, const char *s, | ||
2678 | unsigned count) | ||
2679 | { | ||
2680 | struct mac_serial *info = zs_soft + co->index; | ||
2681 | int i; | ||
2682 | |||
2683 | /* Turn of interrupts and enable the transmitter. */ | ||
2684 | write_zsreg(info->zs_channel, R1, info->curregs[1] & ~TxINT_ENAB); | ||
2685 | write_zsreg(info->zs_channel, R5, info->curregs[5] | TxENAB | RTS | DTR); | ||
2686 | |||
2687 | for (i=0; i<count; i++) { | ||
2688 | /* Wait for the transmit buffer to empty. */ | ||
2689 | while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) { | ||
2690 | eieio(); | ||
2691 | } | ||
2692 | |||
2693 | write_zsdata(info->zs_channel, s[i]); | ||
2694 | if (s[i] == 10) { | ||
2695 | while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) | ||
2696 | == 0) | ||
2697 | eieio(); | ||
2698 | |||
2699 | write_zsdata(info->zs_channel, 13); | ||
2700 | } | ||
2701 | } | ||
2702 | |||
2703 | /* Restore the values in the registers. */ | ||
2704 | write_zsreg(info->zs_channel, R1, info->curregs[1]); | ||
2705 | /* Don't disable the transmitter. */ | ||
2706 | } | ||
2707 | |||
2708 | static struct tty_driver *serial_driver; | ||
2709 | |||
2710 | static struct tty_driver *serial_console_device(struct console *c, int *index) | ||
2711 | { | ||
2712 | *index = c->index; | ||
2713 | return serial_driver; | ||
2714 | } | ||
2715 | |||
2716 | /* | ||
2717 | * Setup initial baud/bits/parity. We do two things here: | ||
2718 | * - construct a cflag setting for the first rs_open() | ||
2719 | * - initialize the serial port | ||
2720 | * Return non-zero if we didn't find a serial port. | ||
2721 | */ | ||
2722 | static int __init serial_console_setup(struct console *co, char *options) | ||
2723 | { | ||
2724 | struct mac_serial *info; | ||
2725 | int baud = 38400; | ||
2726 | int bits = 8; | ||
2727 | int parity = 'n'; | ||
2728 | int cflag = CREAD | HUPCL | CLOCAL; | ||
2729 | int brg; | ||
2730 | char *s; | ||
2731 | long flags; | ||
2732 | |||
2733 | /* Find out how many Z8530 SCCs we have */ | ||
2734 | if (zs_chain == 0) | ||
2735 | probe_sccs(); | ||
2736 | |||
2737 | if (zs_chain == 0) | ||
2738 | return -1; | ||
2739 | |||
2740 | /* Do we have the device asked for? */ | ||
2741 | if (co->index >= zs_channels_found) | ||
2742 | return -1; | ||
2743 | info = zs_soft + co->index; | ||
2744 | |||
2745 | set_scc_power(info, 1); | ||
2746 | |||
2747 | /* Reset the channel */ | ||
2748 | write_zsreg(info->zs_channel, R9, CHRA); | ||
2749 | |||
2750 | if (options) { | ||
2751 | baud = simple_strtoul(options, NULL, 10); | ||
2752 | s = options; | ||
2753 | while(*s >= '0' && *s <= '9') | ||
2754 | s++; | ||
2755 | if (*s) | ||
2756 | parity = *s++; | ||
2757 | if (*s) | ||
2758 | bits = *s - '0'; | ||
2759 | } | ||
2760 | |||
2761 | /* | ||
2762 | * Now construct a cflag setting. | ||
2763 | */ | ||
2764 | switch(baud) { | ||
2765 | case 1200: | ||
2766 | cflag |= B1200; | ||
2767 | break; | ||
2768 | case 2400: | ||
2769 | cflag |= B2400; | ||
2770 | break; | ||
2771 | case 4800: | ||
2772 | cflag |= B4800; | ||
2773 | break; | ||
2774 | case 9600: | ||
2775 | cflag |= B9600; | ||
2776 | break; | ||
2777 | case 19200: | ||
2778 | cflag |= B19200; | ||
2779 | break; | ||
2780 | case 57600: | ||
2781 | cflag |= B57600; | ||
2782 | break; | ||
2783 | case 115200: | ||
2784 | cflag |= B115200; | ||
2785 | break; | ||
2786 | case 38400: | ||
2787 | default: | ||
2788 | cflag |= B38400; | ||
2789 | break; | ||
2790 | } | ||
2791 | switch(bits) { | ||
2792 | case 7: | ||
2793 | cflag |= CS7; | ||
2794 | break; | ||
2795 | default: | ||
2796 | case 8: | ||
2797 | cflag |= CS8; | ||
2798 | break; | ||
2799 | } | ||
2800 | switch(parity) { | ||
2801 | case 'o': case 'O': | ||
2802 | cflag |= PARENB | PARODD; | ||
2803 | break; | ||
2804 | case 'e': case 'E': | ||
2805 | cflag |= PARENB; | ||
2806 | break; | ||
2807 | } | ||
2808 | co->cflag = cflag; | ||
2809 | |||
2810 | spin_lock_irqsave(&info->lock, flags); | ||
2811 | memset(info->curregs, 0, sizeof(info->curregs)); | ||
2812 | |||
2813 | info->zs_baud = baud; | ||
2814 | info->clk_divisor = 16; | ||
2815 | switch (info->zs_baud) { | ||
2816 | case ZS_CLOCK/16: /* 230400 */ | ||
2817 | info->curregs[4] = X16CLK; | ||
2818 | info->curregs[11] = 0; | ||
2819 | break; | ||
2820 | case ZS_CLOCK/32: /* 115200 */ | ||
2821 | info->curregs[4] = X32CLK; | ||
2822 | info->curregs[11] = 0; | ||
2823 | break; | ||
2824 | default: | ||
2825 | info->curregs[4] = X16CLK; | ||
2826 | info->curregs[11] = TCBR | RCBR; | ||
2827 | brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); | ||
2828 | info->curregs[12] = (brg & 255); | ||
2829 | info->curregs[13] = ((brg >> 8) & 255); | ||
2830 | info->curregs[14] = BRENABL; | ||
2831 | } | ||
2832 | |||
2833 | /* byte size and parity */ | ||
2834 | info->curregs[3] &= ~RxNBITS_MASK; | ||
2835 | info->curregs[5] &= ~TxNBITS_MASK; | ||
2836 | switch (cflag & CSIZE) { | ||
2837 | case CS5: | ||
2838 | info->curregs[3] |= Rx5; | ||
2839 | info->curregs[5] |= Tx5; | ||
2840 | break; | ||
2841 | case CS6: | ||
2842 | info->curregs[3] |= Rx6; | ||
2843 | info->curregs[5] |= Tx6; | ||
2844 | break; | ||
2845 | case CS7: | ||
2846 | info->curregs[3] |= Rx7; | ||
2847 | info->curregs[5] |= Tx7; | ||
2848 | break; | ||
2849 | case CS8: | ||
2850 | default: /* defaults to 8 bits */ | ||
2851 | info->curregs[3] |= Rx8; | ||
2852 | info->curregs[5] |= Tx8; | ||
2853 | break; | ||
2854 | } | ||
2855 | info->curregs[5] |= TxENAB | RTS | DTR; | ||
2856 | info->pendregs[3] = info->curregs[3]; | ||
2857 | info->pendregs[5] = info->curregs[5]; | ||
2858 | |||
2859 | info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); | ||
2860 | if (cflag & CSTOPB) { | ||
2861 | info->curregs[4] |= SB2; | ||
2862 | } else { | ||
2863 | info->curregs[4] |= SB1; | ||
2864 | } | ||
2865 | if (cflag & PARENB) { | ||
2866 | info->curregs[4] |= PAR_ENA; | ||
2867 | if (!(cflag & PARODD)) { | ||
2868 | info->curregs[4] |= PAR_EVEN; | ||
2869 | } | ||
2870 | } | ||
2871 | info->pendregs[4] = info->curregs[4]; | ||
2872 | |||
2873 | if (!(cflag & CLOCAL)) { | ||
2874 | if (!(info->curregs[15] & DCDIE)) | ||
2875 | info->read_reg_zero = read_zsreg(info->zs_channel, 0); | ||
2876 | info->curregs[15] |= DCDIE; | ||
2877 | } else | ||
2878 | info->curregs[15] &= ~DCDIE; | ||
2879 | if (cflag & CRTSCTS) { | ||
2880 | info->curregs[15] |= CTSIE; | ||
2881 | if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) | ||
2882 | info->tx_stopped = 1; | ||
2883 | } else { | ||
2884 | info->curregs[15] &= ~CTSIE; | ||
2885 | info->tx_stopped = 0; | ||
2886 | } | ||
2887 | info->pendregs[15] = info->curregs[15]; | ||
2888 | |||
2889 | /* Load up the new values */ | ||
2890 | load_zsregs(info->zs_channel, info->curregs); | ||
2891 | |||
2892 | spin_unlock_irqrestore(&info->lock, flags); | ||
2893 | |||
2894 | return 0; | ||
2895 | } | ||
2896 | |||
2897 | static struct console sercons = { | ||
2898 | .name = "ttyS", | ||
2899 | .write = serial_console_write, | ||
2900 | .device = serial_console_device, | ||
2901 | .setup = serial_console_setup, | ||
2902 | .flags = CON_PRINTBUFFER, | ||
2903 | .index = -1, | ||
2904 | }; | ||
2905 | |||
2906 | /* | ||
2907 | * Register console. | ||
2908 | */ | ||
2909 | static void __init mac_scc_console_init(void) | ||
2910 | { | ||
2911 | register_console(&sercons); | ||
2912 | } | ||
2913 | console_initcall(mac_scc_console_init); | ||
2914 | |||
2915 | #endif /* ifdef CONFIG_SERIAL_CONSOLE */ | ||
2916 | |||
2917 | #ifdef CONFIG_KGDB | ||
2918 | /* These are for receiving and sending characters under the kgdb | ||
2919 | * source level kernel debugger. | ||
2920 | */ | ||
2921 | void putDebugChar(char kgdb_char) | ||
2922 | { | ||
2923 | struct mac_zschannel *chan = zs_kgdbchan; | ||
2924 | while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) | ||
2925 | udelay(5); | ||
2926 | write_zsdata(chan, kgdb_char); | ||
2927 | } | ||
2928 | |||
2929 | char getDebugChar(void) | ||
2930 | { | ||
2931 | struct mac_zschannel *chan = zs_kgdbchan; | ||
2932 | while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) | ||
2933 | eieio(); /*barrier();*/ | ||
2934 | return read_zsdata(chan); | ||
2935 | } | ||
2936 | |||
2937 | void kgdb_interruptible(int yes) | ||
2938 | { | ||
2939 | struct mac_zschannel *chan = zs_kgdbchan; | ||
2940 | int one, nine; | ||
2941 | nine = read_zsreg(chan, 9); | ||
2942 | if (yes == 1) { | ||
2943 | one = EXT_INT_ENAB|INT_ALL_Rx; | ||
2944 | nine |= MIE; | ||
2945 | printk("turning serial ints on\n"); | ||
2946 | } else { | ||
2947 | one = RxINT_DISAB; | ||
2948 | nine &= ~MIE; | ||
2949 | printk("turning serial ints off\n"); | ||
2950 | } | ||
2951 | write_zsreg(chan, 1, one); | ||
2952 | write_zsreg(chan, 9, nine); | ||
2953 | } | ||
2954 | |||
2955 | /* This sets up the serial port we're using, and turns on | ||
2956 | * interrupts for that channel, so kgdb is usable once we're done. | ||
2957 | */ | ||
2958 | static inline void kgdb_chaninit(struct mac_zschannel *ms, int intson, int bps) | ||
2959 | { | ||
2960 | int brg; | ||
2961 | int i, x; | ||
2962 | volatile char *sccc = ms->control; | ||
2963 | brg = BPS_TO_BRG(bps, ZS_CLOCK/16); | ||
2964 | printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg); | ||
2965 | for (i = 20000; i != 0; --i) { | ||
2966 | x = *sccc; eieio(); | ||
2967 | } | ||
2968 | for (i = 0; i < sizeof(scc_inittab); ++i) { | ||
2969 | write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]); | ||
2970 | i++; | ||
2971 | } | ||
2972 | } | ||
2973 | |||
2974 | /* This is called at boot time to prime the kgdb serial debugging | ||
2975 | * serial line. The 'tty_num' argument is 0 for /dev/ttya and 1 | ||
2976 | * for /dev/ttyb which is determined in setup_arch() from the | ||
2977 | * boot command line flags. | ||
2978 | * XXX at the moment probably only channel A will work | ||
2979 | */ | ||
2980 | void __init zs_kgdb_hook(int tty_num) | ||
2981 | { | ||
2982 | /* Find out how many Z8530 SCCs we have */ | ||
2983 | if (zs_chain == 0) | ||
2984 | probe_sccs(); | ||
2985 | |||
2986 | set_scc_power(&zs_soft[tty_num], 1); | ||
2987 | |||
2988 | zs_kgdbchan = zs_soft[tty_num].zs_channel; | ||
2989 | zs_soft[tty_num].change_needed = 0; | ||
2990 | zs_soft[tty_num].clk_divisor = 16; | ||
2991 | zs_soft[tty_num].zs_baud = 38400; | ||
2992 | zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ | ||
2993 | |||
2994 | /* Turn on transmitter/receiver at 8-bits/char */ | ||
2995 | kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400); | ||
2996 | printk("KGDB: on channel %d initialized\n", tty_num); | ||
2997 | set_debug_traps(); /* init stub */ | ||
2998 | } | ||
2999 | #endif /* ifdef CONFIG_KGDB */ | ||
3000 | |||
3001 | #ifdef CONFIG_PMAC_PBOOK | ||
3002 | /* | ||
3003 | * notify clients before sleep and reset bus afterwards | ||
3004 | */ | ||
3005 | int | ||
3006 | serial_notify_sleep(struct pmu_sleep_notifier *self, int when) | ||
3007 | { | ||
3008 | int i; | ||
3009 | |||
3010 | switch (when) { | ||
3011 | case PBOOK_SLEEP_REQUEST: | ||
3012 | case PBOOK_SLEEP_REJECT: | ||
3013 | break; | ||
3014 | |||
3015 | case PBOOK_SLEEP_NOW: | ||
3016 | for (i=0; i<zs_channels_found; i++) { | ||
3017 | struct mac_serial *info = &zs_soft[i]; | ||
3018 | if (info->flags & ZILOG_INITIALIZED) { | ||
3019 | shutdown(info); | ||
3020 | info->flags |= ZILOG_SLEEPING; | ||
3021 | } | ||
3022 | } | ||
3023 | break; | ||
3024 | case PBOOK_WAKE: | ||
3025 | for (i=0; i<zs_channels_found; i++) { | ||
3026 | struct mac_serial *info = &zs_soft[i]; | ||
3027 | if (info->flags & ZILOG_SLEEPING) { | ||
3028 | info->flags &= ~ZILOG_SLEEPING; | ||
3029 | startup(info); | ||
3030 | } | ||
3031 | } | ||
3032 | break; | ||
3033 | } | ||
3034 | return PBOOK_SLEEP_OK; | ||
3035 | } | ||
3036 | #endif /* CONFIG_PMAC_PBOOK */ | ||
diff --git a/drivers/macintosh/macserial.h b/drivers/macintosh/macserial.h new file mode 100644 index 000000000000..bade11a7a5c3 --- /dev/null +++ b/drivers/macintosh/macserial.h | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * macserial.h: Definitions for the Macintosh Z8530 serial driver. | ||
3 | * | ||
4 | * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. | ||
5 | * | ||
6 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | ||
7 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
8 | */ | ||
9 | #ifndef _MACSERIAL_H | ||
10 | #define _MACSERIAL_H | ||
11 | |||
12 | #include <linux/spinlock.h> | ||
13 | |||
14 | #define NUM_ZSREGS 16 | ||
15 | |||
16 | struct serial_struct { | ||
17 | int type; | ||
18 | int line; | ||
19 | int port; | ||
20 | int irq; | ||
21 | int flags; | ||
22 | int xmit_fifo_size; | ||
23 | int custom_divisor; | ||
24 | int baud_base; | ||
25 | unsigned short close_delay; | ||
26 | char reserved_char[2]; | ||
27 | int hub6; | ||
28 | unsigned short closing_wait; /* time to wait before closing */ | ||
29 | unsigned short closing_wait2; /* no longer used... */ | ||
30 | int reserved[4]; | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * For the close wait times, 0 means wait forever for serial port to | ||
35 | * flush its output. 65535 means don't wait at all. | ||
36 | */ | ||
37 | #define ZILOG_CLOSING_WAIT_INF 0 | ||
38 | #define ZILOG_CLOSING_WAIT_NONE 65535 | ||
39 | |||
40 | /* | ||
41 | * Definitions for ZILOG_struct (and serial_struct) flags field | ||
42 | */ | ||
43 | #define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes | ||
44 | * on the callout port */ | ||
45 | #define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ | ||
46 | #define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ | ||
47 | #define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ | ||
48 | |||
49 | #define ZILOG_SPD_MASK 0x0030 | ||
50 | #define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ | ||
51 | |||
52 | #define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ | ||
53 | #define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ | ||
54 | |||
55 | #define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ | ||
56 | #define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ | ||
57 | #define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ | ||
58 | #define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ | ||
59 | #define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ | ||
60 | |||
61 | #define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ | ||
62 | #define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged | ||
63 | * users can set or reset */ | ||
64 | |||
65 | /* Internal flags used only by kernel/chr_drv/serial.c */ | ||
66 | #define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ | ||
67 | #define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ | ||
68 | #define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ | ||
69 | #define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ | ||
70 | #define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ | ||
71 | #define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ | ||
72 | #define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ | ||
73 | #define ZILOG_SLEEPING 0x01000000 /* have shut it down for sleep */ | ||
74 | |||
75 | /* Software state per channel */ | ||
76 | |||
77 | #ifdef __KERNEL__ | ||
78 | /* | ||
79 | * This is our internal structure for each serial port's state. | ||
80 | * | ||
81 | * Many fields are paralleled by the structure used by the serial_struct | ||
82 | * structure. | ||
83 | * | ||
84 | * For definitions of the flags field, see tty.h | ||
85 | */ | ||
86 | |||
87 | struct mac_serial; | ||
88 | |||
89 | struct mac_zschannel { | ||
90 | volatile unsigned char* control; | ||
91 | volatile unsigned char* data; | ||
92 | spinlock_t lock; | ||
93 | /* Used for debugging */ | ||
94 | struct mac_serial* parent; | ||
95 | }; | ||
96 | |||
97 | struct mac_dma { | ||
98 | volatile struct dbdma_regs dma; | ||
99 | volatile unsigned short res_count; | ||
100 | volatile unsigned short command; | ||
101 | volatile unsigned int buf_addr; | ||
102 | }; | ||
103 | |||
104 | struct mac_serial { | ||
105 | struct mac_serial *zs_next; /* For IRQ servicing chain */ | ||
106 | struct mac_zschannel *zs_channel; /* Channel registers */ | ||
107 | struct mac_zschannel *zs_chan_a; /* A side registers */ | ||
108 | unsigned char read_reg_zero; | ||
109 | struct device_node* dev_node; | ||
110 | spinlock_t lock; | ||
111 | |||
112 | char soft_carrier; /* Use soft carrier on this channel */ | ||
113 | char break_abort; /* Is serial console in, so process brk/abrt */ | ||
114 | char kgdb_channel; /* Kgdb is running on this channel */ | ||
115 | char is_cons; /* Is this our console. */ | ||
116 | char is_internal_modem; /* is connected to an internal modem */ | ||
117 | char is_irda; /* is connected to an IrDA codec */ | ||
118 | int port_type; /* Port type for pmac_feature */ | ||
119 | unsigned char tx_active; /* character is being xmitted */ | ||
120 | unsigned char tx_stopped; /* output is suspended */ | ||
121 | unsigned char power_wait; /* waiting for power-up delay to expire */ | ||
122 | |||
123 | /* We need to know the current clock divisor | ||
124 | * to read the bps rate the chip has currently | ||
125 | * loaded. | ||
126 | */ | ||
127 | unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ | ||
128 | int zs_baud; | ||
129 | |||
130 | /* Current write register values */ | ||
131 | unsigned char curregs[NUM_ZSREGS]; | ||
132 | |||
133 | /* Values we need to set next opportunity */ | ||
134 | unsigned char pendregs[NUM_ZSREGS]; | ||
135 | |||
136 | char change_needed; | ||
137 | |||
138 | int magic; | ||
139 | int baud_base; | ||
140 | int port; | ||
141 | int irq; | ||
142 | int flags; /* defined in tty.h */ | ||
143 | int type; /* UART type */ | ||
144 | struct tty_struct *tty; | ||
145 | int read_status_mask; | ||
146 | int ignore_status_mask; | ||
147 | int timeout; | ||
148 | int xmit_fifo_size; | ||
149 | int custom_divisor; | ||
150 | int x_char; /* xon/xoff character */ | ||
151 | int close_delay; | ||
152 | unsigned short closing_wait; | ||
153 | unsigned short closing_wait2; | ||
154 | unsigned long event; | ||
155 | unsigned long last_active; | ||
156 | int line; | ||
157 | int count; /* # of fd on device */ | ||
158 | int blocked_open; /* # of blocked opens */ | ||
159 | unsigned char *xmit_buf; | ||
160 | int xmit_head; | ||
161 | int xmit_tail; | ||
162 | int xmit_cnt; | ||
163 | struct work_struct tqueue; | ||
164 | wait_queue_head_t open_wait; | ||
165 | wait_queue_head_t close_wait; | ||
166 | |||
167 | volatile struct dbdma_regs *tx_dma; | ||
168 | int tx_dma_irq; | ||
169 | volatile struct dbdma_cmd *tx_cmds; | ||
170 | volatile struct mac_dma *rx; | ||
171 | int rx_dma_irq; | ||
172 | volatile struct dbdma_cmd **rx_cmds; | ||
173 | unsigned char **rx_char_buf; | ||
174 | unsigned char **rx_flag_buf; | ||
175 | #define RX_BUF_SIZE 256 | ||
176 | int rx_nbuf; | ||
177 | int rx_done_bytes; | ||
178 | int rx_ubuf; | ||
179 | int rx_fbuf; | ||
180 | #define RX_NO_FBUF (-1) | ||
181 | int rx_cbuf; | ||
182 | spinlock_t rx_dma_lock; | ||
183 | int has_dma; | ||
184 | int dma_initted; | ||
185 | void *dma_priv; | ||
186 | struct timer_list poll_dma_timer; | ||
187 | #define RX_DMA_TIMER (jiffies + 10*HZ/1000) | ||
188 | |||
189 | struct timer_list powerup_timer; | ||
190 | }; | ||
191 | |||
192 | |||
193 | #define SERIAL_MAGIC 0x5301 | ||
194 | |||
195 | /* | ||
196 | * The size of the serial xmit buffer is 1 page, or 4096 bytes | ||
197 | */ | ||
198 | #define SERIAL_XMIT_SIZE 4096 | ||
199 | |||
200 | /* | ||
201 | * Events are used to schedule things to happen at timer-interrupt | ||
202 | * time, instead of at rs interrupt time. | ||
203 | */ | ||
204 | #define RS_EVENT_WRITE_WAKEUP 0 | ||
205 | |||
206 | #endif /* __KERNEL__ */ | ||
207 | |||
208 | /* Conversion routines to/from brg time constants from/to bits | ||
209 | * per second. | ||
210 | */ | ||
211 | #define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) | ||
212 | #define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) | ||
213 | |||
214 | /* The Zilog register set */ | ||
215 | |||
216 | #define FLAG 0x7e | ||
217 | |||
218 | /* Write Register 0 */ | ||
219 | #define R0 0 /* Register selects */ | ||
220 | #define R1 1 | ||
221 | #define R2 2 | ||
222 | #define R3 3 | ||
223 | #define R4 4 | ||
224 | #define R5 5 | ||
225 | #define R6 6 | ||
226 | #define R7 7 | ||
227 | #define R8 8 | ||
228 | #define R9 9 | ||
229 | #define R10 10 | ||
230 | #define R11 11 | ||
231 | #define R12 12 | ||
232 | #define R13 13 | ||
233 | #define R14 14 | ||
234 | #define R15 15 | ||
235 | |||
236 | #define NULLCODE 0 /* Null Code */ | ||
237 | #define POINT_HIGH 0x8 /* Select upper half of registers */ | ||
238 | #define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ | ||
239 | #define SEND_ABORT 0x18 /* HDLC Abort */ | ||
240 | #define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ | ||
241 | #define RES_Tx_P 0x28 /* Reset TxINT Pending */ | ||
242 | #define ERR_RES 0x30 /* Error Reset */ | ||
243 | #define RES_H_IUS 0x38 /* Reset highest IUS */ | ||
244 | |||
245 | #define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ | ||
246 | #define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ | ||
247 | #define RES_EOM_L 0xC0 /* Reset EOM latch */ | ||
248 | |||
249 | /* Write Register 1 */ | ||
250 | |||
251 | #define EXT_INT_ENAB 0x1 /* Ext Int Enable */ | ||
252 | #define TxINT_ENAB 0x2 /* Tx Int Enable */ | ||
253 | #define PAR_SPEC 0x4 /* Parity is special condition */ | ||
254 | |||
255 | #define RxINT_DISAB 0 /* Rx Int Disable */ | ||
256 | #define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ | ||
257 | #define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ | ||
258 | #define INT_ERR_Rx 0x18 /* Int on error only */ | ||
259 | |||
260 | #define WT_RDY_RT 0x20 /* W/Req reflects recv if 1, xmit if 0 */ | ||
261 | #define WT_FN_RDYFN 0x40 /* W/Req pin is DMA request if 1, wait if 0 */ | ||
262 | #define WT_RDY_ENAB 0x80 /* Enable W/Req pin */ | ||
263 | |||
264 | /* Write Register #2 (Interrupt Vector) */ | ||
265 | |||
266 | /* Write Register 3 */ | ||
267 | |||
268 | #define RxENABLE 0x1 /* Rx Enable */ | ||
269 | #define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ | ||
270 | #define ADD_SM 0x4 /* Address Search Mode (SDLC) */ | ||
271 | #define RxCRC_ENAB 0x8 /* Rx CRC Enable */ | ||
272 | #define ENT_HM 0x10 /* Enter Hunt Mode */ | ||
273 | #define AUTO_ENAB 0x20 /* Auto Enables */ | ||
274 | #define Rx5 0x0 /* Rx 5 Bits/Character */ | ||
275 | #define Rx7 0x40 /* Rx 7 Bits/Character */ | ||
276 | #define Rx6 0x80 /* Rx 6 Bits/Character */ | ||
277 | #define Rx8 0xc0 /* Rx 8 Bits/Character */ | ||
278 | #define RxNBITS_MASK 0xc0 | ||
279 | |||
280 | /* Write Register 4 */ | ||
281 | |||
282 | #define PAR_ENA 0x1 /* Parity Enable */ | ||
283 | #define PAR_EVEN 0x2 /* Parity Even/Odd* */ | ||
284 | |||
285 | #define SYNC_ENAB 0 /* Sync Modes Enable */ | ||
286 | #define SB1 0x4 /* 1 stop bit/char */ | ||
287 | #define SB15 0x8 /* 1.5 stop bits/char */ | ||
288 | #define SB2 0xc /* 2 stop bits/char */ | ||
289 | #define SB_MASK 0xc | ||
290 | |||
291 | #define MONSYNC 0 /* 8 Bit Sync character */ | ||
292 | #define BISYNC 0x10 /* 16 bit sync character */ | ||
293 | #define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ | ||
294 | #define EXTSYNC 0x30 /* External Sync Mode */ | ||
295 | |||
296 | #define X1CLK 0x0 /* x1 clock mode */ | ||
297 | #define X16CLK 0x40 /* x16 clock mode */ | ||
298 | #define X32CLK 0x80 /* x32 clock mode */ | ||
299 | #define X64CLK 0xC0 /* x64 clock mode */ | ||
300 | #define XCLK_MASK 0xC0 | ||
301 | |||
302 | /* Write Register 5 */ | ||
303 | |||
304 | #define TxCRC_ENAB 0x1 /* Tx CRC Enable */ | ||
305 | #define RTS 0x2 /* RTS */ | ||
306 | #define SDLC_CRC 0x4 /* SDLC/CRC-16 */ | ||
307 | #define TxENAB 0x8 /* Tx Enable */ | ||
308 | #define SND_BRK 0x10 /* Send Break */ | ||
309 | #define Tx5 0x0 /* Tx 5 bits (or less)/character */ | ||
310 | #define Tx7 0x20 /* Tx 7 bits/character */ | ||
311 | #define Tx6 0x40 /* Tx 6 bits/character */ | ||
312 | #define Tx8 0x60 /* Tx 8 bits/character */ | ||
313 | #define TxNBITS_MASK 0x60 | ||
314 | #define DTR 0x80 /* DTR */ | ||
315 | |||
316 | /* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ | ||
317 | |||
318 | /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ | ||
319 | |||
320 | /* Write Register 7' (Some enhanced feature control) */ | ||
321 | #define ENEXREAD 0x40 /* Enable read of some write registers */ | ||
322 | |||
323 | /* Write Register 8 (transmit buffer) */ | ||
324 | |||
325 | /* Write Register 9 (Master interrupt control) */ | ||
326 | #define VIS 1 /* Vector Includes Status */ | ||
327 | #define NV 2 /* No Vector */ | ||
328 | #define DLC 4 /* Disable Lower Chain */ | ||
329 | #define MIE 8 /* Master Interrupt Enable */ | ||
330 | #define STATHI 0x10 /* Status high */ | ||
331 | #define NORESET 0 /* No reset on write to R9 */ | ||
332 | #define CHRB 0x40 /* Reset channel B */ | ||
333 | #define CHRA 0x80 /* Reset channel A */ | ||
334 | #define FHWRES 0xc0 /* Force hardware reset */ | ||
335 | |||
336 | /* Write Register 10 (misc control bits) */ | ||
337 | #define BIT6 1 /* 6 bit/8bit sync */ | ||
338 | #define LOOPMODE 2 /* SDLC Loop mode */ | ||
339 | #define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ | ||
340 | #define MARKIDLE 8 /* Mark/flag on idle */ | ||
341 | #define GAOP 0x10 /* Go active on poll */ | ||
342 | #define NRZ 0 /* NRZ mode */ | ||
343 | #define NRZI 0x20 /* NRZI mode */ | ||
344 | #define FM1 0x40 /* FM1 (transition = 1) */ | ||
345 | #define FM0 0x60 /* FM0 (transition = 0) */ | ||
346 | #define CRCPS 0x80 /* CRC Preset I/O */ | ||
347 | |||
348 | /* Write Register 11 (Clock Mode control) */ | ||
349 | #define TRxCXT 0 /* TRxC = Xtal output */ | ||
350 | #define TRxCTC 1 /* TRxC = Transmit clock */ | ||
351 | #define TRxCBR 2 /* TRxC = BR Generator Output */ | ||
352 | #define TRxCDP 3 /* TRxC = DPLL output */ | ||
353 | #define TRxCOI 4 /* TRxC O/I */ | ||
354 | #define TCRTxCP 0 /* Transmit clock = RTxC pin */ | ||
355 | #define TCTRxCP 8 /* Transmit clock = TRxC pin */ | ||
356 | #define TCBR 0x10 /* Transmit clock = BR Generator output */ | ||
357 | #define TCDPLL 0x18 /* Transmit clock = DPLL output */ | ||
358 | #define RCRTxCP 0 /* Receive clock = RTxC pin */ | ||
359 | #define RCTRxCP 0x20 /* Receive clock = TRxC pin */ | ||
360 | #define RCBR 0x40 /* Receive clock = BR Generator output */ | ||
361 | #define RCDPLL 0x60 /* Receive clock = DPLL output */ | ||
362 | #define RTxCX 0x80 /* RTxC Xtal/No Xtal */ | ||
363 | |||
364 | /* Write Register 12 (lower byte of baud rate generator time constant) */ | ||
365 | |||
366 | /* Write Register 13 (upper byte of baud rate generator time constant) */ | ||
367 | |||
368 | /* Write Register 14 (Misc control bits) */ | ||
369 | #define BRENABL 1 /* Baud rate generator enable */ | ||
370 | #define BRSRC 2 /* Baud rate generator source */ | ||
371 | #define DTRREQ 4 /* DTR/Request function */ | ||
372 | #define AUTOECHO 8 /* Auto Echo */ | ||
373 | #define LOOPBAK 0x10 /* Local loopback */ | ||
374 | #define SEARCH 0x20 /* Enter search mode */ | ||
375 | #define RMC 0x40 /* Reset missing clock */ | ||
376 | #define DISDPLL 0x60 /* Disable DPLL */ | ||
377 | #define SSBR 0x80 /* Set DPLL source = BR generator */ | ||
378 | #define SSRTxC 0xa0 /* Set DPLL source = RTxC */ | ||
379 | #define SFMM 0xc0 /* Set FM mode */ | ||
380 | #define SNRZI 0xe0 /* Set NRZI mode */ | ||
381 | |||
382 | /* Write Register 15 (external/status interrupt control) */ | ||
383 | #define EN85C30 1 /* Enable some 85c30-enhanced registers */ | ||
384 | #define ZCIE 2 /* Zero count IE */ | ||
385 | #define ENSTFIFO 4 /* Enable status FIFO (SDLC) */ | ||
386 | #define DCDIE 8 /* DCD IE */ | ||
387 | #define SYNCIE 0x10 /* Sync/hunt IE */ | ||
388 | #define CTSIE 0x20 /* CTS IE */ | ||
389 | #define TxUIE 0x40 /* Tx Underrun/EOM IE */ | ||
390 | #define BRKIE 0x80 /* Break/Abort IE */ | ||
391 | |||
392 | |||
393 | /* Read Register 0 */ | ||
394 | #define Rx_CH_AV 0x1 /* Rx Character Available */ | ||
395 | #define ZCOUNT 0x2 /* Zero count */ | ||
396 | #define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ | ||
397 | #define DCD 0x8 /* DCD */ | ||
398 | #define SYNC_HUNT 0x10 /* Sync/hunt */ | ||
399 | #define CTS 0x20 /* CTS */ | ||
400 | #define TxEOM 0x40 /* Tx underrun */ | ||
401 | #define BRK_ABRT 0x80 /* Break/Abort */ | ||
402 | |||
403 | /* Read Register 1 */ | ||
404 | #define ALL_SNT 0x1 /* All sent */ | ||
405 | /* Residue Data for 8 Rx bits/char programmed */ | ||
406 | #define RES3 0x8 /* 0/3 */ | ||
407 | #define RES4 0x4 /* 0/4 */ | ||
408 | #define RES5 0xc /* 0/5 */ | ||
409 | #define RES6 0x2 /* 0/6 */ | ||
410 | #define RES7 0xa /* 0/7 */ | ||
411 | #define RES8 0x6 /* 0/8 */ | ||
412 | #define RES18 0xe /* 1/8 */ | ||
413 | #define RES28 0x0 /* 2/8 */ | ||
414 | /* Special Rx Condition Interrupts */ | ||
415 | #define PAR_ERR 0x10 /* Parity error */ | ||
416 | #define Rx_OVR 0x20 /* Rx Overrun Error */ | ||
417 | #define FRM_ERR 0x40 /* CRC/Framing Error */ | ||
418 | #define END_FR 0x80 /* End of Frame (SDLC) */ | ||
419 | |||
420 | /* Read Register 2 (channel b only) - Interrupt vector */ | ||
421 | #define CHB_Tx_EMPTY 0x00 | ||
422 | #define CHB_EXT_STAT 0x02 | ||
423 | #define CHB_Rx_AVAIL 0x04 | ||
424 | #define CHB_SPECIAL 0x06 | ||
425 | #define CHA_Tx_EMPTY 0x08 | ||
426 | #define CHA_EXT_STAT 0x0a | ||
427 | #define CHA_Rx_AVAIL 0x0c | ||
428 | #define CHA_SPECIAL 0x0e | ||
429 | #define STATUS_MASK 0x06 | ||
430 | |||
431 | /* Read Register 3 (interrupt pending register) ch a only */ | ||
432 | #define CHBEXT 0x1 /* Channel B Ext/Stat IP */ | ||
433 | #define CHBTxIP 0x2 /* Channel B Tx IP */ | ||
434 | #define CHBRxIP 0x4 /* Channel B Rx IP */ | ||
435 | #define CHAEXT 0x8 /* Channel A Ext/Stat IP */ | ||
436 | #define CHATxIP 0x10 /* Channel A Tx IP */ | ||
437 | #define CHARxIP 0x20 /* Channel A Rx IP */ | ||
438 | |||
439 | /* Read Register 8 (receive data register) */ | ||
440 | |||
441 | /* Read Register 10 (misc status bits) */ | ||
442 | #define ONLOOP 2 /* On loop */ | ||
443 | #define LOOPSEND 0x10 /* Loop sending */ | ||
444 | #define CLK2MIS 0x40 /* Two clocks missing */ | ||
445 | #define CLK1MIS 0x80 /* One clock missing */ | ||
446 | |||
447 | /* Read Register 12 (lower byte of baud rate generator constant) */ | ||
448 | |||
449 | /* Read Register 13 (upper byte of baud rate generator constant) */ | ||
450 | |||
451 | /* Read Register 15 (value of WR 15) */ | ||
452 | |||
453 | /* Misc macros */ | ||
454 | #define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) | ||
455 | #define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ | ||
456 | garbage = read_zsdata(channel); \ | ||
457 | garbage = read_zsdata(channel); \ | ||
458 | garbage = read_zsdata(channel); \ | ||
459 | } while(0) | ||
460 | |||
461 | #endif /* !(_MACSERIAL_H) */ | ||
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c new file mode 100644 index 000000000000..b8b5a2f1485a --- /dev/null +++ b/drivers/macintosh/mediabay.c | |||
@@ -0,0 +1,851 @@ | |||
1 | /* | ||
2 | * Driver for the media bay on the PowerBook 3400 and 2400. | ||
3 | * | ||
4 | * Copyright (C) 1998 Paul Mackerras. | ||
5 | * | ||
6 | * Various evolutions by Benjamin Herrenschmidt & Henry Worth | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/hdreg.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/ide.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/machdep.h> | ||
28 | #include <asm/pmac_feature.h> | ||
29 | #include <asm/mediabay.h> | ||
30 | #include <asm/sections.h> | ||
31 | #include <asm/ohare.h> | ||
32 | #include <asm/heathrow.h> | ||
33 | #include <asm/keylargo.h> | ||
34 | #include <linux/adb.h> | ||
35 | #include <linux/pmu.h> | ||
36 | |||
37 | |||
38 | #define MB_DEBUG | ||
39 | #define MB_IGNORE_SIGNALS | ||
40 | |||
41 | #ifdef MB_DEBUG | ||
42 | #define MBDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) | ||
43 | #else | ||
44 | #define MBDBG(fmt, arg...) do { } while (0) | ||
45 | #endif | ||
46 | |||
47 | #define MB_FCR32(bay, r) ((bay)->base + ((r) >> 2)) | ||
48 | #define MB_FCR8(bay, r) (((volatile u8 __iomem *)((bay)->base)) + (r)) | ||
49 | |||
50 | #define MB_IN32(bay,r) (in_le32(MB_FCR32(bay,r))) | ||
51 | #define MB_OUT32(bay,r,v) (out_le32(MB_FCR32(bay,r), (v))) | ||
52 | #define MB_BIS(bay,r,v) (MB_OUT32((bay), (r), MB_IN32((bay), r) | (v))) | ||
53 | #define MB_BIC(bay,r,v) (MB_OUT32((bay), (r), MB_IN32((bay), r) & ~(v))) | ||
54 | #define MB_IN8(bay,r) (in_8(MB_FCR8(bay,r))) | ||
55 | #define MB_OUT8(bay,r,v) (out_8(MB_FCR8(bay,r), (v))) | ||
56 | |||
57 | struct media_bay_info; | ||
58 | |||
59 | struct mb_ops { | ||
60 | char* name; | ||
61 | void (*init)(struct media_bay_info *bay); | ||
62 | u8 (*content)(struct media_bay_info *bay); | ||
63 | void (*power)(struct media_bay_info *bay, int on_off); | ||
64 | int (*setup_bus)(struct media_bay_info *bay, u8 device_id); | ||
65 | void (*un_reset)(struct media_bay_info *bay); | ||
66 | void (*un_reset_ide)(struct media_bay_info *bay); | ||
67 | }; | ||
68 | |||
69 | struct media_bay_info { | ||
70 | u32 __iomem *base; | ||
71 | int content_id; | ||
72 | int state; | ||
73 | int last_value; | ||
74 | int value_count; | ||
75 | int timer; | ||
76 | struct macio_dev *mdev; | ||
77 | struct mb_ops* ops; | ||
78 | int index; | ||
79 | int cached_gpio; | ||
80 | int sleeping; | ||
81 | struct semaphore lock; | ||
82 | #ifdef CONFIG_BLK_DEV_IDE | ||
83 | void __iomem *cd_base; | ||
84 | int cd_index; | ||
85 | int cd_irq; | ||
86 | int cd_retry; | ||
87 | #endif | ||
88 | }; | ||
89 | |||
90 | #define MAX_BAYS 2 | ||
91 | |||
92 | static struct media_bay_info media_bays[MAX_BAYS]; | ||
93 | int media_bay_count = 0; | ||
94 | |||
95 | #ifdef CONFIG_BLK_DEV_IDE | ||
96 | /* check the busy bit in the media-bay ide interface | ||
97 | (assumes the media-bay contains an ide device) */ | ||
98 | #define MB_IDE_READY(i) ((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0) | ||
99 | #endif | ||
100 | |||
101 | /* | ||
102 | * Wait that number of ms between each step in normal polling mode | ||
103 | */ | ||
104 | #define MB_POLL_DELAY 25 | ||
105 | |||
106 | /* | ||
107 | * Consider the media-bay ID value stable if it is the same for | ||
108 | * this number of milliseconds | ||
109 | */ | ||
110 | #define MB_STABLE_DELAY 100 | ||
111 | |||
112 | /* Wait after powering up the media bay this delay in ms | ||
113 | * timeout bumped for some powerbooks | ||
114 | */ | ||
115 | #define MB_POWER_DELAY 200 | ||
116 | |||
117 | /* | ||
118 | * Hold the media-bay reset signal true for this many ticks | ||
119 | * after a device is inserted before releasing it. | ||
120 | */ | ||
121 | #define MB_RESET_DELAY 50 | ||
122 | |||
123 | /* | ||
124 | * Wait this long after the reset signal is released and before doing | ||
125 | * further operations. After this delay, the IDE reset signal is released | ||
126 | * too for an IDE device | ||
127 | */ | ||
128 | #define MB_SETUP_DELAY 100 | ||
129 | |||
130 | /* | ||
131 | * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted | ||
132 | * (or until the device is ready) before waiting for busy bit to disappear | ||
133 | */ | ||
134 | #define MB_IDE_WAIT 1000 | ||
135 | |||
136 | /* | ||
137 | * Timeout waiting for busy bit of an IDE device to go down | ||
138 | */ | ||
139 | #define MB_IDE_TIMEOUT 5000 | ||
140 | |||
141 | /* | ||
142 | * Max retries of the full power up/down sequence for an IDE device | ||
143 | */ | ||
144 | #define MAX_CD_RETRIES 3 | ||
145 | |||
146 | /* | ||
147 | * States of a media bay | ||
148 | */ | ||
149 | enum { | ||
150 | mb_empty = 0, /* Idle */ | ||
151 | mb_powering_up, /* power bit set, waiting MB_POWER_DELAY */ | ||
152 | mb_enabling_bay, /* enable bits set, waiting MB_RESET_DELAY */ | ||
153 | mb_resetting, /* reset bit unset, waiting MB_SETUP_DELAY */ | ||
154 | mb_ide_resetting, /* IDE reset bit unser, waiting MB_IDE_WAIT */ | ||
155 | mb_ide_waiting, /* Waiting for BUSY bit to go away until MB_IDE_TIMEOUT */ | ||
156 | mb_up, /* Media bay full */ | ||
157 | mb_powering_down /* Powering down (avoid too fast down/up) */ | ||
158 | }; | ||
159 | |||
160 | #define MB_POWER_SOUND 0x08 | ||
161 | #define MB_POWER_FLOPPY 0x04 | ||
162 | #define MB_POWER_ATA 0x02 | ||
163 | #define MB_POWER_PCI 0x01 | ||
164 | #define MB_POWER_OFF 0x00 | ||
165 | |||
166 | /* | ||
167 | * Functions for polling content of media bay | ||
168 | */ | ||
169 | |||
170 | static u8 __pmac | ||
171 | ohare_mb_content(struct media_bay_info *bay) | ||
172 | { | ||
173 | return (MB_IN32(bay, OHARE_MBCR) >> 12) & 7; | ||
174 | } | ||
175 | |||
176 | static u8 __pmac | ||
177 | heathrow_mb_content(struct media_bay_info *bay) | ||
178 | { | ||
179 | return (MB_IN32(bay, HEATHROW_MBCR) >> 12) & 7; | ||
180 | } | ||
181 | |||
182 | static u8 __pmac | ||
183 | keylargo_mb_content(struct media_bay_info *bay) | ||
184 | { | ||
185 | int new_gpio; | ||
186 | |||
187 | new_gpio = MB_IN8(bay, KL_GPIO_MEDIABAY_IRQ) & KEYLARGO_GPIO_INPUT_DATA; | ||
188 | if (new_gpio) { | ||
189 | bay->cached_gpio = new_gpio; | ||
190 | return MB_NO; | ||
191 | } else if (bay->cached_gpio != new_gpio) { | ||
192 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE); | ||
193 | (void)MB_IN32(bay, KEYLARGO_MBCR); | ||
194 | udelay(5); | ||
195 | MB_BIC(bay, KEYLARGO_MBCR, 0x0000000F); | ||
196 | (void)MB_IN32(bay, KEYLARGO_MBCR); | ||
197 | udelay(5); | ||
198 | bay->cached_gpio = new_gpio; | ||
199 | } | ||
200 | return (MB_IN32(bay, KEYLARGO_MBCR) >> 4) & 7; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Functions for powering up/down the bay, puts the bay device | ||
205 | * into reset state as well | ||
206 | */ | ||
207 | |||
208 | static void __pmac | ||
209 | ohare_mb_power(struct media_bay_info* bay, int on_off) | ||
210 | { | ||
211 | if (on_off) { | ||
212 | /* Power up device, assert it's reset line */ | ||
213 | MB_BIC(bay, OHARE_FCR, OH_BAY_RESET_N); | ||
214 | MB_BIC(bay, OHARE_FCR, OH_BAY_POWER_N); | ||
215 | } else { | ||
216 | /* Disable all devices */ | ||
217 | MB_BIC(bay, OHARE_FCR, OH_BAY_DEV_MASK); | ||
218 | MB_BIC(bay, OHARE_FCR, OH_FLOPPY_ENABLE); | ||
219 | /* Cut power from bay, release reset line */ | ||
220 | MB_BIS(bay, OHARE_FCR, OH_BAY_POWER_N); | ||
221 | MB_BIS(bay, OHARE_FCR, OH_BAY_RESET_N); | ||
222 | MB_BIS(bay, OHARE_FCR, OH_IDE1_RESET_N); | ||
223 | } | ||
224 | MB_BIC(bay, OHARE_MBCR, 0x00000F00); | ||
225 | } | ||
226 | |||
227 | static void __pmac | ||
228 | heathrow_mb_power(struct media_bay_info* bay, int on_off) | ||
229 | { | ||
230 | if (on_off) { | ||
231 | /* Power up device, assert it's reset line */ | ||
232 | MB_BIC(bay, HEATHROW_FCR, HRW_BAY_RESET_N); | ||
233 | MB_BIC(bay, HEATHROW_FCR, HRW_BAY_POWER_N); | ||
234 | } else { | ||
235 | /* Disable all devices */ | ||
236 | MB_BIC(bay, HEATHROW_FCR, HRW_BAY_DEV_MASK); | ||
237 | MB_BIC(bay, HEATHROW_FCR, HRW_SWIM_ENABLE); | ||
238 | /* Cut power from bay, release reset line */ | ||
239 | MB_BIS(bay, HEATHROW_FCR, HRW_BAY_POWER_N); | ||
240 | MB_BIS(bay, HEATHROW_FCR, HRW_BAY_RESET_N); | ||
241 | MB_BIS(bay, HEATHROW_FCR, HRW_IDE1_RESET_N); | ||
242 | } | ||
243 | MB_BIC(bay, HEATHROW_MBCR, 0x00000F00); | ||
244 | } | ||
245 | |||
246 | static void __pmac | ||
247 | keylargo_mb_power(struct media_bay_info* bay, int on_off) | ||
248 | { | ||
249 | if (on_off) { | ||
250 | /* Power up device, assert it's reset line */ | ||
251 | MB_BIC(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_RESET); | ||
252 | MB_BIC(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_POWER); | ||
253 | } else { | ||
254 | /* Disable all devices */ | ||
255 | MB_BIC(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); | ||
256 | MB_BIC(bay, KEYLARGO_FCR1, KL1_EIDE0_ENABLE); | ||
257 | /* Cut power from bay, release reset line */ | ||
258 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_POWER); | ||
259 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_RESET); | ||
260 | MB_BIS(bay, KEYLARGO_FCR1, KL1_EIDE0_RESET_N); | ||
261 | } | ||
262 | MB_BIC(bay, KEYLARGO_MBCR, 0x0000000F); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Functions for configuring the media bay for a given type of device, | ||
267 | * enable the related busses | ||
268 | */ | ||
269 | |||
270 | static int __pmac | ||
271 | ohare_mb_setup_bus(struct media_bay_info* bay, u8 device_id) | ||
272 | { | ||
273 | switch(device_id) { | ||
274 | case MB_FD: | ||
275 | case MB_FD1: | ||
276 | MB_BIS(bay, OHARE_FCR, OH_BAY_FLOPPY_ENABLE); | ||
277 | MB_BIS(bay, OHARE_FCR, OH_FLOPPY_ENABLE); | ||
278 | return 0; | ||
279 | case MB_CD: | ||
280 | MB_BIC(bay, OHARE_FCR, OH_IDE1_RESET_N); | ||
281 | MB_BIS(bay, OHARE_FCR, OH_BAY_IDE_ENABLE); | ||
282 | return 0; | ||
283 | case MB_PCI: | ||
284 | MB_BIS(bay, OHARE_FCR, OH_BAY_PCI_ENABLE); | ||
285 | return 0; | ||
286 | } | ||
287 | return -ENODEV; | ||
288 | } | ||
289 | |||
290 | static int __pmac | ||
291 | heathrow_mb_setup_bus(struct media_bay_info* bay, u8 device_id) | ||
292 | { | ||
293 | switch(device_id) { | ||
294 | case MB_FD: | ||
295 | case MB_FD1: | ||
296 | MB_BIS(bay, HEATHROW_FCR, HRW_BAY_FLOPPY_ENABLE); | ||
297 | MB_BIS(bay, HEATHROW_FCR, HRW_SWIM_ENABLE); | ||
298 | return 0; | ||
299 | case MB_CD: | ||
300 | MB_BIC(bay, HEATHROW_FCR, HRW_IDE1_RESET_N); | ||
301 | MB_BIS(bay, HEATHROW_FCR, HRW_BAY_IDE_ENABLE); | ||
302 | return 0; | ||
303 | case MB_PCI: | ||
304 | MB_BIS(bay, HEATHROW_FCR, HRW_BAY_PCI_ENABLE); | ||
305 | return 0; | ||
306 | } | ||
307 | return -ENODEV; | ||
308 | } | ||
309 | |||
310 | static int __pmac | ||
311 | keylargo_mb_setup_bus(struct media_bay_info* bay, u8 device_id) | ||
312 | { | ||
313 | switch(device_id) { | ||
314 | case MB_CD: | ||
315 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); | ||
316 | MB_BIC(bay, KEYLARGO_FCR1, KL1_EIDE0_RESET_N); | ||
317 | MB_BIS(bay, KEYLARGO_FCR1, KL1_EIDE0_ENABLE); | ||
318 | return 0; | ||
319 | case MB_PCI: | ||
320 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_PCI_ENABLE); | ||
321 | return 0; | ||
322 | case MB_SOUND: | ||
323 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_SOUND_ENABLE); | ||
324 | return 0; | ||
325 | } | ||
326 | return -ENODEV; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * Functions for tweaking resets | ||
331 | */ | ||
332 | |||
333 | static void __pmac | ||
334 | ohare_mb_un_reset(struct media_bay_info* bay) | ||
335 | { | ||
336 | MB_BIS(bay, OHARE_FCR, OH_BAY_RESET_N); | ||
337 | } | ||
338 | |||
339 | static void __pmac keylargo_mb_init(struct media_bay_info *bay) | ||
340 | { | ||
341 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE); | ||
342 | } | ||
343 | |||
344 | static void __pmac heathrow_mb_un_reset(struct media_bay_info* bay) | ||
345 | { | ||
346 | MB_BIS(bay, HEATHROW_FCR, HRW_BAY_RESET_N); | ||
347 | } | ||
348 | |||
349 | static void __pmac keylargo_mb_un_reset(struct media_bay_info* bay) | ||
350 | { | ||
351 | MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_RESET); | ||
352 | } | ||
353 | |||
354 | static void __pmac ohare_mb_un_reset_ide(struct media_bay_info* bay) | ||
355 | { | ||
356 | MB_BIS(bay, OHARE_FCR, OH_IDE1_RESET_N); | ||
357 | } | ||
358 | |||
359 | static void __pmac heathrow_mb_un_reset_ide(struct media_bay_info* bay) | ||
360 | { | ||
361 | MB_BIS(bay, HEATHROW_FCR, HRW_IDE1_RESET_N); | ||
362 | } | ||
363 | |||
364 | static void __pmac keylargo_mb_un_reset_ide(struct media_bay_info* bay) | ||
365 | { | ||
366 | MB_BIS(bay, KEYLARGO_FCR1, KL1_EIDE0_RESET_N); | ||
367 | } | ||
368 | |||
369 | static inline void __pmac set_mb_power(struct media_bay_info* bay, int onoff) | ||
370 | { | ||
371 | /* Power up up and assert the bay reset line */ | ||
372 | if (onoff) { | ||
373 | bay->ops->power(bay, 1); | ||
374 | bay->state = mb_powering_up; | ||
375 | MBDBG("mediabay%d: powering up\n", bay->index); | ||
376 | } else { | ||
377 | /* Make sure everything is powered down & disabled */ | ||
378 | bay->ops->power(bay, 0); | ||
379 | bay->state = mb_powering_down; | ||
380 | MBDBG("mediabay%d: powering down\n", bay->index); | ||
381 | } | ||
382 | bay->timer = msecs_to_jiffies(MB_POWER_DELAY); | ||
383 | } | ||
384 | |||
385 | static void __pmac poll_media_bay(struct media_bay_info* bay) | ||
386 | { | ||
387 | int id = bay->ops->content(bay); | ||
388 | |||
389 | if (id == bay->last_value) { | ||
390 | if (id != bay->content_id) { | ||
391 | bay->value_count += msecs_to_jiffies(MB_POLL_DELAY); | ||
392 | if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) { | ||
393 | /* If the device type changes without going thru | ||
394 | * "MB_NO", we force a pass by "MB_NO" to make sure | ||
395 | * things are properly reset | ||
396 | */ | ||
397 | if ((id != MB_NO) && (bay->content_id != MB_NO)) { | ||
398 | id = MB_NO; | ||
399 | MBDBG("mediabay%d: forcing MB_NO\n", bay->index); | ||
400 | } | ||
401 | MBDBG("mediabay%d: switching to %d\n", bay->index, id); | ||
402 | set_mb_power(bay, id != MB_NO); | ||
403 | bay->content_id = id; | ||
404 | if (id == MB_NO) { | ||
405 | #ifdef CONFIG_BLK_DEV_IDE | ||
406 | bay->cd_retry = 0; | ||
407 | #endif | ||
408 | printk(KERN_INFO "media bay %d is empty\n", bay->index); | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | } else { | ||
413 | bay->last_value = id; | ||
414 | bay->value_count = 0; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | int __pmac check_media_bay(struct device_node *which_bay, int what) | ||
419 | { | ||
420 | #ifdef CONFIG_BLK_DEV_IDE | ||
421 | int i; | ||
422 | |||
423 | for (i=0; i<media_bay_count; i++) | ||
424 | if (media_bays[i].mdev && which_bay == media_bays[i].mdev->ofdev.node) { | ||
425 | if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) | ||
426 | return 0; | ||
427 | media_bays[i].cd_index = -1; | ||
428 | return -EINVAL; | ||
429 | } | ||
430 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
431 | return -ENODEV; | ||
432 | } | ||
433 | EXPORT_SYMBOL(check_media_bay); | ||
434 | |||
435 | int __pmac check_media_bay_by_base(unsigned long base, int what) | ||
436 | { | ||
437 | #ifdef CONFIG_BLK_DEV_IDE | ||
438 | int i; | ||
439 | |||
440 | for (i=0; i<media_bay_count; i++) | ||
441 | if (media_bays[i].mdev && base == (unsigned long) media_bays[i].cd_base) { | ||
442 | if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) | ||
443 | return 0; | ||
444 | media_bays[i].cd_index = -1; | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | #endif | ||
448 | |||
449 | return -ENODEV; | ||
450 | } | ||
451 | |||
452 | int __pmac media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, | ||
453 | int irq, int index) | ||
454 | { | ||
455 | #ifdef CONFIG_BLK_DEV_IDE | ||
456 | int i; | ||
457 | |||
458 | for (i=0; i<media_bay_count; i++) { | ||
459 | struct media_bay_info* bay = &media_bays[i]; | ||
460 | |||
461 | if (bay->mdev && which_bay == bay->mdev->ofdev.node) { | ||
462 | int timeout = 5000; | ||
463 | |||
464 | down(&bay->lock); | ||
465 | |||
466 | bay->cd_base = (void __iomem *) base; | ||
467 | bay->cd_irq = irq; | ||
468 | |||
469 | if ((MB_CD != bay->content_id) || bay->state != mb_up) { | ||
470 | up(&bay->lock); | ||
471 | return 0; | ||
472 | } | ||
473 | printk(KERN_DEBUG "Registered ide%d for media bay %d\n", index, i); | ||
474 | do { | ||
475 | if (MB_IDE_READY(i)) { | ||
476 | bay->cd_index = index; | ||
477 | up(&bay->lock); | ||
478 | return 0; | ||
479 | } | ||
480 | mdelay(1); | ||
481 | } while(--timeout); | ||
482 | printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i); | ||
483 | up(&bay->lock); | ||
484 | return -ENODEV; | ||
485 | } | ||
486 | } | ||
487 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
488 | |||
489 | return -ENODEV; | ||
490 | } | ||
491 | |||
492 | static void __pmac media_bay_step(int i) | ||
493 | { | ||
494 | struct media_bay_info* bay = &media_bays[i]; | ||
495 | |||
496 | /* We don't poll when powering down */ | ||
497 | if (bay->state != mb_powering_down) | ||
498 | poll_media_bay(bay); | ||
499 | |||
500 | /* If timer expired or polling IDE busy, run state machine */ | ||
501 | if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) { | ||
502 | bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); | ||
503 | if (bay->timer > 0) | ||
504 | return; | ||
505 | bay->timer = 0; | ||
506 | } | ||
507 | |||
508 | switch(bay->state) { | ||
509 | case mb_powering_up: | ||
510 | if (bay->ops->setup_bus(bay, bay->last_value) < 0) { | ||
511 | MBDBG("mediabay%d: device not supported (kind:%d)\n", i, bay->content_id); | ||
512 | set_mb_power(bay, 0); | ||
513 | break; | ||
514 | } | ||
515 | bay->timer = msecs_to_jiffies(MB_RESET_DELAY); | ||
516 | bay->state = mb_enabling_bay; | ||
517 | MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); | ||
518 | break; | ||
519 | case mb_enabling_bay: | ||
520 | bay->ops->un_reset(bay); | ||
521 | bay->timer = msecs_to_jiffies(MB_SETUP_DELAY); | ||
522 | bay->state = mb_resetting; | ||
523 | MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id); | ||
524 | break; | ||
525 | |||
526 | case mb_resetting: | ||
527 | if (bay->content_id != MB_CD) { | ||
528 | MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); | ||
529 | bay->state = mb_up; | ||
530 | break; | ||
531 | } | ||
532 | #ifdef CONFIG_BLK_DEV_IDE | ||
533 | MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id); | ||
534 | bay->ops->un_reset_ide(bay); | ||
535 | bay->timer = msecs_to_jiffies(MB_IDE_WAIT); | ||
536 | bay->state = mb_ide_resetting; | ||
537 | #else | ||
538 | printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i); | ||
539 | set_mb_power(bay, 0); | ||
540 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
541 | break; | ||
542 | |||
543 | #ifdef CONFIG_BLK_DEV_IDE | ||
544 | case mb_ide_resetting: | ||
545 | bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT); | ||
546 | bay->state = mb_ide_waiting; | ||
547 | MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id); | ||
548 | break; | ||
549 | |||
550 | case mb_ide_waiting: | ||
551 | if (bay->cd_base == NULL) { | ||
552 | bay->timer = 0; | ||
553 | bay->state = mb_up; | ||
554 | MBDBG("mediabay%d: up before IDE init\n", i); | ||
555 | break; | ||
556 | } else if (MB_IDE_READY(i)) { | ||
557 | bay->timer = 0; | ||
558 | bay->state = mb_up; | ||
559 | if (bay->cd_index < 0) { | ||
560 | hw_regs_t hw; | ||
561 | |||
562 | printk("mediabay %d, registering IDE...\n", i); | ||
563 | pmu_suspend(); | ||
564 | ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL); | ||
565 | hw.irq = bay->cd_irq; | ||
566 | hw.chipset = ide_pmac; | ||
567 | bay->cd_index = ide_register_hw(&hw, NULL); | ||
568 | pmu_resume(); | ||
569 | } | ||
570 | if (bay->cd_index == -1) { | ||
571 | /* We eventually do a retry */ | ||
572 | bay->cd_retry++; | ||
573 | printk("IDE register error\n"); | ||
574 | set_mb_power(bay, 0); | ||
575 | } else { | ||
576 | printk(KERN_DEBUG "media-bay %d is ide%d\n", i, bay->cd_index); | ||
577 | MBDBG("mediabay %d IDE ready\n", i); | ||
578 | } | ||
579 | break; | ||
580 | } else if (bay->timer > 0) | ||
581 | bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); | ||
582 | if (bay->timer <= 0) { | ||
583 | printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n", | ||
584 | i, readb(bay->cd_base + 0x70)); | ||
585 | MBDBG("mediabay%d: nIDE Timeout !\n", i); | ||
586 | set_mb_power(bay, 0); | ||
587 | bay->timer = 0; | ||
588 | } | ||
589 | break; | ||
590 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
591 | |||
592 | case mb_powering_down: | ||
593 | bay->state = mb_empty; | ||
594 | #ifdef CONFIG_BLK_DEV_IDE | ||
595 | if (bay->cd_index >= 0) { | ||
596 | printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, | ||
597 | bay->cd_index); | ||
598 | ide_unregister(bay->cd_index); | ||
599 | bay->cd_index = -1; | ||
600 | } | ||
601 | if (bay->cd_retry) { | ||
602 | if (bay->cd_retry > MAX_CD_RETRIES) { | ||
603 | /* Should add an error sound (sort of beep in dmasound) */ | ||
604 | printk("\nmedia-bay %d, IDE device badly inserted or unrecognised\n", i); | ||
605 | } else { | ||
606 | /* Force a new power down/up sequence */ | ||
607 | bay->content_id = MB_NO; | ||
608 | } | ||
609 | } | ||
610 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
611 | MBDBG("mediabay%d: end of power down\n", i); | ||
612 | break; | ||
613 | } | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * This procedure runs as a kernel thread to poll the media bay | ||
618 | * once each tick and register and unregister the IDE interface | ||
619 | * with the IDE driver. It needs to be a thread because | ||
620 | * ide_register can't be called from interrupt context. | ||
621 | */ | ||
622 | static int __pmac media_bay_task(void *x) | ||
623 | { | ||
624 | int i; | ||
625 | |||
626 | strcpy(current->comm, "media-bay"); | ||
627 | #ifdef MB_IGNORE_SIGNALS | ||
628 | sigfillset(¤t->blocked); | ||
629 | #endif | ||
630 | |||
631 | for (;;) { | ||
632 | for (i = 0; i < media_bay_count; ++i) { | ||
633 | down(&media_bays[i].lock); | ||
634 | if (!media_bays[i].sleeping) | ||
635 | media_bay_step(i); | ||
636 | up(&media_bays[i].lock); | ||
637 | } | ||
638 | |||
639 | msleep_interruptible(MB_POLL_DELAY); | ||
640 | if (signal_pending(current)) | ||
641 | return 0; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_match *match) | ||
646 | { | ||
647 | struct media_bay_info* bay; | ||
648 | u32 __iomem *regbase; | ||
649 | struct device_node *ofnode; | ||
650 | int i; | ||
651 | |||
652 | ofnode = mdev->ofdev.node; | ||
653 | |||
654 | if (macio_resource_count(mdev) < 1) | ||
655 | return -ENODEV; | ||
656 | if (macio_request_resources(mdev, "media-bay")) | ||
657 | return -EBUSY; | ||
658 | /* Media bay registers are located at the beginning of the | ||
659 | * mac-io chip, we get the parent address for now (hrm...) | ||
660 | */ | ||
661 | regbase = (u32 __iomem *) | ||
662 | ioremap(ofnode->parent->addrs[0].address, 0x100); | ||
663 | if (regbase == NULL) { | ||
664 | macio_release_resources(mdev); | ||
665 | return -ENOMEM; | ||
666 | } | ||
667 | |||
668 | i = media_bay_count++; | ||
669 | bay = &media_bays[i]; | ||
670 | bay->mdev = mdev; | ||
671 | bay->base = regbase; | ||
672 | bay->index = i; | ||
673 | bay->ops = match->data; | ||
674 | bay->sleeping = 0; | ||
675 | init_MUTEX(&bay->lock); | ||
676 | |||
677 | /* Init HW probing */ | ||
678 | if (bay->ops->init) | ||
679 | bay->ops->init(bay); | ||
680 | |||
681 | printk(KERN_INFO "mediabay%d: Registered %s media-bay\n", i, bay->ops->name); | ||
682 | |||
683 | /* Force an immediate detect */ | ||
684 | set_mb_power(bay, 0); | ||
685 | msleep(MB_POWER_DELAY); | ||
686 | bay->content_id = MB_NO; | ||
687 | bay->last_value = bay->ops->content(bay); | ||
688 | bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); | ||
689 | bay->state = mb_empty; | ||
690 | do { | ||
691 | msleep(MB_POLL_DELAY); | ||
692 | media_bay_step(i); | ||
693 | } while((bay->state != mb_empty) && | ||
694 | (bay->state != mb_up)); | ||
695 | |||
696 | /* Mark us ready by filling our mdev data */ | ||
697 | macio_set_drvdata(mdev, bay); | ||
698 | |||
699 | /* Startup kernel thread */ | ||
700 | if (i == 0) | ||
701 | kernel_thread(media_bay_task, NULL, CLONE_KERNEL); | ||
702 | |||
703 | return 0; | ||
704 | |||
705 | } | ||
706 | |||
707 | static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state) | ||
708 | { | ||
709 | struct media_bay_info *bay = macio_get_drvdata(mdev); | ||
710 | |||
711 | if (state != mdev->ofdev.dev.power.power_state && state == PM_SUSPEND_MEM) { | ||
712 | down(&bay->lock); | ||
713 | bay->sleeping = 1; | ||
714 | set_mb_power(bay, 0); | ||
715 | up(&bay->lock); | ||
716 | msleep(MB_POLL_DELAY); | ||
717 | mdev->ofdev.dev.power.power_state = state; | ||
718 | } | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int __pmac media_bay_resume(struct macio_dev *mdev) | ||
723 | { | ||
724 | struct media_bay_info *bay = macio_get_drvdata(mdev); | ||
725 | |||
726 | if (mdev->ofdev.dev.power.power_state != 0) { | ||
727 | mdev->ofdev.dev.power.power_state = 0; | ||
728 | |||
729 | /* We re-enable the bay using it's previous content | ||
730 | only if it did not change. Note those bozo timings, | ||
731 | they seem to help the 3400 get it right. | ||
732 | */ | ||
733 | /* Force MB power to 0 */ | ||
734 | down(&bay->lock); | ||
735 | set_mb_power(bay, 0); | ||
736 | msleep(MB_POWER_DELAY); | ||
737 | if (bay->ops->content(bay) != bay->content_id) { | ||
738 | printk("mediabay%d: content changed during sleep...\n", bay->index); | ||
739 | up(&bay->lock); | ||
740 | return 0; | ||
741 | } | ||
742 | set_mb_power(bay, 1); | ||
743 | bay->last_value = bay->content_id; | ||
744 | bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); | ||
745 | bay->timer = msecs_to_jiffies(MB_POWER_DELAY); | ||
746 | #ifdef CONFIG_BLK_DEV_IDE | ||
747 | bay->cd_retry = 0; | ||
748 | #endif | ||
749 | do { | ||
750 | msleep(MB_POLL_DELAY); | ||
751 | media_bay_step(bay->index); | ||
752 | } while((bay->state != mb_empty) && | ||
753 | (bay->state != mb_up)); | ||
754 | bay->sleeping = 0; | ||
755 | up(&bay->lock); | ||
756 | } | ||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | |||
761 | /* Definitions of "ops" structures. | ||
762 | */ | ||
763 | static struct mb_ops ohare_mb_ops __pmacdata = { | ||
764 | .name = "Ohare", | ||
765 | .content = ohare_mb_content, | ||
766 | .power = ohare_mb_power, | ||
767 | .setup_bus = ohare_mb_setup_bus, | ||
768 | .un_reset = ohare_mb_un_reset, | ||
769 | .un_reset_ide = ohare_mb_un_reset_ide, | ||
770 | }; | ||
771 | |||
772 | static struct mb_ops heathrow_mb_ops __pmacdata = { | ||
773 | .name = "Heathrow", | ||
774 | .content = heathrow_mb_content, | ||
775 | .power = heathrow_mb_power, | ||
776 | .setup_bus = heathrow_mb_setup_bus, | ||
777 | .un_reset = heathrow_mb_un_reset, | ||
778 | .un_reset_ide = heathrow_mb_un_reset_ide, | ||
779 | }; | ||
780 | |||
781 | static struct mb_ops keylargo_mb_ops __pmacdata = { | ||
782 | .name = "KeyLargo", | ||
783 | .init = keylargo_mb_init, | ||
784 | .content = keylargo_mb_content, | ||
785 | .power = keylargo_mb_power, | ||
786 | .setup_bus = keylargo_mb_setup_bus, | ||
787 | .un_reset = keylargo_mb_un_reset, | ||
788 | .un_reset_ide = keylargo_mb_un_reset_ide, | ||
789 | }; | ||
790 | |||
791 | /* | ||
792 | * It seems that the bit for the media-bay interrupt in the IRQ_LEVEL | ||
793 | * register is always set when there is something in the media bay. | ||
794 | * This causes problems for the interrupt code if we attach an interrupt | ||
795 | * handler to the media-bay interrupt, because it tends to go into | ||
796 | * an infinite loop calling the media bay interrupt handler. | ||
797 | * Therefore we do it all by polling the media bay once each tick. | ||
798 | */ | ||
799 | |||
800 | static struct of_match media_bay_match[] = | ||
801 | { | ||
802 | { | ||
803 | .name = "media-bay", | ||
804 | .type = OF_ANY_MATCH, | ||
805 | .compatible = "keylargo-media-bay", | ||
806 | .data = &keylargo_mb_ops, | ||
807 | }, | ||
808 | { | ||
809 | .name = "media-bay", | ||
810 | .type = OF_ANY_MATCH, | ||
811 | .compatible = "heathrow-media-bay", | ||
812 | .data = &heathrow_mb_ops, | ||
813 | }, | ||
814 | { | ||
815 | .name = "media-bay", | ||
816 | .type = OF_ANY_MATCH, | ||
817 | .compatible = "ohare-media-bay", | ||
818 | .data = &ohare_mb_ops, | ||
819 | }, | ||
820 | {}, | ||
821 | }; | ||
822 | |||
823 | static struct macio_driver media_bay_driver = | ||
824 | { | ||
825 | .name = "media-bay", | ||
826 | .match_table = media_bay_match, | ||
827 | .probe = media_bay_attach, | ||
828 | .suspend = media_bay_suspend, | ||
829 | .resume = media_bay_resume | ||
830 | }; | ||
831 | |||
832 | static int __init media_bay_init(void) | ||
833 | { | ||
834 | int i; | ||
835 | |||
836 | for (i=0; i<MAX_BAYS; i++) { | ||
837 | memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info)); | ||
838 | media_bays[i].content_id = -1; | ||
839 | #ifdef CONFIG_BLK_DEV_IDE | ||
840 | media_bays[i].cd_index = -1; | ||
841 | #endif | ||
842 | } | ||
843 | if (_machine != _MACH_Pmac) | ||
844 | return -ENODEV; | ||
845 | |||
846 | macio_register_driver(&media_bay_driver); | ||
847 | |||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | device_initcall(media_bay_init); | ||
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c new file mode 100644 index 000000000000..30791875fc97 --- /dev/null +++ b/drivers/macintosh/nvram.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * /dev/nvram driver for Power Macintosh. | ||
3 | */ | ||
4 | |||
5 | #define NVRAM_VERSION "1.0" | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/miscdevice.h> | ||
13 | #include <linux/fcntl.h> | ||
14 | #include <linux/nvram.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/smp_lock.h> | ||
17 | #include <asm/uaccess.h> | ||
18 | #include <asm/nvram.h> | ||
19 | |||
20 | #define NVRAM_SIZE 8192 | ||
21 | |||
22 | static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) | ||
23 | { | ||
24 | lock_kernel(); | ||
25 | switch (origin) { | ||
26 | case 1: | ||
27 | offset += file->f_pos; | ||
28 | break; | ||
29 | case 2: | ||
30 | offset += NVRAM_SIZE; | ||
31 | break; | ||
32 | } | ||
33 | if (offset < 0) { | ||
34 | unlock_kernel(); | ||
35 | return -EINVAL; | ||
36 | } | ||
37 | file->f_pos = offset; | ||
38 | unlock_kernel(); | ||
39 | return file->f_pos; | ||
40 | } | ||
41 | |||
42 | static ssize_t read_nvram(struct file *file, char __user *buf, | ||
43 | size_t count, loff_t *ppos) | ||
44 | { | ||
45 | unsigned int i; | ||
46 | char __user *p = buf; | ||
47 | |||
48 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
49 | return -EFAULT; | ||
50 | if (*ppos >= NVRAM_SIZE) | ||
51 | return 0; | ||
52 | for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) | ||
53 | if (__put_user(nvram_read_byte(i), p)) | ||
54 | return -EFAULT; | ||
55 | *ppos = i; | ||
56 | return p - buf; | ||
57 | } | ||
58 | |||
59 | static ssize_t write_nvram(struct file *file, const char __user *buf, | ||
60 | size_t count, loff_t *ppos) | ||
61 | { | ||
62 | unsigned int i; | ||
63 | const char __user *p = buf; | ||
64 | char c; | ||
65 | |||
66 | if (!access_ok(VERIFY_READ, buf, count)) | ||
67 | return -EFAULT; | ||
68 | if (*ppos >= NVRAM_SIZE) | ||
69 | return 0; | ||
70 | for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) { | ||
71 | if (__get_user(c, p)) | ||
72 | return -EFAULT; | ||
73 | nvram_write_byte(c, i); | ||
74 | } | ||
75 | *ppos = i; | ||
76 | return p - buf; | ||
77 | } | ||
78 | |||
79 | static int nvram_ioctl(struct inode *inode, struct file *file, | ||
80 | unsigned int cmd, unsigned long arg) | ||
81 | { | ||
82 | switch(cmd) { | ||
83 | case PMAC_NVRAM_GET_OFFSET: | ||
84 | { | ||
85 | int part, offset; | ||
86 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) | ||
87 | return -EFAULT; | ||
88 | if (part < pmac_nvram_OF || part > pmac_nvram_NR) | ||
89 | return -EINVAL; | ||
90 | offset = pmac_get_partition(part); | ||
91 | if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0) | ||
92 | return -EFAULT; | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | default: | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | struct file_operations nvram_fops = { | ||
104 | .owner = THIS_MODULE, | ||
105 | .llseek = nvram_llseek, | ||
106 | .read = read_nvram, | ||
107 | .write = write_nvram, | ||
108 | .ioctl = nvram_ioctl, | ||
109 | }; | ||
110 | |||
111 | static struct miscdevice nvram_dev = { | ||
112 | NVRAM_MINOR, | ||
113 | "nvram", | ||
114 | &nvram_fops | ||
115 | }; | ||
116 | |||
117 | int __init nvram_init(void) | ||
118 | { | ||
119 | printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", | ||
120 | NVRAM_VERSION); | ||
121 | return misc_register(&nvram_dev); | ||
122 | } | ||
123 | |||
124 | void __exit nvram_cleanup(void) | ||
125 | { | ||
126 | misc_deregister( &nvram_dev ); | ||
127 | } | ||
128 | |||
129 | module_init(nvram_init); | ||
130 | module_exit(nvram_cleanup); | ||
131 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c new file mode 100644 index 000000000000..fb535737d17d --- /dev/null +++ b/drivers/macintosh/smu.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * PowerMac G5 SMU driver | ||
3 | * | ||
4 | * Copyright 2004 J. Mayer <l_indien@magic.fr> | ||
5 | * Copyright 2005 Benjamin Herrenschmidt, IBM Corp. | ||
6 | * | ||
7 | * Released under the term of the GNU GPL v2. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * For now, this driver includes: | ||
12 | * - RTC get & set | ||
13 | * - reboot & shutdown commands | ||
14 | * all synchronous with IRQ disabled (ugh) | ||
15 | * | ||
16 | * TODO: | ||
17 | * rework in a way the PMU driver works, that is asynchronous | ||
18 | * with a queue of commands. I'll do that as soon as I have an | ||
19 | * SMU based machine at hand. Some more cleanup is needed too, | ||
20 | * like maybe fitting it into a platform device, etc... | ||
21 | * Also check what's up with cache coherency, and if we really | ||
22 | * can't do better than flushing the cache, maybe build a table | ||
23 | * of command len/reply len like the PMU driver to only flush | ||
24 | * what is actually necessary. | ||
25 | * --BenH. | ||
26 | */ | ||
27 | |||
28 | #include <linux/config.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/dmapool.h> | ||
33 | #include <linux/bootmem.h> | ||
34 | #include <linux/vmalloc.h> | ||
35 | #include <linux/highmem.h> | ||
36 | #include <linux/jiffies.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/rtc.h> | ||
39 | |||
40 | #include <asm/byteorder.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/prom.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/pmac_feature.h> | ||
45 | #include <asm/smu.h> | ||
46 | #include <asm/sections.h> | ||
47 | #include <asm/abs_addr.h> | ||
48 | |||
49 | #define DEBUG_SMU 1 | ||
50 | |||
51 | #ifdef DEBUG_SMU | ||
52 | #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) | ||
53 | #else | ||
54 | #define DPRINTK(fmt, args...) do { } while (0) | ||
55 | #endif | ||
56 | |||
57 | /* | ||
58 | * This is the command buffer passed to the SMU hardware | ||
59 | */ | ||
60 | struct smu_cmd_buf { | ||
61 | u8 cmd; | ||
62 | u8 length; | ||
63 | u8 data[0x0FFE]; | ||
64 | }; | ||
65 | |||
66 | struct smu_device { | ||
67 | spinlock_t lock; | ||
68 | struct device_node *of_node; | ||
69 | int db_ack; /* doorbell ack GPIO */ | ||
70 | int db_req; /* doorbell req GPIO */ | ||
71 | u32 __iomem *db_buf; /* doorbell buffer */ | ||
72 | struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ | ||
73 | u32 cmd_buf_abs; /* command buffer absolute */ | ||
74 | }; | ||
75 | |||
76 | /* | ||
77 | * I don't think there will ever be more than one SMU, so | ||
78 | * for now, just hard code that | ||
79 | */ | ||
80 | static struct smu_device *smu; | ||
81 | |||
82 | /* | ||
83 | * SMU low level communication stuff | ||
84 | */ | ||
85 | static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack) | ||
86 | { | ||
87 | rmb(); | ||
88 | return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0; | ||
89 | } | ||
90 | |||
91 | static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf) | ||
92 | { | ||
93 | return (~cmd_buf->cmd) & 0xff; | ||
94 | } | ||
95 | |||
96 | static void smu_send_cmd(struct smu_device *dev) | ||
97 | { | ||
98 | /* SMU command buf is currently cacheable, we need a physical | ||
99 | * address. This isn't exactly a DMA mapping here, I suspect | ||
100 | * the SMU is actually communicating with us via i2c to the | ||
101 | * northbridge or the CPU to access RAM. | ||
102 | */ | ||
103 | writel(dev->cmd_buf_abs, dev->db_buf); | ||
104 | |||
105 | /* Ring the SMU doorbell */ | ||
106 | pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4); | ||
107 | pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4); | ||
108 | } | ||
109 | |||
110 | static int smu_cmd_done(struct smu_device *dev) | ||
111 | { | ||
112 | unsigned long wait = 0; | ||
113 | int gpio; | ||
114 | |||
115 | /* Check the SMU doorbell */ | ||
116 | do { | ||
117 | gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, | ||
118 | NULL, dev->db_ack); | ||
119 | if ((gpio & 7) == 7) | ||
120 | return 0; | ||
121 | udelay(100); | ||
122 | } while(++wait < 10000); | ||
123 | |||
124 | printk(KERN_ERR "SMU timeout !\n"); | ||
125 | return -ENXIO; | ||
126 | } | ||
127 | |||
128 | static int smu_do_cmd(struct smu_device *dev) | ||
129 | { | ||
130 | int rc; | ||
131 | u8 cmd_ack; | ||
132 | |||
133 | DPRINTK("SMU do_cmd %02x len=%d %02x\n", | ||
134 | dev->cmd_buf->cmd, dev->cmd_buf->length, | ||
135 | dev->cmd_buf->data[0]); | ||
136 | |||
137 | cmd_ack = smu_save_ack_cmd(dev->cmd_buf); | ||
138 | |||
139 | /* Clear cmd_buf cache lines */ | ||
140 | flush_inval_dcache_range((unsigned long)dev->cmd_buf, | ||
141 | ((unsigned long)dev->cmd_buf) + | ||
142 | sizeof(struct smu_cmd_buf)); | ||
143 | smu_send_cmd(dev); | ||
144 | rc = smu_cmd_done(dev); | ||
145 | if (rc == 0) | ||
146 | rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1; | ||
147 | |||
148 | DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n", | ||
149 | dev->cmd_buf->cmd, dev->cmd_buf->length, | ||
150 | dev->cmd_buf->data[0], rc, cmd_ack); | ||
151 | |||
152 | return rc; | ||
153 | } | ||
154 | |||
155 | /* RTC low level commands */ | ||
156 | static inline int bcd2hex (int n) | ||
157 | { | ||
158 | return (((n & 0xf0) >> 4) * 10) + (n & 0xf); | ||
159 | } | ||
160 | |||
161 | static inline int hex2bcd (int n) | ||
162 | { | ||
163 | return ((n / 10) << 4) + (n % 10); | ||
164 | } | ||
165 | |||
166 | #if 0 | ||
167 | static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) | ||
168 | { | ||
169 | cmd_buf->cmd = 0x8e; | ||
170 | cmd_buf->length = 8; | ||
171 | cmd_buf->data[0] = 0x00; | ||
172 | memset(cmd_buf->data + 1, 0, 7); | ||
173 | } | ||
174 | |||
175 | static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) | ||
176 | { | ||
177 | cmd_buf->cmd = 0x8e; | ||
178 | cmd_buf->length = 1; | ||
179 | cmd_buf->data[0] = 0x01; | ||
180 | } | ||
181 | |||
182 | static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) | ||
183 | { | ||
184 | cmd_buf->cmd = 0x8e; | ||
185 | cmd_buf->length = 1; | ||
186 | cmd_buf->data[0] = 0x02; | ||
187 | } | ||
188 | #endif | ||
189 | |||
190 | static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf, | ||
191 | struct rtc_time *time) | ||
192 | { | ||
193 | cmd_buf->cmd = 0x8e; | ||
194 | cmd_buf->length = 8; | ||
195 | cmd_buf->data[0] = 0x80; | ||
196 | cmd_buf->data[1] = hex2bcd(time->tm_sec); | ||
197 | cmd_buf->data[2] = hex2bcd(time->tm_min); | ||
198 | cmd_buf->data[3] = hex2bcd(time->tm_hour); | ||
199 | cmd_buf->data[4] = time->tm_wday; | ||
200 | cmd_buf->data[5] = hex2bcd(time->tm_mday); | ||
201 | cmd_buf->data[6] = hex2bcd(time->tm_mon) + 1; | ||
202 | cmd_buf->data[7] = hex2bcd(time->tm_year - 100); | ||
203 | } | ||
204 | |||
205 | static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf) | ||
206 | { | ||
207 | cmd_buf->cmd = 0x8e; | ||
208 | cmd_buf->length = 1; | ||
209 | cmd_buf->data[0] = 0x81; | ||
210 | } | ||
211 | |||
212 | static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf, | ||
213 | struct rtc_time *time) | ||
214 | { | ||
215 | time->tm_sec = bcd2hex(cmd_buf->data[0]); | ||
216 | time->tm_min = bcd2hex(cmd_buf->data[1]); | ||
217 | time->tm_hour = bcd2hex(cmd_buf->data[2]); | ||
218 | time->tm_wday = bcd2hex(cmd_buf->data[3]); | ||
219 | time->tm_mday = bcd2hex(cmd_buf->data[4]); | ||
220 | time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1; | ||
221 | time->tm_year = bcd2hex(cmd_buf->data[6]) + 100; | ||
222 | } | ||
223 | |||
224 | int smu_get_rtc_time(struct rtc_time *time) | ||
225 | { | ||
226 | unsigned long flags; | ||
227 | int rc; | ||
228 | |||
229 | if (smu == NULL) | ||
230 | return -ENODEV; | ||
231 | |||
232 | memset(time, 0, sizeof(struct rtc_time)); | ||
233 | spin_lock_irqsave(&smu->lock, flags); | ||
234 | smu_fill_get_rtc_cmd(smu->cmd_buf); | ||
235 | rc = smu_do_cmd(smu); | ||
236 | if (rc == 0) | ||
237 | smu_parse_get_rtc_reply(smu->cmd_buf, time); | ||
238 | spin_unlock_irqrestore(&smu->lock, flags); | ||
239 | |||
240 | return rc; | ||
241 | } | ||
242 | |||
243 | int smu_set_rtc_time(struct rtc_time *time) | ||
244 | { | ||
245 | unsigned long flags; | ||
246 | int rc; | ||
247 | |||
248 | if (smu == NULL) | ||
249 | return -ENODEV; | ||
250 | |||
251 | spin_lock_irqsave(&smu->lock, flags); | ||
252 | smu_fill_set_rtc_cmd(smu->cmd_buf, time); | ||
253 | rc = smu_do_cmd(smu); | ||
254 | spin_unlock_irqrestore(&smu->lock, flags); | ||
255 | |||
256 | return rc; | ||
257 | } | ||
258 | |||
259 | void smu_shutdown(void) | ||
260 | { | ||
261 | const unsigned char *command = "SHUTDOWN"; | ||
262 | unsigned long flags; | ||
263 | |||
264 | if (smu == NULL) | ||
265 | return; | ||
266 | |||
267 | spin_lock_irqsave(&smu->lock, flags); | ||
268 | smu->cmd_buf->cmd = 0xaa; | ||
269 | smu->cmd_buf->length = strlen(command); | ||
270 | strcpy(smu->cmd_buf->data, command); | ||
271 | smu_do_cmd(smu); | ||
272 | for (;;) | ||
273 | ; | ||
274 | spin_unlock_irqrestore(&smu->lock, flags); | ||
275 | } | ||
276 | |||
277 | void smu_restart(void) | ||
278 | { | ||
279 | const unsigned char *command = "RESTART"; | ||
280 | unsigned long flags; | ||
281 | |||
282 | if (smu == NULL) | ||
283 | return; | ||
284 | |||
285 | spin_lock_irqsave(&smu->lock, flags); | ||
286 | smu->cmd_buf->cmd = 0xaa; | ||
287 | smu->cmd_buf->length = strlen(command); | ||
288 | strcpy(smu->cmd_buf->data, command); | ||
289 | smu_do_cmd(smu); | ||
290 | for (;;) | ||
291 | ; | ||
292 | spin_unlock_irqrestore(&smu->lock, flags); | ||
293 | } | ||
294 | |||
295 | int smu_present(void) | ||
296 | { | ||
297 | return smu != NULL; | ||
298 | } | ||
299 | |||
300 | |||
301 | int smu_init (void) | ||
302 | { | ||
303 | struct device_node *np; | ||
304 | u32 *data; | ||
305 | |||
306 | np = of_find_node_by_type(NULL, "smu"); | ||
307 | if (np == NULL) | ||
308 | return -ENODEV; | ||
309 | |||
310 | if (smu_cmdbuf_abs == 0) { | ||
311 | printk(KERN_ERR "SMU: Command buffer not allocated !\n"); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | smu = alloc_bootmem(sizeof(struct smu_device)); | ||
316 | if (smu == NULL) | ||
317 | return -ENOMEM; | ||
318 | memset(smu, 0, sizeof(*smu)); | ||
319 | |||
320 | spin_lock_init(&smu->lock); | ||
321 | smu->of_node = np; | ||
322 | /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a | ||
323 | * 32 bits value safely | ||
324 | */ | ||
325 | smu->cmd_buf_abs = (u32)smu_cmdbuf_abs; | ||
326 | smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs); | ||
327 | |||
328 | np = of_find_node_by_name(NULL, "smu-doorbell"); | ||
329 | if (np == NULL) { | ||
330 | printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); | ||
331 | goto fail; | ||
332 | } | ||
333 | data = (u32 *)get_property(np, "reg", NULL); | ||
334 | of_node_put(np); | ||
335 | if (data == NULL) { | ||
336 | printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); | ||
337 | goto fail; | ||
338 | } | ||
339 | |||
340 | /* Current setup has one doorbell GPIO that does both doorbell | ||
341 | * and ack. GPIOs are at 0x50, best would be to find that out | ||
342 | * in the device-tree though. | ||
343 | */ | ||
344 | smu->db_req = 0x50 + *data; | ||
345 | smu->db_ack = 0x50 + *data; | ||
346 | |||
347 | /* Doorbell buffer is currently hard-coded, I didn't find a proper | ||
348 | * device-tree entry giving the address. Best would probably to use | ||
349 | * an offset for K2 base though, but let's do it that way for now. | ||
350 | */ | ||
351 | smu->db_buf = ioremap(0x8000860c, 0x1000); | ||
352 | if (smu->db_buf == NULL) { | ||
353 | printk(KERN_ERR "SMU: Can't map doorbell buffer pointer !\n"); | ||
354 | goto fail; | ||
355 | } | ||
356 | |||
357 | sys_ctrler = SYS_CTRLER_SMU; | ||
358 | return 0; | ||
359 | |||
360 | fail: | ||
361 | smu = NULL; | ||
362 | return -ENXIO; | ||
363 | |||
364 | } | ||
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c new file mode 100644 index 000000000000..e0ac63effa55 --- /dev/null +++ b/drivers/macintosh/therm_adt746x.c | |||
@@ -0,0 +1,612 @@ | |||
1 | /* | ||
2 | * Device driver for the i2c thermostat found on the iBook G4, Albook G4 | ||
3 | * | ||
4 | * Copyright (C) 2003, 2004 Colin Leroy, Rasmus Rohde, Benjamin Herrenschmidt | ||
5 | * | ||
6 | * Documentation from | ||
7 | * http://www.analog.com/UploadedFiles/Data_Sheets/115254175ADT7467_pra.pdf | ||
8 | * http://www.analog.com/UploadedFiles/Data_Sheets/3686221171167ADT7460_b.pdf | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/wait.h> | ||
25 | #include <linux/suspend.h> | ||
26 | #include <linux/kthread.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | |||
29 | #include <asm/prom.h> | ||
30 | #include <asm/machdep.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/sections.h> | ||
34 | #include <asm/of_device.h> | ||
35 | |||
36 | #undef DEBUG | ||
37 | |||
38 | #define CONFIG_REG 0x40 | ||
39 | #define MANUAL_MASK 0xe0 | ||
40 | #define AUTO_MASK 0x20 | ||
41 | |||
42 | static u8 TEMP_REG[3] = {0x26, 0x25, 0x27}; /* local, cpu, gpu */ | ||
43 | static u8 LIMIT_REG[3] = {0x6b, 0x6a, 0x6c}; /* local, cpu, gpu */ | ||
44 | static u8 MANUAL_MODE[2] = {0x5c, 0x5d}; | ||
45 | static u8 REM_CONTROL[2] = {0x00, 0x40}; | ||
46 | static u8 FAN_SPEED[2] = {0x28, 0x2a}; | ||
47 | static u8 FAN_SPD_SET[2] = {0x30, 0x31}; | ||
48 | |||
49 | static u8 default_limits_local[3] = {70, 50, 70}; /* local, cpu, gpu */ | ||
50 | static u8 default_limits_chip[3] = {80, 65, 80}; /* local, cpu, gpu */ | ||
51 | |||
52 | static int limit_adjust = 0; | ||
53 | static int fan_speed = -1; | ||
54 | |||
55 | MODULE_AUTHOR("Colin Leroy <colin@colino.net>"); | ||
56 | MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and " | ||
57 | "Powerbook G4 Alu"); | ||
58 | MODULE_LICENSE("GPL"); | ||
59 | |||
60 | module_param(limit_adjust, int, 0644); | ||
61 | MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) " | ||
62 | "by N degrees."); | ||
63 | |||
64 | module_param(fan_speed, int, 0644); | ||
65 | MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) " | ||
66 | "(default 64)"); | ||
67 | |||
68 | struct thermostat { | ||
69 | struct i2c_client clt; | ||
70 | u8 temps[3]; | ||
71 | u8 cached_temp[3]; | ||
72 | u8 initial_limits[3]; | ||
73 | u8 limits[3]; | ||
74 | int last_speed[2]; | ||
75 | int last_var[2]; | ||
76 | }; | ||
77 | |||
78 | static enum {ADT7460, ADT7467} therm_type; | ||
79 | static int therm_bus, therm_address; | ||
80 | static struct of_device * of_dev; | ||
81 | static struct thermostat* thermostat; | ||
82 | static struct task_struct *thread_therm = NULL; | ||
83 | |||
84 | static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, | ||
85 | int busno); | ||
86 | |||
87 | static void write_both_fan_speed(struct thermostat *th, int speed); | ||
88 | static void write_fan_speed(struct thermostat *th, int speed, int fan); | ||
89 | |||
90 | static int | ||
91 | write_reg(struct thermostat* th, int reg, u8 data) | ||
92 | { | ||
93 | u8 tmp[2]; | ||
94 | int rc; | ||
95 | |||
96 | tmp[0] = reg; | ||
97 | tmp[1] = data; | ||
98 | rc = i2c_master_send(&th->clt, (const char *)tmp, 2); | ||
99 | if (rc < 0) | ||
100 | return rc; | ||
101 | if (rc != 2) | ||
102 | return -ENODEV; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int | ||
107 | read_reg(struct thermostat* th, int reg) | ||
108 | { | ||
109 | u8 reg_addr, data; | ||
110 | int rc; | ||
111 | |||
112 | reg_addr = (u8)reg; | ||
113 | rc = i2c_master_send(&th->clt, ®_addr, 1); | ||
114 | if (rc < 0) | ||
115 | return rc; | ||
116 | if (rc != 1) | ||
117 | return -ENODEV; | ||
118 | rc = i2c_master_recv(&th->clt, (char *)&data, 1); | ||
119 | if (rc < 0) | ||
120 | return rc; | ||
121 | return data; | ||
122 | } | ||
123 | |||
124 | static int | ||
125 | attach_thermostat(struct i2c_adapter *adapter) | ||
126 | { | ||
127 | unsigned long bus_no; | ||
128 | |||
129 | if (strncmp(adapter->name, "uni-n", 5)) | ||
130 | return -ENODEV; | ||
131 | bus_no = simple_strtoul(adapter->name + 6, NULL, 10); | ||
132 | if (bus_no != therm_bus) | ||
133 | return -ENODEV; | ||
134 | return attach_one_thermostat(adapter, therm_address, bus_no); | ||
135 | } | ||
136 | |||
137 | static int | ||
138 | detach_thermostat(struct i2c_adapter *adapter) | ||
139 | { | ||
140 | struct thermostat* th; | ||
141 | int i; | ||
142 | |||
143 | if (thermostat == NULL) | ||
144 | return 0; | ||
145 | |||
146 | th = thermostat; | ||
147 | |||
148 | if (thread_therm != NULL) { | ||
149 | kthread_stop(thread_therm); | ||
150 | } | ||
151 | |||
152 | printk(KERN_INFO "adt746x: Putting max temperatures back from " | ||
153 | "%d, %d, %d to %d, %d, %d\n", | ||
154 | th->limits[0], th->limits[1], th->limits[2], | ||
155 | th->initial_limits[0], th->initial_limits[1], | ||
156 | th->initial_limits[2]); | ||
157 | |||
158 | for (i = 0; i < 3; i++) | ||
159 | write_reg(th, LIMIT_REG[i], th->initial_limits[i]); | ||
160 | |||
161 | write_both_fan_speed(th, -1); | ||
162 | |||
163 | i2c_detach_client(&th->clt); | ||
164 | |||
165 | thermostat = NULL; | ||
166 | |||
167 | kfree(th); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct i2c_driver thermostat_driver = { | ||
173 | .owner = THIS_MODULE, | ||
174 | .name = "therm_adt746x", | ||
175 | .flags = I2C_DF_NOTIFY, | ||
176 | .attach_adapter = attach_thermostat, | ||
177 | .detach_adapter = detach_thermostat, | ||
178 | }; | ||
179 | |||
180 | static int read_fan_speed(struct thermostat *th, u8 addr) | ||
181 | { | ||
182 | u8 tmp[2]; | ||
183 | u16 res; | ||
184 | |||
185 | /* should start with low byte */ | ||
186 | tmp[1] = read_reg(th, addr); | ||
187 | tmp[0] = read_reg(th, addr + 1); | ||
188 | |||
189 | res = tmp[1] + (tmp[0] << 8); | ||
190 | /* "a value of 0xffff means that the fan has stopped" */ | ||
191 | return (res == 0xffff ? 0 : (90000*60)/res); | ||
192 | } | ||
193 | |||
194 | static void write_both_fan_speed(struct thermostat *th, int speed) | ||
195 | { | ||
196 | write_fan_speed(th, speed, 0); | ||
197 | if (therm_type == ADT7460) | ||
198 | write_fan_speed(th, speed, 1); | ||
199 | } | ||
200 | |||
201 | static void write_fan_speed(struct thermostat *th, int speed, int fan) | ||
202 | { | ||
203 | u8 manual; | ||
204 | |||
205 | if (speed > 0xff) | ||
206 | speed = 0xff; | ||
207 | else if (speed < -1) | ||
208 | speed = 0; | ||
209 | |||
210 | if (therm_type == ADT7467 && fan == 1) | ||
211 | return; | ||
212 | |||
213 | if (th->last_speed[fan] != speed) { | ||
214 | if (speed == -1) | ||
215 | printk(KERN_DEBUG "adt746x: Setting speed to automatic " | ||
216 | "for %s fan.\n", fan?"GPU":"CPU"); | ||
217 | else | ||
218 | printk(KERN_DEBUG "adt746x: Setting speed to %d " | ||
219 | "for %s fan.\n", speed, fan?"GPU":"CPU"); | ||
220 | } else | ||
221 | return; | ||
222 | |||
223 | if (speed >= 0) { | ||
224 | manual = read_reg(th, MANUAL_MODE[fan]); | ||
225 | write_reg(th, MANUAL_MODE[fan], manual|MANUAL_MASK); | ||
226 | write_reg(th, FAN_SPD_SET[fan], speed); | ||
227 | } else { | ||
228 | /* back to automatic */ | ||
229 | if(therm_type == ADT7460) { | ||
230 | manual = read_reg(th, | ||
231 | MANUAL_MODE[fan]) & (~MANUAL_MASK); | ||
232 | |||
233 | write_reg(th, | ||
234 | MANUAL_MODE[fan], manual|REM_CONTROL[fan]); | ||
235 | } else { | ||
236 | manual = read_reg(th, MANUAL_MODE[fan]); | ||
237 | write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK)); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | th->last_speed[fan] = speed; | ||
242 | } | ||
243 | |||
244 | static void read_sensors(struct thermostat *th) | ||
245 | { | ||
246 | int i = 0; | ||
247 | |||
248 | for (i = 0; i < 3; i++) | ||
249 | th->temps[i] = read_reg(th, TEMP_REG[i]); | ||
250 | } | ||
251 | |||
252 | #ifdef DEBUG | ||
253 | static void display_stats(struct thermostat *th) | ||
254 | { | ||
255 | if (th->temps[0] != th->cached_temp[0] | ||
256 | || th->temps[1] != th->cached_temp[1] | ||
257 | || th->temps[2] != th->cached_temp[2]) { | ||
258 | printk(KERN_INFO "adt746x: Temperature infos:" | ||
259 | " thermostats: %d,%d,%d;" | ||
260 | " limits: %d,%d,%d;" | ||
261 | " fan speed: %d RPM\n", | ||
262 | th->temps[0], th->temps[1], th->temps[2], | ||
263 | th->limits[0], th->limits[1], th->limits[2], | ||
264 | read_fan_speed(th, FAN_SPEED[0])); | ||
265 | } | ||
266 | th->cached_temp[0] = th->temps[0]; | ||
267 | th->cached_temp[1] = th->temps[1]; | ||
268 | th->cached_temp[2] = th->temps[2]; | ||
269 | } | ||
270 | #endif | ||
271 | |||
272 | static void update_fans_speed (struct thermostat *th) | ||
273 | { | ||
274 | int lastvar = 0; /* last variation, for iBook */ | ||
275 | int i = 0; | ||
276 | |||
277 | /* we don't care about local sensor, so we start at sensor 1 */ | ||
278 | for (i = 1; i < 3; i++) { | ||
279 | int started = 0; | ||
280 | int fan_number = (therm_type == ADT7460 && i == 2); | ||
281 | int var = th->temps[i] - th->limits[i]; | ||
282 | |||
283 | if (var > -1) { | ||
284 | int step = (255 - fan_speed) / 7; | ||
285 | int new_speed = 0; | ||
286 | |||
287 | /* hysteresis : change fan speed only if variation is | ||
288 | * more than two degrees */ | ||
289 | if (abs(var - th->last_var[fan_number]) < 2) | ||
290 | continue; | ||
291 | |||
292 | started = 1; | ||
293 | new_speed = fan_speed + ((var-1)*step); | ||
294 | |||
295 | if (new_speed < fan_speed) | ||
296 | new_speed = fan_speed; | ||
297 | if (new_speed > 255) | ||
298 | new_speed = 255; | ||
299 | |||
300 | printk(KERN_DEBUG "adt746x: setting fans speed to %d " | ||
301 | "(limit exceeded by %d on %s) \n", | ||
302 | new_speed, var, | ||
303 | fan_number?"GPU/pwr":"CPU"); | ||
304 | write_both_fan_speed(th, new_speed); | ||
305 | th->last_var[fan_number] = var; | ||
306 | } else if (var < -2) { | ||
307 | /* don't stop fan if GPU/power is cold and CPU is not | ||
308 | * so cold (lastvar >= -1) */ | ||
309 | if (i == 2 && lastvar < -1) { | ||
310 | if (th->last_speed[fan_number] != 0) | ||
311 | printk(KERN_DEBUG "adt746x: Stopping " | ||
312 | "fans.\n"); | ||
313 | write_both_fan_speed(th, 0); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | lastvar = var; | ||
318 | |||
319 | if (started) | ||
320 | return; /* we don't want to re-stop the fan | ||
321 | * if CPU is heating and GPU/power is not */ | ||
322 | } | ||
323 | } | ||
324 | |||
325 | static int monitor_task(void *arg) | ||
326 | { | ||
327 | struct thermostat* th = arg; | ||
328 | |||
329 | while(!kthread_should_stop()) { | ||
330 | if (current->flags & PF_FREEZE) | ||
331 | refrigerator(PF_FREEZE); | ||
332 | |||
333 | msleep_interruptible(2000); | ||
334 | |||
335 | #ifndef DEBUG | ||
336 | if (fan_speed != -1) | ||
337 | read_sensors(th); | ||
338 | #else | ||
339 | read_sensors(th); | ||
340 | #endif | ||
341 | |||
342 | if (fan_speed != -1) | ||
343 | update_fans_speed(th); | ||
344 | |||
345 | #ifdef DEBUG | ||
346 | display_stats(th); | ||
347 | #endif | ||
348 | |||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static void set_limit(struct thermostat *th, int i) | ||
355 | { | ||
356 | /* Set CPU limit higher to avoid powerdowns */ | ||
357 | th->limits[i] = default_limits_chip[i] + limit_adjust; | ||
358 | write_reg(th, LIMIT_REG[i], th->limits[i]); | ||
359 | |||
360 | /* set our limits to normal */ | ||
361 | th->limits[i] = default_limits_local[i] + limit_adjust; | ||
362 | } | ||
363 | |||
364 | static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, | ||
365 | int busno) | ||
366 | { | ||
367 | struct thermostat* th; | ||
368 | int rc; | ||
369 | int i; | ||
370 | |||
371 | if (thermostat) | ||
372 | return 0; | ||
373 | |||
374 | th = (struct thermostat *) | ||
375 | kmalloc(sizeof(struct thermostat), GFP_KERNEL); | ||
376 | |||
377 | if (!th) | ||
378 | return -ENOMEM; | ||
379 | |||
380 | memset(th, 0, sizeof(*th)); | ||
381 | th->clt.addr = addr; | ||
382 | th->clt.adapter = adapter; | ||
383 | th->clt.driver = &thermostat_driver; | ||
384 | strcpy(th->clt.name, "thermostat"); | ||
385 | |||
386 | rc = read_reg(th, 0); | ||
387 | if (rc < 0) { | ||
388 | printk(KERN_ERR "adt746x: Thermostat failed to read config " | ||
389 | "from bus %d !\n", | ||
390 | busno); | ||
391 | kfree(th); | ||
392 | return -ENODEV; | ||
393 | } | ||
394 | |||
395 | /* force manual control to start the fan quieter */ | ||
396 | if (fan_speed == -1) | ||
397 | fan_speed = 64; | ||
398 | |||
399 | if(therm_type == ADT7460) { | ||
400 | printk(KERN_INFO "adt746x: ADT7460 initializing\n"); | ||
401 | /* The 7460 needs to be started explicitly */ | ||
402 | write_reg(th, CONFIG_REG, 1); | ||
403 | } else | ||
404 | printk(KERN_INFO "adt746x: ADT7467 initializing\n"); | ||
405 | |||
406 | for (i = 0; i < 3; i++) { | ||
407 | th->initial_limits[i] = read_reg(th, LIMIT_REG[i]); | ||
408 | set_limit(th, i); | ||
409 | } | ||
410 | |||
411 | printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d" | ||
412 | " to %d, %d, %d\n", | ||
413 | th->initial_limits[0], th->initial_limits[1], | ||
414 | th->initial_limits[2], th->limits[0], th->limits[1], | ||
415 | th->limits[2]); | ||
416 | |||
417 | thermostat = th; | ||
418 | |||
419 | if (i2c_attach_client(&th->clt)) { | ||
420 | printk(KERN_INFO "adt746x: Thermostat failed to attach " | ||
421 | "client !\n"); | ||
422 | thermostat = NULL; | ||
423 | kfree(th); | ||
424 | return -ENODEV; | ||
425 | } | ||
426 | |||
427 | /* be sure to really write fan speed the first time */ | ||
428 | th->last_speed[0] = -2; | ||
429 | th->last_speed[1] = -2; | ||
430 | th->last_var[0] = -80; | ||
431 | th->last_var[1] = -80; | ||
432 | |||
433 | if (fan_speed != -1) { | ||
434 | /* manual mode, stop fans */ | ||
435 | write_both_fan_speed(th, 0); | ||
436 | } else { | ||
437 | /* automatic mode */ | ||
438 | write_both_fan_speed(th, -1); | ||
439 | } | ||
440 | |||
441 | thread_therm = kthread_run(monitor_task, th, "kfand"); | ||
442 | |||
443 | if (thread_therm == ERR_PTR(-ENOMEM)) { | ||
444 | printk(KERN_INFO "adt746x: Kthread creation failed\n"); | ||
445 | thread_therm = NULL; | ||
446 | return -ENOMEM; | ||
447 | } | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | * Now, unfortunately, sysfs doesn't give us a nice void * we could | ||
454 | * pass around to the attribute functions, so we don't really have | ||
455 | * choice but implement a bunch of them... | ||
456 | * | ||
457 | */ | ||
458 | #define BUILD_SHOW_FUNC_INT(name, data) \ | ||
459 | static ssize_t show_##name(struct device *dev, char *buf) \ | ||
460 | { \ | ||
461 | return sprintf(buf, "%d\n", data); \ | ||
462 | } | ||
463 | |||
464 | #define BUILD_SHOW_FUNC_FAN(name, data) \ | ||
465 | static ssize_t show_##name(struct device *dev, char *buf) \ | ||
466 | { \ | ||
467 | return sprintf(buf, "%d (%d rpm)\n", \ | ||
468 | thermostat->last_speed[data], \ | ||
469 | read_fan_speed(thermostat, FAN_SPEED[data]) \ | ||
470 | ); \ | ||
471 | } | ||
472 | |||
473 | #define BUILD_STORE_FUNC_DEG(name, data) \ | ||
474 | static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \ | ||
475 | { \ | ||
476 | int val; \ | ||
477 | int i; \ | ||
478 | val = simple_strtol(buf, NULL, 10); \ | ||
479 | printk(KERN_INFO "Adjusting limits by %d°C\n", val); \ | ||
480 | limit_adjust = val; \ | ||
481 | for (i=0; i < 3; i++) \ | ||
482 | set_limit(thermostat, i); \ | ||
483 | return n; \ | ||
484 | } | ||
485 | |||
486 | #define BUILD_STORE_FUNC_INT(name, data) \ | ||
487 | static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \ | ||
488 | { \ | ||
489 | u32 val; \ | ||
490 | val = simple_strtoul(buf, NULL, 10); \ | ||
491 | if (val < 0 || val > 255) \ | ||
492 | return -EINVAL; \ | ||
493 | printk(KERN_INFO "Setting specified fan speed to %d\n", val); \ | ||
494 | data = val; \ | ||
495 | return n; \ | ||
496 | } | ||
497 | |||
498 | BUILD_SHOW_FUNC_INT(cpu_temperature, (read_reg(thermostat, TEMP_REG[1]))) | ||
499 | BUILD_SHOW_FUNC_INT(gpu_temperature, (read_reg(thermostat, TEMP_REG[2]))) | ||
500 | BUILD_SHOW_FUNC_INT(cpu_limit, thermostat->limits[1]) | ||
501 | BUILD_SHOW_FUNC_INT(gpu_limit, thermostat->limits[2]) | ||
502 | |||
503 | BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed) | ||
504 | BUILD_SHOW_FUNC_FAN(cpu_fan_speed, 0) | ||
505 | BUILD_SHOW_FUNC_FAN(gpu_fan_speed, 1) | ||
506 | |||
507 | BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed) | ||
508 | BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust) | ||
509 | BUILD_STORE_FUNC_DEG(limit_adjust, thermostat) | ||
510 | |||
511 | static DEVICE_ATTR(cpu_temperature, S_IRUGO, | ||
512 | show_cpu_temperature,NULL); | ||
513 | static DEVICE_ATTR(gpu_temperature, S_IRUGO, | ||
514 | show_gpu_temperature,NULL); | ||
515 | static DEVICE_ATTR(cpu_limit, S_IRUGO, | ||
516 | show_cpu_limit, NULL); | ||
517 | static DEVICE_ATTR(gpu_limit, S_IRUGO, | ||
518 | show_gpu_limit, NULL); | ||
519 | |||
520 | static DEVICE_ATTR(specified_fan_speed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, | ||
521 | show_specified_fan_speed,store_specified_fan_speed); | ||
522 | |||
523 | static DEVICE_ATTR(cpu_fan_speed, S_IRUGO, | ||
524 | show_cpu_fan_speed, NULL); | ||
525 | static DEVICE_ATTR(gpu_fan_speed, S_IRUGO, | ||
526 | show_gpu_fan_speed, NULL); | ||
527 | |||
528 | static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, | ||
529 | show_limit_adjust, store_limit_adjust); | ||
530 | |||
531 | |||
532 | static int __init | ||
533 | thermostat_init(void) | ||
534 | { | ||
535 | struct device_node* np; | ||
536 | u32 *prop; | ||
537 | |||
538 | np = of_find_node_by_name(NULL, "fan"); | ||
539 | if (!np) | ||
540 | return -ENODEV; | ||
541 | if (device_is_compatible(np, "adt7460")) | ||
542 | therm_type = ADT7460; | ||
543 | else if (device_is_compatible(np, "adt7467")) | ||
544 | therm_type = ADT7467; | ||
545 | else | ||
546 | return -ENODEV; | ||
547 | |||
548 | prop = (u32 *)get_property(np, "reg", NULL); | ||
549 | if (!prop) | ||
550 | return -ENODEV; | ||
551 | |||
552 | /* look for bus either by path or using "reg" */ | ||
553 | if (strstr(np->full_name, "/i2c-bus@") != NULL) { | ||
554 | const char *tmp_bus = (strstr(np->full_name, "/i2c-bus@") + 9); | ||
555 | therm_bus = tmp_bus[0]-'0'; | ||
556 | } else { | ||
557 | therm_bus = ((*prop) >> 8) & 0x0f; | ||
558 | } | ||
559 | |||
560 | therm_address = ((*prop) & 0xff) >> 1; | ||
561 | |||
562 | printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, " | ||
563 | "limit_adjust: %d, fan_speed: %d\n", | ||
564 | therm_bus, therm_address, limit_adjust, fan_speed); | ||
565 | |||
566 | of_dev = of_platform_device_create(np, "temperatures"); | ||
567 | |||
568 | if (of_dev == NULL) { | ||
569 | printk(KERN_ERR "Can't register temperatures device !\n"); | ||
570 | return -ENODEV; | ||
571 | } | ||
572 | |||
573 | device_create_file(&of_dev->dev, &dev_attr_cpu_temperature); | ||
574 | device_create_file(&of_dev->dev, &dev_attr_gpu_temperature); | ||
575 | device_create_file(&of_dev->dev, &dev_attr_cpu_limit); | ||
576 | device_create_file(&of_dev->dev, &dev_attr_gpu_limit); | ||
577 | device_create_file(&of_dev->dev, &dev_attr_limit_adjust); | ||
578 | device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed); | ||
579 | device_create_file(&of_dev->dev, &dev_attr_cpu_fan_speed); | ||
580 | if(therm_type == ADT7460) | ||
581 | device_create_file(&of_dev->dev, &dev_attr_gpu_fan_speed); | ||
582 | |||
583 | #ifndef CONFIG_I2C_KEYWEST | ||
584 | request_module("i2c-keywest"); | ||
585 | #endif | ||
586 | |||
587 | return i2c_add_driver(&thermostat_driver); | ||
588 | } | ||
589 | |||
590 | static void __exit | ||
591 | thermostat_exit(void) | ||
592 | { | ||
593 | if (of_dev) { | ||
594 | device_remove_file(&of_dev->dev, &dev_attr_cpu_temperature); | ||
595 | device_remove_file(&of_dev->dev, &dev_attr_gpu_temperature); | ||
596 | device_remove_file(&of_dev->dev, &dev_attr_cpu_limit); | ||
597 | device_remove_file(&of_dev->dev, &dev_attr_gpu_limit); | ||
598 | device_remove_file(&of_dev->dev, &dev_attr_limit_adjust); | ||
599 | device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed); | ||
600 | device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed); | ||
601 | |||
602 | if(therm_type == ADT7460) | ||
603 | device_remove_file(&of_dev->dev, | ||
604 | &dev_attr_gpu_fan_speed); | ||
605 | |||
606 | of_device_unregister(of_dev); | ||
607 | } | ||
608 | i2c_del_driver(&thermostat_driver); | ||
609 | } | ||
610 | |||
611 | module_init(thermostat_init); | ||
612 | module_exit(thermostat_exit); | ||
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c new file mode 100644 index 000000000000..82336a5a5474 --- /dev/null +++ b/drivers/macintosh/therm_pm72.c | |||
@@ -0,0 +1,2080 @@ | |||
1 | /* | ||
2 | * Device driver for the thermostats & fan controller of the | ||
3 | * Apple G5 "PowerMac7,2" desktop machines. | ||
4 | * | ||
5 | * (c) Copyright IBM Corp. 2003-2004 | ||
6 | * | ||
7 | * Maintained by: Benjamin Herrenschmidt | ||
8 | * <benh@kernel.crashing.org> | ||
9 | * | ||
10 | * | ||
11 | * The algorithm used is the PID control algorithm, used the same | ||
12 | * way the published Darwin code does, using the same values that | ||
13 | * are present in the Darwin 7.0 snapshot property lists. | ||
14 | * | ||
15 | * As far as the CPUs control loops are concerned, I use the | ||
16 | * calibration & PID constants provided by the EEPROM, | ||
17 | * I do _not_ embed any value from the property lists, as the ones | ||
18 | * provided by Darwin 7.0 seem to always have an older version that | ||
19 | * what I've seen on the actual computers. | ||
20 | * It would be interesting to verify that though. Darwin has a | ||
21 | * version code of 1.0.0d11 for all control loops it seems, while | ||
22 | * so far, the machines EEPROMs contain a dataset versioned 1.0.0f | ||
23 | * | ||
24 | * Darwin doesn't provide source to all parts, some missing | ||
25 | * bits like the AppleFCU driver or the actual scale of some | ||
26 | * of the values returned by sensors had to be "guessed" some | ||
27 | * way... or based on what Open Firmware does. | ||
28 | * | ||
29 | * I didn't yet figure out how to get the slots power consumption | ||
30 | * out of the FCU, so that part has not been implemented yet and | ||
31 | * the slots fan is set to a fixed 50% PWM, hoping this value is | ||
32 | * safe enough ... | ||
33 | * | ||
34 | * Note: I have observed strange oscillations of the CPU control | ||
35 | * loop on a dual G5 here. When idle, the CPU exhaust fan tend to | ||
36 | * oscillates slowly (over several minutes) between the minimum | ||
37 | * of 300RPMs and approx. 1000 RPMs. I don't know what is causing | ||
38 | * this, it could be some incorrect constant or an error in the | ||
39 | * way I ported the algorithm, or it could be just normal. I | ||
40 | * don't have full understanding on the way Apple tweaked the PID | ||
41 | * algorithm for the CPU control, it is definitely not a standard | ||
42 | * implementation... | ||
43 | * | ||
44 | * TODO: - Check MPU structure version/signature | ||
45 | * - Add things like /sbin/overtemp for non-critical | ||
46 | * overtemp conditions so userland can take some policy | ||
47 | * decisions, like slewing down CPUs | ||
48 | * - Deal with fan and i2c failures in a better way | ||
49 | * - Maybe do a generic PID based on params used for | ||
50 | * U3 and Drives ? Definitely need to factor code a bit | ||
51 | * bettter... also make sensor detection more robust using | ||
52 | * the device-tree to probe for them | ||
53 | * - Figure out how to get the slots consumption and set the | ||
54 | * slots fan accordingly | ||
55 | * | ||
56 | * History: | ||
57 | * | ||
58 | * Nov. 13, 2003 : 0.5 | ||
59 | * - First release | ||
60 | * | ||
61 | * Nov. 14, 2003 : 0.6 | ||
62 | * - Read fan speed from FCU, low level fan routines now deal | ||
63 | * with errors & check fan status, though higher level don't | ||
64 | * do much. | ||
65 | * - Move a bunch of definitions to .h file | ||
66 | * | ||
67 | * Nov. 18, 2003 : 0.7 | ||
68 | * - Fix build on ppc64 kernel | ||
69 | * - Move back statics definitions to .c file | ||
70 | * - Avoid calling schedule_timeout with a negative number | ||
71 | * | ||
72 | * Dec. 18, 2003 : 0.8 | ||
73 | * - Fix typo when reading back fan speed on 2 CPU machines | ||
74 | * | ||
75 | * Mar. 11, 2004 : 0.9 | ||
76 | * - Rework code accessing the ADC chips, make it more robust and | ||
77 | * closer to the chip spec. Also make sure it is configured properly, | ||
78 | * I've seen yet unexplained cases where on startup, I would have stale | ||
79 | * values in the configuration register | ||
80 | * - Switch back to use of target fan speed for PID, thus lowering | ||
81 | * pressure on i2c | ||
82 | * | ||
83 | * Oct. 20, 2004 : 1.1 | ||
84 | * - Add device-tree lookup for fan IDs, should detect liquid cooling | ||
85 | * pumps when present | ||
86 | * - Enable driver for PowerMac7,3 machines | ||
87 | * - Split the U3/Backside cooling on U3 & U3H versions as Darwin does | ||
88 | * - Add new CPU cooling algorithm for machines with liquid cooling | ||
89 | * - Workaround for some PowerMac7,3 with empty "fan" node in the devtree | ||
90 | * - Fix a signed/unsigned compare issue in some PID loops | ||
91 | * | ||
92 | * Mar. 10, 2005 : 1.2 | ||
93 | * - Add basic support for Xserve G5 | ||
94 | * - Retreive pumps min/max from EEPROM image in device-tree (broken) | ||
95 | * - Use min/max macros here or there | ||
96 | * - Latest darwin updated U3H min fan speed to 20% PWM | ||
97 | * | ||
98 | */ | ||
99 | |||
100 | #include <linux/config.h> | ||
101 | #include <linux/types.h> | ||
102 | #include <linux/module.h> | ||
103 | #include <linux/errno.h> | ||
104 | #include <linux/kernel.h> | ||
105 | #include <linux/delay.h> | ||
106 | #include <linux/sched.h> | ||
107 | #include <linux/i2c.h> | ||
108 | #include <linux/slab.h> | ||
109 | #include <linux/init.h> | ||
110 | #include <linux/spinlock.h> | ||
111 | #include <linux/smp_lock.h> | ||
112 | #include <linux/wait.h> | ||
113 | #include <linux/reboot.h> | ||
114 | #include <linux/kmod.h> | ||
115 | #include <linux/i2c.h> | ||
116 | #include <linux/i2c-dev.h> | ||
117 | #include <asm/prom.h> | ||
118 | #include <asm/machdep.h> | ||
119 | #include <asm/io.h> | ||
120 | #include <asm/system.h> | ||
121 | #include <asm/sections.h> | ||
122 | #include <asm/of_device.h> | ||
123 | |||
124 | #include "therm_pm72.h" | ||
125 | |||
126 | #define VERSION "1.2b2" | ||
127 | |||
128 | #undef DEBUG | ||
129 | |||
130 | #ifdef DEBUG | ||
131 | #define DBG(args...) printk(args) | ||
132 | #else | ||
133 | #define DBG(args...) do { } while(0) | ||
134 | #endif | ||
135 | |||
136 | |||
137 | /* | ||
138 | * Driver statics | ||
139 | */ | ||
140 | |||
141 | static struct of_device * of_dev; | ||
142 | static struct i2c_adapter * u3_0; | ||
143 | static struct i2c_adapter * u3_1; | ||
144 | static struct i2c_adapter * k2; | ||
145 | static struct i2c_client * fcu; | ||
146 | static struct cpu_pid_state cpu_state[2]; | ||
147 | static struct basckside_pid_params backside_params; | ||
148 | static struct backside_pid_state backside_state; | ||
149 | static struct drives_pid_state drives_state; | ||
150 | static struct dimm_pid_state dimms_state; | ||
151 | static int state; | ||
152 | static int cpu_count; | ||
153 | static int cpu_pid_type; | ||
154 | static pid_t ctrl_task; | ||
155 | static struct completion ctrl_complete; | ||
156 | static int critical_state; | ||
157 | static int rackmac; | ||
158 | static s32 dimm_output_clamp; | ||
159 | |||
160 | static DECLARE_MUTEX(driver_lock); | ||
161 | |||
162 | /* | ||
163 | * We have 3 types of CPU PID control. One is "split" old style control | ||
164 | * for intake & exhaust fans, the other is "combined" control for both | ||
165 | * CPUs that also deals with the pumps when present. To be "compatible" | ||
166 | * with OS X at this point, we only use "COMBINED" on the machines that | ||
167 | * are identified as having the pumps (though that identification is at | ||
168 | * least dodgy). Ultimately, we could probably switch completely to this | ||
169 | * algorithm provided we hack it to deal with the UP case | ||
170 | */ | ||
171 | #define CPU_PID_TYPE_SPLIT 0 | ||
172 | #define CPU_PID_TYPE_COMBINED 1 | ||
173 | #define CPU_PID_TYPE_RACKMAC 2 | ||
174 | |||
175 | /* | ||
176 | * This table describes all fans in the FCU. The "id" and "type" values | ||
177 | * are defaults valid for all earlier machines. Newer machines will | ||
178 | * eventually override the table content based on the device-tree | ||
179 | */ | ||
180 | struct fcu_fan_table | ||
181 | { | ||
182 | char* loc; /* location code */ | ||
183 | int type; /* 0 = rpm, 1 = pwm, 2 = pump */ | ||
184 | int id; /* id or -1 */ | ||
185 | }; | ||
186 | |||
187 | #define FCU_FAN_RPM 0 | ||
188 | #define FCU_FAN_PWM 1 | ||
189 | |||
190 | #define FCU_FAN_ABSENT_ID -1 | ||
191 | |||
192 | #define FCU_FAN_COUNT ARRAY_SIZE(fcu_fans) | ||
193 | |||
194 | struct fcu_fan_table fcu_fans[] = { | ||
195 | [BACKSIDE_FAN_PWM_INDEX] = { | ||
196 | .loc = "BACKSIDE,SYS CTRLR FAN", | ||
197 | .type = FCU_FAN_PWM, | ||
198 | .id = BACKSIDE_FAN_PWM_DEFAULT_ID, | ||
199 | }, | ||
200 | [DRIVES_FAN_RPM_INDEX] = { | ||
201 | .loc = "DRIVE BAY", | ||
202 | .type = FCU_FAN_RPM, | ||
203 | .id = DRIVES_FAN_RPM_DEFAULT_ID, | ||
204 | }, | ||
205 | [SLOTS_FAN_PWM_INDEX] = { | ||
206 | .loc = "SLOT,PCI FAN", | ||
207 | .type = FCU_FAN_PWM, | ||
208 | .id = SLOTS_FAN_PWM_DEFAULT_ID, | ||
209 | }, | ||
210 | [CPUA_INTAKE_FAN_RPM_INDEX] = { | ||
211 | .loc = "CPU A INTAKE", | ||
212 | .type = FCU_FAN_RPM, | ||
213 | .id = CPUA_INTAKE_FAN_RPM_DEFAULT_ID, | ||
214 | }, | ||
215 | [CPUA_EXHAUST_FAN_RPM_INDEX] = { | ||
216 | .loc = "CPU A EXHAUST", | ||
217 | .type = FCU_FAN_RPM, | ||
218 | .id = CPUA_EXHAUST_FAN_RPM_DEFAULT_ID, | ||
219 | }, | ||
220 | [CPUB_INTAKE_FAN_RPM_INDEX] = { | ||
221 | .loc = "CPU B INTAKE", | ||
222 | .type = FCU_FAN_RPM, | ||
223 | .id = CPUB_INTAKE_FAN_RPM_DEFAULT_ID, | ||
224 | }, | ||
225 | [CPUB_EXHAUST_FAN_RPM_INDEX] = { | ||
226 | .loc = "CPU B EXHAUST", | ||
227 | .type = FCU_FAN_RPM, | ||
228 | .id = CPUB_EXHAUST_FAN_RPM_DEFAULT_ID, | ||
229 | }, | ||
230 | /* pumps aren't present by default, have to be looked up in the | ||
231 | * device-tree | ||
232 | */ | ||
233 | [CPUA_PUMP_RPM_INDEX] = { | ||
234 | .loc = "CPU A PUMP", | ||
235 | .type = FCU_FAN_RPM, | ||
236 | .id = FCU_FAN_ABSENT_ID, | ||
237 | }, | ||
238 | [CPUB_PUMP_RPM_INDEX] = { | ||
239 | .loc = "CPU B PUMP", | ||
240 | .type = FCU_FAN_RPM, | ||
241 | .id = FCU_FAN_ABSENT_ID, | ||
242 | }, | ||
243 | /* Xserve fans */ | ||
244 | [CPU_A1_FAN_RPM_INDEX] = { | ||
245 | .loc = "CPU A 1", | ||
246 | .type = FCU_FAN_RPM, | ||
247 | .id = FCU_FAN_ABSENT_ID, | ||
248 | }, | ||
249 | [CPU_A2_FAN_RPM_INDEX] = { | ||
250 | .loc = "CPU A 2", | ||
251 | .type = FCU_FAN_RPM, | ||
252 | .id = FCU_FAN_ABSENT_ID, | ||
253 | }, | ||
254 | [CPU_A3_FAN_RPM_INDEX] = { | ||
255 | .loc = "CPU A 3", | ||
256 | .type = FCU_FAN_RPM, | ||
257 | .id = FCU_FAN_ABSENT_ID, | ||
258 | }, | ||
259 | [CPU_B1_FAN_RPM_INDEX] = { | ||
260 | .loc = "CPU B 1", | ||
261 | .type = FCU_FAN_RPM, | ||
262 | .id = FCU_FAN_ABSENT_ID, | ||
263 | }, | ||
264 | [CPU_B2_FAN_RPM_INDEX] = { | ||
265 | .loc = "CPU B 2", | ||
266 | .type = FCU_FAN_RPM, | ||
267 | .id = FCU_FAN_ABSENT_ID, | ||
268 | }, | ||
269 | [CPU_B3_FAN_RPM_INDEX] = { | ||
270 | .loc = "CPU B 3", | ||
271 | .type = FCU_FAN_RPM, | ||
272 | .id = FCU_FAN_ABSENT_ID, | ||
273 | }, | ||
274 | }; | ||
275 | |||
276 | /* | ||
277 | * i2c_driver structure to attach to the host i2c controller | ||
278 | */ | ||
279 | |||
280 | static int therm_pm72_attach(struct i2c_adapter *adapter); | ||
281 | static int therm_pm72_detach(struct i2c_adapter *adapter); | ||
282 | |||
283 | static struct i2c_driver therm_pm72_driver = | ||
284 | { | ||
285 | .owner = THIS_MODULE, | ||
286 | .name = "therm_pm72", | ||
287 | .flags = I2C_DF_NOTIFY, | ||
288 | .attach_adapter = therm_pm72_attach, | ||
289 | .detach_adapter = therm_pm72_detach, | ||
290 | }; | ||
291 | |||
292 | /* | ||
293 | * Utility function to create an i2c_client structure and | ||
294 | * attach it to one of u3 adapters | ||
295 | */ | ||
296 | static struct i2c_client *attach_i2c_chip(int id, const char *name) | ||
297 | { | ||
298 | struct i2c_client *clt; | ||
299 | struct i2c_adapter *adap; | ||
300 | |||
301 | if (id & 0x200) | ||
302 | adap = k2; | ||
303 | else if (id & 0x100) | ||
304 | adap = u3_1; | ||
305 | else | ||
306 | adap = u3_0; | ||
307 | if (adap == NULL) | ||
308 | return NULL; | ||
309 | |||
310 | clt = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
311 | if (clt == NULL) | ||
312 | return NULL; | ||
313 | memset(clt, 0, sizeof(struct i2c_client)); | ||
314 | |||
315 | clt->addr = (id >> 1) & 0x7f; | ||
316 | clt->adapter = adap; | ||
317 | clt->driver = &therm_pm72_driver; | ||
318 | strncpy(clt->name, name, I2C_NAME_SIZE-1); | ||
319 | |||
320 | if (i2c_attach_client(clt)) { | ||
321 | printk(KERN_ERR "therm_pm72: Failed to attach to i2c ID 0x%x\n", id); | ||
322 | kfree(clt); | ||
323 | return NULL; | ||
324 | } | ||
325 | return clt; | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Utility function to get rid of the i2c_client structure | ||
330 | * (will also detach from the adapter hopepfully) | ||
331 | */ | ||
332 | static void detach_i2c_chip(struct i2c_client *clt) | ||
333 | { | ||
334 | i2c_detach_client(clt); | ||
335 | kfree(clt); | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * Here are the i2c chip access wrappers | ||
340 | */ | ||
341 | |||
342 | static void initialize_adc(struct cpu_pid_state *state) | ||
343 | { | ||
344 | int rc; | ||
345 | u8 buf[2]; | ||
346 | |||
347 | /* Read ADC the configuration register and cache it. We | ||
348 | * also make sure Config2 contains proper values, I've seen | ||
349 | * cases where we got stale grabage in there, thus preventing | ||
350 | * proper reading of conv. values | ||
351 | */ | ||
352 | |||
353 | /* Clear Config2 */ | ||
354 | buf[0] = 5; | ||
355 | buf[1] = 0; | ||
356 | i2c_master_send(state->monitor, buf, 2); | ||
357 | |||
358 | /* Read & cache Config1 */ | ||
359 | buf[0] = 1; | ||
360 | rc = i2c_master_send(state->monitor, buf, 1); | ||
361 | if (rc > 0) { | ||
362 | rc = i2c_master_recv(state->monitor, buf, 1); | ||
363 | if (rc > 0) { | ||
364 | state->adc_config = buf[0]; | ||
365 | DBG("ADC config reg: %02x\n", state->adc_config); | ||
366 | /* Disable shutdown mode */ | ||
367 | state->adc_config &= 0xfe; | ||
368 | buf[0] = 1; | ||
369 | buf[1] = state->adc_config; | ||
370 | rc = i2c_master_send(state->monitor, buf, 2); | ||
371 | } | ||
372 | } | ||
373 | if (rc <= 0) | ||
374 | printk(KERN_ERR "therm_pm72: Error reading ADC config" | ||
375 | " register !\n"); | ||
376 | } | ||
377 | |||
378 | static int read_smon_adc(struct cpu_pid_state *state, int chan) | ||
379 | { | ||
380 | int rc, data, tries = 0; | ||
381 | u8 buf[2]; | ||
382 | |||
383 | for (;;) { | ||
384 | /* Set channel */ | ||
385 | buf[0] = 1; | ||
386 | buf[1] = (state->adc_config & 0x1f) | (chan << 5); | ||
387 | rc = i2c_master_send(state->monitor, buf, 2); | ||
388 | if (rc <= 0) | ||
389 | goto error; | ||
390 | /* Wait for convertion */ | ||
391 | msleep(1); | ||
392 | /* Switch to data register */ | ||
393 | buf[0] = 4; | ||
394 | rc = i2c_master_send(state->monitor, buf, 1); | ||
395 | if (rc <= 0) | ||
396 | goto error; | ||
397 | /* Read result */ | ||
398 | rc = i2c_master_recv(state->monitor, buf, 2); | ||
399 | if (rc < 0) | ||
400 | goto error; | ||
401 | data = ((u16)buf[0]) << 8 | (u16)buf[1]; | ||
402 | return data >> 6; | ||
403 | error: | ||
404 | DBG("Error reading ADC, retrying...\n"); | ||
405 | if (++tries > 10) { | ||
406 | printk(KERN_ERR "therm_pm72: Error reading ADC !\n"); | ||
407 | return -1; | ||
408 | } | ||
409 | msleep(10); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | static int read_lm87_reg(struct i2c_client * chip, int reg) | ||
414 | { | ||
415 | int rc, tries = 0; | ||
416 | u8 buf; | ||
417 | |||
418 | for (;;) { | ||
419 | /* Set address */ | ||
420 | buf = (u8)reg; | ||
421 | rc = i2c_master_send(chip, &buf, 1); | ||
422 | if (rc <= 0) | ||
423 | goto error; | ||
424 | rc = i2c_master_recv(chip, &buf, 1); | ||
425 | if (rc <= 0) | ||
426 | goto error; | ||
427 | return (int)buf; | ||
428 | error: | ||
429 | DBG("Error reading LM87, retrying...\n"); | ||
430 | if (++tries > 10) { | ||
431 | printk(KERN_ERR "therm_pm72: Error reading LM87 !\n"); | ||
432 | return -1; | ||
433 | } | ||
434 | msleep(10); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | static int fan_read_reg(int reg, unsigned char *buf, int nb) | ||
439 | { | ||
440 | int tries, nr, nw; | ||
441 | |||
442 | buf[0] = reg; | ||
443 | tries = 0; | ||
444 | for (;;) { | ||
445 | nw = i2c_master_send(fcu, buf, 1); | ||
446 | if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100) | ||
447 | break; | ||
448 | msleep(10); | ||
449 | ++tries; | ||
450 | } | ||
451 | if (nw <= 0) { | ||
452 | printk(KERN_ERR "Failure writing address to FCU: %d", nw); | ||
453 | return -EIO; | ||
454 | } | ||
455 | tries = 0; | ||
456 | for (;;) { | ||
457 | nr = i2c_master_recv(fcu, buf, nb); | ||
458 | if (nr > 0 || (nr < 0 && nr != ENODEV) || tries >= 100) | ||
459 | break; | ||
460 | msleep(10); | ||
461 | ++tries; | ||
462 | } | ||
463 | if (nr <= 0) | ||
464 | printk(KERN_ERR "Failure reading data from FCU: %d", nw); | ||
465 | return nr; | ||
466 | } | ||
467 | |||
468 | static int fan_write_reg(int reg, const unsigned char *ptr, int nb) | ||
469 | { | ||
470 | int tries, nw; | ||
471 | unsigned char buf[16]; | ||
472 | |||
473 | buf[0] = reg; | ||
474 | memcpy(buf+1, ptr, nb); | ||
475 | ++nb; | ||
476 | tries = 0; | ||
477 | for (;;) { | ||
478 | nw = i2c_master_send(fcu, buf, nb); | ||
479 | if (nw > 0 || (nw < 0 && nw != EIO) || tries >= 100) | ||
480 | break; | ||
481 | msleep(10); | ||
482 | ++tries; | ||
483 | } | ||
484 | if (nw < 0) | ||
485 | printk(KERN_ERR "Failure writing to FCU: %d", nw); | ||
486 | return nw; | ||
487 | } | ||
488 | |||
489 | static int start_fcu(void) | ||
490 | { | ||
491 | unsigned char buf = 0xff; | ||
492 | int rc; | ||
493 | |||
494 | rc = fan_write_reg(0xe, &buf, 1); | ||
495 | if (rc < 0) | ||
496 | return -EIO; | ||
497 | rc = fan_write_reg(0x2e, &buf, 1); | ||
498 | if (rc < 0) | ||
499 | return -EIO; | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static int set_rpm_fan(int fan_index, int rpm) | ||
504 | { | ||
505 | unsigned char buf[2]; | ||
506 | int rc, id; | ||
507 | |||
508 | if (fcu_fans[fan_index].type != FCU_FAN_RPM) | ||
509 | return -EINVAL; | ||
510 | id = fcu_fans[fan_index].id; | ||
511 | if (id == FCU_FAN_ABSENT_ID) | ||
512 | return -EINVAL; | ||
513 | |||
514 | if (rpm < 300) | ||
515 | rpm = 300; | ||
516 | else if (rpm > 8191) | ||
517 | rpm = 8191; | ||
518 | buf[0] = rpm >> 5; | ||
519 | buf[1] = rpm << 3; | ||
520 | rc = fan_write_reg(0x10 + (id * 2), buf, 2); | ||
521 | if (rc < 0) | ||
522 | return -EIO; | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static int get_rpm_fan(int fan_index, int programmed) | ||
527 | { | ||
528 | unsigned char failure; | ||
529 | unsigned char active; | ||
530 | unsigned char buf[2]; | ||
531 | int rc, id, reg_base; | ||
532 | |||
533 | if (fcu_fans[fan_index].type != FCU_FAN_RPM) | ||
534 | return -EINVAL; | ||
535 | id = fcu_fans[fan_index].id; | ||
536 | if (id == FCU_FAN_ABSENT_ID) | ||
537 | return -EINVAL; | ||
538 | |||
539 | rc = fan_read_reg(0xb, &failure, 1); | ||
540 | if (rc != 1) | ||
541 | return -EIO; | ||
542 | if ((failure & (1 << id)) != 0) | ||
543 | return -EFAULT; | ||
544 | rc = fan_read_reg(0xd, &active, 1); | ||
545 | if (rc != 1) | ||
546 | return -EIO; | ||
547 | if ((active & (1 << id)) == 0) | ||
548 | return -ENXIO; | ||
549 | |||
550 | /* Programmed value or real current speed */ | ||
551 | reg_base = programmed ? 0x10 : 0x11; | ||
552 | rc = fan_read_reg(reg_base + (id * 2), buf, 2); | ||
553 | if (rc != 2) | ||
554 | return -EIO; | ||
555 | |||
556 | return (buf[0] << 5) | buf[1] >> 3; | ||
557 | } | ||
558 | |||
559 | static int set_pwm_fan(int fan_index, int pwm) | ||
560 | { | ||
561 | unsigned char buf[2]; | ||
562 | int rc, id; | ||
563 | |||
564 | if (fcu_fans[fan_index].type != FCU_FAN_PWM) | ||
565 | return -EINVAL; | ||
566 | id = fcu_fans[fan_index].id; | ||
567 | if (id == FCU_FAN_ABSENT_ID) | ||
568 | return -EINVAL; | ||
569 | |||
570 | if (pwm < 10) | ||
571 | pwm = 10; | ||
572 | else if (pwm > 100) | ||
573 | pwm = 100; | ||
574 | pwm = (pwm * 2559) / 1000; | ||
575 | buf[0] = pwm; | ||
576 | rc = fan_write_reg(0x30 + (id * 2), buf, 1); | ||
577 | if (rc < 0) | ||
578 | return rc; | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int get_pwm_fan(int fan_index) | ||
583 | { | ||
584 | unsigned char failure; | ||
585 | unsigned char active; | ||
586 | unsigned char buf[2]; | ||
587 | int rc, id; | ||
588 | |||
589 | if (fcu_fans[fan_index].type != FCU_FAN_PWM) | ||
590 | return -EINVAL; | ||
591 | id = fcu_fans[fan_index].id; | ||
592 | if (id == FCU_FAN_ABSENT_ID) | ||
593 | return -EINVAL; | ||
594 | |||
595 | rc = fan_read_reg(0x2b, &failure, 1); | ||
596 | if (rc != 1) | ||
597 | return -EIO; | ||
598 | if ((failure & (1 << id)) != 0) | ||
599 | return -EFAULT; | ||
600 | rc = fan_read_reg(0x2d, &active, 1); | ||
601 | if (rc != 1) | ||
602 | return -EIO; | ||
603 | if ((active & (1 << id)) == 0) | ||
604 | return -ENXIO; | ||
605 | |||
606 | /* Programmed value or real current speed */ | ||
607 | rc = fan_read_reg(0x30 + (id * 2), buf, 1); | ||
608 | if (rc != 1) | ||
609 | return -EIO; | ||
610 | |||
611 | return (buf[0] * 1000) / 2559; | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * Utility routine to read the CPU calibration EEPROM data | ||
616 | * from the device-tree | ||
617 | */ | ||
618 | static int read_eeprom(int cpu, struct mpu_data *out) | ||
619 | { | ||
620 | struct device_node *np; | ||
621 | char nodename[64]; | ||
622 | u8 *data; | ||
623 | int len; | ||
624 | |||
625 | /* prom.c routine for finding a node by path is a bit brain dead | ||
626 | * and requires exact @xxx unit numbers. This is a bit ugly but | ||
627 | * will work for these machines | ||
628 | */ | ||
629 | sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0); | ||
630 | np = of_find_node_by_path(nodename); | ||
631 | if (np == NULL) { | ||
632 | printk(KERN_ERR "therm_pm72: Failed to retreive cpuid node from device-tree\n"); | ||
633 | return -ENODEV; | ||
634 | } | ||
635 | data = (u8 *)get_property(np, "cpuid", &len); | ||
636 | if (data == NULL) { | ||
637 | printk(KERN_ERR "therm_pm72: Failed to retreive cpuid property from device-tree\n"); | ||
638 | of_node_put(np); | ||
639 | return -ENODEV; | ||
640 | } | ||
641 | memcpy(out, data, sizeof(struct mpu_data)); | ||
642 | of_node_put(np); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static void fetch_cpu_pumps_minmax(void) | ||
648 | { | ||
649 | struct cpu_pid_state *state0 = &cpu_state[0]; | ||
650 | struct cpu_pid_state *state1 = &cpu_state[1]; | ||
651 | u16 pump_min = 0, pump_max = 0xffff; | ||
652 | u16 tmp[4]; | ||
653 | |||
654 | /* Try to fetch pumps min/max infos from eeprom */ | ||
655 | |||
656 | memcpy(&tmp, &state0->mpu.processor_part_num, 8); | ||
657 | if (tmp[0] != 0xffff && tmp[1] != 0xffff) { | ||
658 | pump_min = max(pump_min, tmp[0]); | ||
659 | pump_max = min(pump_max, tmp[1]); | ||
660 | } | ||
661 | if (tmp[2] != 0xffff && tmp[3] != 0xffff) { | ||
662 | pump_min = max(pump_min, tmp[2]); | ||
663 | pump_max = min(pump_max, tmp[3]); | ||
664 | } | ||
665 | |||
666 | /* Double check the values, this _IS_ needed as the EEPROM on | ||
667 | * some dual 2.5Ghz G5s seem, at least, to have both min & max | ||
668 | * same to the same value ... (grrrr) | ||
669 | */ | ||
670 | if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) { | ||
671 | pump_min = CPU_PUMP_OUTPUT_MIN; | ||
672 | pump_max = CPU_PUMP_OUTPUT_MAX; | ||
673 | } | ||
674 | |||
675 | state0->pump_min = state1->pump_min = pump_min; | ||
676 | state0->pump_max = state1->pump_max = pump_max; | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * Now, unfortunately, sysfs doesn't give us a nice void * we could | ||
681 | * pass around to the attribute functions, so we don't really have | ||
682 | * choice but implement a bunch of them... | ||
683 | * | ||
684 | * That sucks a bit, we take the lock because FIX32TOPRINT evaluates | ||
685 | * the input twice... I accept patches :) | ||
686 | */ | ||
687 | #define BUILD_SHOW_FUNC_FIX(name, data) \ | ||
688 | static ssize_t show_##name(struct device *dev, char *buf) \ | ||
689 | { \ | ||
690 | ssize_t r; \ | ||
691 | down(&driver_lock); \ | ||
692 | r = sprintf(buf, "%d.%03d", FIX32TOPRINT(data)); \ | ||
693 | up(&driver_lock); \ | ||
694 | return r; \ | ||
695 | } | ||
696 | #define BUILD_SHOW_FUNC_INT(name, data) \ | ||
697 | static ssize_t show_##name(struct device *dev, char *buf) \ | ||
698 | { \ | ||
699 | return sprintf(buf, "%d", data); \ | ||
700 | } | ||
701 | |||
702 | BUILD_SHOW_FUNC_FIX(cpu0_temperature, cpu_state[0].last_temp) | ||
703 | BUILD_SHOW_FUNC_FIX(cpu0_voltage, cpu_state[0].voltage) | ||
704 | BUILD_SHOW_FUNC_FIX(cpu0_current, cpu_state[0].current_a) | ||
705 | BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, cpu_state[0].rpm) | ||
706 | BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, cpu_state[0].intake_rpm) | ||
707 | |||
708 | BUILD_SHOW_FUNC_FIX(cpu1_temperature, cpu_state[1].last_temp) | ||
709 | BUILD_SHOW_FUNC_FIX(cpu1_voltage, cpu_state[1].voltage) | ||
710 | BUILD_SHOW_FUNC_FIX(cpu1_current, cpu_state[1].current_a) | ||
711 | BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, cpu_state[1].rpm) | ||
712 | BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, cpu_state[1].intake_rpm) | ||
713 | |||
714 | BUILD_SHOW_FUNC_FIX(backside_temperature, backside_state.last_temp) | ||
715 | BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm) | ||
716 | |||
717 | BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp) | ||
718 | BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm) | ||
719 | |||
720 | BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp) | ||
721 | |||
722 | static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL); | ||
723 | static DEVICE_ATTR(cpu0_voltage,S_IRUGO,show_cpu0_voltage,NULL); | ||
724 | static DEVICE_ATTR(cpu0_current,S_IRUGO,show_cpu0_current,NULL); | ||
725 | static DEVICE_ATTR(cpu0_exhaust_fan_rpm,S_IRUGO,show_cpu0_exhaust_fan_rpm,NULL); | ||
726 | static DEVICE_ATTR(cpu0_intake_fan_rpm,S_IRUGO,show_cpu0_intake_fan_rpm,NULL); | ||
727 | |||
728 | static DEVICE_ATTR(cpu1_temperature,S_IRUGO,show_cpu1_temperature,NULL); | ||
729 | static DEVICE_ATTR(cpu1_voltage,S_IRUGO,show_cpu1_voltage,NULL); | ||
730 | static DEVICE_ATTR(cpu1_current,S_IRUGO,show_cpu1_current,NULL); | ||
731 | static DEVICE_ATTR(cpu1_exhaust_fan_rpm,S_IRUGO,show_cpu1_exhaust_fan_rpm,NULL); | ||
732 | static DEVICE_ATTR(cpu1_intake_fan_rpm,S_IRUGO,show_cpu1_intake_fan_rpm,NULL); | ||
733 | |||
734 | static DEVICE_ATTR(backside_temperature,S_IRUGO,show_backside_temperature,NULL); | ||
735 | static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL); | ||
736 | |||
737 | static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL); | ||
738 | static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL); | ||
739 | |||
740 | static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL); | ||
741 | |||
742 | /* | ||
743 | * CPUs fans control loop | ||
744 | */ | ||
745 | |||
746 | static int do_read_one_cpu_values(struct cpu_pid_state *state, s32 *temp, s32 *power) | ||
747 | { | ||
748 | s32 ltemp, volts, amps; | ||
749 | int index, rc = 0; | ||
750 | |||
751 | /* Default (in case of error) */ | ||
752 | *temp = state->cur_temp; | ||
753 | *power = state->cur_power; | ||
754 | |||
755 | if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) | ||
756 | index = (state->index == 0) ? | ||
757 | CPU_A1_FAN_RPM_INDEX : CPU_B1_FAN_RPM_INDEX; | ||
758 | else | ||
759 | index = (state->index == 0) ? | ||
760 | CPUA_EXHAUST_FAN_RPM_INDEX : CPUB_EXHAUST_FAN_RPM_INDEX; | ||
761 | |||
762 | /* Read current fan status */ | ||
763 | rc = get_rpm_fan(index, !RPM_PID_USE_ACTUAL_SPEED); | ||
764 | if (rc < 0) { | ||
765 | /* XXX What do we do now ? Nothing for now, keep old value, but | ||
766 | * return error upstream | ||
767 | */ | ||
768 | DBG(" cpu %d, fan reading error !\n", state->index); | ||
769 | } else { | ||
770 | state->rpm = rc; | ||
771 | DBG(" cpu %d, exhaust RPM: %d\n", state->index, state->rpm); | ||
772 | } | ||
773 | |||
774 | /* Get some sensor readings and scale it */ | ||
775 | ltemp = read_smon_adc(state, 1); | ||
776 | if (ltemp == -1) { | ||
777 | /* XXX What do we do now ? */ | ||
778 | state->overtemp++; | ||
779 | if (rc == 0) | ||
780 | rc = -EIO; | ||
781 | DBG(" cpu %d, temp reading error !\n", state->index); | ||
782 | } else { | ||
783 | /* Fixup temperature according to diode calibration | ||
784 | */ | ||
785 | DBG(" cpu %d, temp raw: %04x, m_diode: %04x, b_diode: %04x\n", | ||
786 | state->index, | ||
787 | ltemp, state->mpu.mdiode, state->mpu.bdiode); | ||
788 | *temp = ((s32)ltemp * (s32)state->mpu.mdiode + ((s32)state->mpu.bdiode << 12)) >> 2; | ||
789 | state->last_temp = *temp; | ||
790 | DBG(" temp: %d.%03d\n", FIX32TOPRINT((*temp))); | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | * Read voltage & current and calculate power | ||
795 | */ | ||
796 | volts = read_smon_adc(state, 3); | ||
797 | amps = read_smon_adc(state, 4); | ||
798 | |||
799 | /* Scale voltage and current raw sensor values according to fixed scales | ||
800 | * obtained in Darwin and calculate power from I and V | ||
801 | */ | ||
802 | volts *= ADC_CPU_VOLTAGE_SCALE; | ||
803 | amps *= ADC_CPU_CURRENT_SCALE; | ||
804 | *power = (((u64)volts) * ((u64)amps)) >> 16; | ||
805 | state->voltage = volts; | ||
806 | state->current_a = amps; | ||
807 | state->last_power = *power; | ||
808 | |||
809 | DBG(" cpu %d, current: %d.%03d, voltage: %d.%03d, power: %d.%03d W\n", | ||
810 | state->index, FIX32TOPRINT(state->current_a), | ||
811 | FIX32TOPRINT(state->voltage), FIX32TOPRINT(*power)); | ||
812 | |||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power) | ||
817 | { | ||
818 | s32 power_target, integral, derivative, proportional, adj_in_target, sval; | ||
819 | s64 integ_p, deriv_p, prop_p, sum; | ||
820 | int i; | ||
821 | |||
822 | /* Calculate power target value (could be done once for all) | ||
823 | * and convert to a 16.16 fp number | ||
824 | */ | ||
825 | power_target = ((u32)(state->mpu.pmaxh - state->mpu.padjmax)) << 16; | ||
826 | DBG(" power target: %d.%03d, error: %d.%03d\n", | ||
827 | FIX32TOPRINT(power_target), FIX32TOPRINT(power_target - power)); | ||
828 | |||
829 | /* Store temperature and power in history array */ | ||
830 | state->cur_temp = (state->cur_temp + 1) % CPU_TEMP_HISTORY_SIZE; | ||
831 | state->temp_history[state->cur_temp] = temp; | ||
832 | state->cur_power = (state->cur_power + 1) % state->count_power; | ||
833 | state->power_history[state->cur_power] = power; | ||
834 | state->error_history[state->cur_power] = power_target - power; | ||
835 | |||
836 | /* If first loop, fill the history table */ | ||
837 | if (state->first) { | ||
838 | for (i = 0; i < (state->count_power - 1); i++) { | ||
839 | state->cur_power = (state->cur_power + 1) % state->count_power; | ||
840 | state->power_history[state->cur_power] = power; | ||
841 | state->error_history[state->cur_power] = power_target - power; | ||
842 | } | ||
843 | for (i = 0; i < (CPU_TEMP_HISTORY_SIZE - 1); i++) { | ||
844 | state->cur_temp = (state->cur_temp + 1) % CPU_TEMP_HISTORY_SIZE; | ||
845 | state->temp_history[state->cur_temp] = temp; | ||
846 | } | ||
847 | state->first = 0; | ||
848 | } | ||
849 | |||
850 | /* Calculate the integral term normally based on the "power" values */ | ||
851 | sum = 0; | ||
852 | integral = 0; | ||
853 | for (i = 0; i < state->count_power; i++) | ||
854 | integral += state->error_history[i]; | ||
855 | integral *= CPU_PID_INTERVAL; | ||
856 | DBG(" integral: %08x\n", integral); | ||
857 | |||
858 | /* Calculate the adjusted input (sense value). | ||
859 | * G_r is 12.20 | ||
860 | * integ is 16.16 | ||
861 | * so the result is 28.36 | ||
862 | * | ||
863 | * input target is mpu.ttarget, input max is mpu.tmax | ||
864 | */ | ||
865 | integ_p = ((s64)state->mpu.pid_gr) * (s64)integral; | ||
866 | DBG(" integ_p: %d\n", (int)(integ_p >> 36)); | ||
867 | sval = (state->mpu.tmax << 16) - ((integ_p >> 20) & 0xffffffff); | ||
868 | adj_in_target = (state->mpu.ttarget << 16); | ||
869 | if (adj_in_target > sval) | ||
870 | adj_in_target = sval; | ||
871 | DBG(" adj_in_target: %d.%03d, ttarget: %d\n", FIX32TOPRINT(adj_in_target), | ||
872 | state->mpu.ttarget); | ||
873 | |||
874 | /* Calculate the derivative term */ | ||
875 | derivative = state->temp_history[state->cur_temp] - | ||
876 | state->temp_history[(state->cur_temp + CPU_TEMP_HISTORY_SIZE - 1) | ||
877 | % CPU_TEMP_HISTORY_SIZE]; | ||
878 | derivative /= CPU_PID_INTERVAL; | ||
879 | deriv_p = ((s64)state->mpu.pid_gd) * (s64)derivative; | ||
880 | DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); | ||
881 | sum += deriv_p; | ||
882 | |||
883 | /* Calculate the proportional term */ | ||
884 | proportional = temp - adj_in_target; | ||
885 | prop_p = ((s64)state->mpu.pid_gp) * (s64)proportional; | ||
886 | DBG(" prop_p: %d\n", (int)(prop_p >> 36)); | ||
887 | sum += prop_p; | ||
888 | |||
889 | /* Scale sum */ | ||
890 | sum >>= 36; | ||
891 | |||
892 | DBG(" sum: %d\n", (int)sum); | ||
893 | state->rpm += (s32)sum; | ||
894 | } | ||
895 | |||
896 | static void do_monitor_cpu_combined(void) | ||
897 | { | ||
898 | struct cpu_pid_state *state0 = &cpu_state[0]; | ||
899 | struct cpu_pid_state *state1 = &cpu_state[1]; | ||
900 | s32 temp0, power0, temp1, power1; | ||
901 | s32 temp_combi, power_combi; | ||
902 | int rc, intake, pump; | ||
903 | |||
904 | rc = do_read_one_cpu_values(state0, &temp0, &power0); | ||
905 | if (rc < 0) { | ||
906 | /* XXX What do we do now ? */ | ||
907 | } | ||
908 | state1->overtemp = 0; | ||
909 | rc = do_read_one_cpu_values(state1, &temp1, &power1); | ||
910 | if (rc < 0) { | ||
911 | /* XXX What do we do now ? */ | ||
912 | } | ||
913 | if (state1->overtemp) | ||
914 | state0->overtemp++; | ||
915 | |||
916 | temp_combi = max(temp0, temp1); | ||
917 | power_combi = max(power0, power1); | ||
918 | |||
919 | /* Check tmax, increment overtemp if we are there. At tmax+8, we go | ||
920 | * full blown immediately and try to trigger a shutdown | ||
921 | */ | ||
922 | if (temp_combi >= ((state0->mpu.tmax + 8) << 16)) { | ||
923 | printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n", | ||
924 | temp_combi >> 16); | ||
925 | state0->overtemp = CPU_MAX_OVERTEMP; | ||
926 | } else if (temp_combi > (state0->mpu.tmax << 16)) | ||
927 | state0->overtemp++; | ||
928 | else | ||
929 | state0->overtemp = 0; | ||
930 | if (state0->overtemp >= CPU_MAX_OVERTEMP) | ||
931 | critical_state = 1; | ||
932 | if (state0->overtemp > 0) { | ||
933 | state0->rpm = state0->mpu.rmaxn_exhaust_fan; | ||
934 | state0->intake_rpm = intake = state0->mpu.rmaxn_intake_fan; | ||
935 | pump = state0->pump_min; | ||
936 | goto do_set_fans; | ||
937 | } | ||
938 | |||
939 | /* Do the PID */ | ||
940 | do_cpu_pid(state0, temp_combi, power_combi); | ||
941 | |||
942 | /* Range check */ | ||
943 | state0->rpm = max(state0->rpm, (int)state0->mpu.rminn_exhaust_fan); | ||
944 | state0->rpm = min(state0->rpm, (int)state0->mpu.rmaxn_exhaust_fan); | ||
945 | |||
946 | /* Calculate intake fan speed */ | ||
947 | intake = (state0->rpm * CPU_INTAKE_SCALE) >> 16; | ||
948 | intake = max(intake, (int)state0->mpu.rminn_intake_fan); | ||
949 | intake = min(intake, (int)state0->mpu.rmaxn_intake_fan); | ||
950 | state0->intake_rpm = intake; | ||
951 | |||
952 | /* Calculate pump speed */ | ||
953 | pump = (state0->rpm * state0->pump_max) / | ||
954 | state0->mpu.rmaxn_exhaust_fan; | ||
955 | pump = min(pump, state0->pump_max); | ||
956 | pump = max(pump, state0->pump_min); | ||
957 | |||
958 | do_set_fans: | ||
959 | /* We copy values from state 0 to state 1 for /sysfs */ | ||
960 | state1->rpm = state0->rpm; | ||
961 | state1->intake_rpm = state0->intake_rpm; | ||
962 | |||
963 | DBG("** CPU %d RPM: %d Ex, %d, Pump: %d, In, overtemp: %d\n", | ||
964 | state1->index, (int)state1->rpm, intake, pump, state1->overtemp); | ||
965 | |||
966 | /* We should check for errors, shouldn't we ? But then, what | ||
967 | * do we do once the error occurs ? For FCU notified fan | ||
968 | * failures (-EFAULT) we probably want to notify userland | ||
969 | * some way... | ||
970 | */ | ||
971 | set_rpm_fan(CPUA_INTAKE_FAN_RPM_INDEX, intake); | ||
972 | set_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, state0->rpm); | ||
973 | set_rpm_fan(CPUB_INTAKE_FAN_RPM_INDEX, intake); | ||
974 | set_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, state0->rpm); | ||
975 | |||
976 | if (fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) | ||
977 | set_rpm_fan(CPUA_PUMP_RPM_INDEX, pump); | ||
978 | if (fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) | ||
979 | set_rpm_fan(CPUB_PUMP_RPM_INDEX, pump); | ||
980 | } | ||
981 | |||
982 | static void do_monitor_cpu_split(struct cpu_pid_state *state) | ||
983 | { | ||
984 | s32 temp, power; | ||
985 | int rc, intake; | ||
986 | |||
987 | /* Read current fan status */ | ||
988 | rc = do_read_one_cpu_values(state, &temp, &power); | ||
989 | if (rc < 0) { | ||
990 | /* XXX What do we do now ? */ | ||
991 | } | ||
992 | |||
993 | /* Check tmax, increment overtemp if we are there. At tmax+8, we go | ||
994 | * full blown immediately and try to trigger a shutdown | ||
995 | */ | ||
996 | if (temp >= ((state->mpu.tmax + 8) << 16)) { | ||
997 | printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum" | ||
998 | " (%d) !\n", | ||
999 | state->index, temp >> 16); | ||
1000 | state->overtemp = CPU_MAX_OVERTEMP; | ||
1001 | } else if (temp > (state->mpu.tmax << 16)) | ||
1002 | state->overtemp++; | ||
1003 | else | ||
1004 | state->overtemp = 0; | ||
1005 | if (state->overtemp >= CPU_MAX_OVERTEMP) | ||
1006 | critical_state = 1; | ||
1007 | if (state->overtemp > 0) { | ||
1008 | state->rpm = state->mpu.rmaxn_exhaust_fan; | ||
1009 | state->intake_rpm = intake = state->mpu.rmaxn_intake_fan; | ||
1010 | goto do_set_fans; | ||
1011 | } | ||
1012 | |||
1013 | /* Do the PID */ | ||
1014 | do_cpu_pid(state, temp, power); | ||
1015 | |||
1016 | /* Range check */ | ||
1017 | state->rpm = max(state->rpm, (int)state->mpu.rminn_exhaust_fan); | ||
1018 | state->rpm = min(state->rpm, (int)state->mpu.rmaxn_exhaust_fan); | ||
1019 | |||
1020 | /* Calculate intake fan */ | ||
1021 | intake = (state->rpm * CPU_INTAKE_SCALE) >> 16; | ||
1022 | intake = max(intake, (int)state->mpu.rminn_intake_fan); | ||
1023 | intake = min(intake, (int)state->mpu.rmaxn_intake_fan); | ||
1024 | state->intake_rpm = intake; | ||
1025 | |||
1026 | do_set_fans: | ||
1027 | DBG("** CPU %d RPM: %d Ex, %d In, overtemp: %d\n", | ||
1028 | state->index, (int)state->rpm, intake, state->overtemp); | ||
1029 | |||
1030 | /* We should check for errors, shouldn't we ? But then, what | ||
1031 | * do we do once the error occurs ? For FCU notified fan | ||
1032 | * failures (-EFAULT) we probably want to notify userland | ||
1033 | * some way... | ||
1034 | */ | ||
1035 | if (state->index == 0) { | ||
1036 | set_rpm_fan(CPUA_INTAKE_FAN_RPM_INDEX, intake); | ||
1037 | set_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, state->rpm); | ||
1038 | } else { | ||
1039 | set_rpm_fan(CPUB_INTAKE_FAN_RPM_INDEX, intake); | ||
1040 | set_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, state->rpm); | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | static void do_monitor_cpu_rack(struct cpu_pid_state *state) | ||
1045 | { | ||
1046 | s32 temp, power, fan_min; | ||
1047 | int rc; | ||
1048 | |||
1049 | /* Read current fan status */ | ||
1050 | rc = do_read_one_cpu_values(state, &temp, &power); | ||
1051 | if (rc < 0) { | ||
1052 | /* XXX What do we do now ? */ | ||
1053 | } | ||
1054 | |||
1055 | /* Check tmax, increment overtemp if we are there. At tmax+8, we go | ||
1056 | * full blown immediately and try to trigger a shutdown | ||
1057 | */ | ||
1058 | if (temp >= ((state->mpu.tmax + 8) << 16)) { | ||
1059 | printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum" | ||
1060 | " (%d) !\n", | ||
1061 | state->index, temp >> 16); | ||
1062 | state->overtemp = CPU_MAX_OVERTEMP; | ||
1063 | } else if (temp > (state->mpu.tmax << 16)) | ||
1064 | state->overtemp++; | ||
1065 | else | ||
1066 | state->overtemp = 0; | ||
1067 | if (state->overtemp >= CPU_MAX_OVERTEMP) | ||
1068 | critical_state = 1; | ||
1069 | if (state->overtemp > 0) { | ||
1070 | state->rpm = state->intake_rpm = state->mpu.rmaxn_intake_fan; | ||
1071 | goto do_set_fans; | ||
1072 | } | ||
1073 | |||
1074 | /* Do the PID */ | ||
1075 | do_cpu_pid(state, temp, power); | ||
1076 | |||
1077 | /* Check clamp from dimms */ | ||
1078 | fan_min = dimm_output_clamp; | ||
1079 | fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan); | ||
1080 | |||
1081 | state->rpm = max(state->rpm, (int)fan_min); | ||
1082 | state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan); | ||
1083 | state->intake_rpm = state->rpm; | ||
1084 | |||
1085 | do_set_fans: | ||
1086 | DBG("** CPU %d RPM: %d overtemp: %d\n", | ||
1087 | state->index, (int)state->rpm, state->overtemp); | ||
1088 | |||
1089 | /* We should check for errors, shouldn't we ? But then, what | ||
1090 | * do we do once the error occurs ? For FCU notified fan | ||
1091 | * failures (-EFAULT) we probably want to notify userland | ||
1092 | * some way... | ||
1093 | */ | ||
1094 | if (state->index == 0) { | ||
1095 | set_rpm_fan(CPU_A1_FAN_RPM_INDEX, state->rpm); | ||
1096 | set_rpm_fan(CPU_A2_FAN_RPM_INDEX, state->rpm); | ||
1097 | set_rpm_fan(CPU_A3_FAN_RPM_INDEX, state->rpm); | ||
1098 | } else { | ||
1099 | set_rpm_fan(CPU_B1_FAN_RPM_INDEX, state->rpm); | ||
1100 | set_rpm_fan(CPU_B2_FAN_RPM_INDEX, state->rpm); | ||
1101 | set_rpm_fan(CPU_B3_FAN_RPM_INDEX, state->rpm); | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | /* | ||
1106 | * Initialize the state structure for one CPU control loop | ||
1107 | */ | ||
1108 | static int init_cpu_state(struct cpu_pid_state *state, int index) | ||
1109 | { | ||
1110 | state->index = index; | ||
1111 | state->first = 1; | ||
1112 | state->rpm = (cpu_pid_type == CPU_PID_TYPE_RACKMAC) ? 4000 : 1000; | ||
1113 | state->overtemp = 0; | ||
1114 | state->adc_config = 0x00; | ||
1115 | |||
1116 | |||
1117 | if (index == 0) | ||
1118 | state->monitor = attach_i2c_chip(SUPPLY_MONITOR_ID, "CPU0_monitor"); | ||
1119 | else if (index == 1) | ||
1120 | state->monitor = attach_i2c_chip(SUPPLY_MONITORB_ID, "CPU1_monitor"); | ||
1121 | if (state->monitor == NULL) | ||
1122 | goto fail; | ||
1123 | |||
1124 | if (read_eeprom(index, &state->mpu)) | ||
1125 | goto fail; | ||
1126 | |||
1127 | state->count_power = state->mpu.tguardband; | ||
1128 | if (state->count_power > CPU_POWER_HISTORY_SIZE) { | ||
1129 | printk(KERN_WARNING "Warning ! too many power history slots\n"); | ||
1130 | state->count_power = CPU_POWER_HISTORY_SIZE; | ||
1131 | } | ||
1132 | DBG("CPU %d Using %d power history entries\n", index, state->count_power); | ||
1133 | |||
1134 | if (index == 0) { | ||
1135 | device_create_file(&of_dev->dev, &dev_attr_cpu0_temperature); | ||
1136 | device_create_file(&of_dev->dev, &dev_attr_cpu0_voltage); | ||
1137 | device_create_file(&of_dev->dev, &dev_attr_cpu0_current); | ||
1138 | device_create_file(&of_dev->dev, &dev_attr_cpu0_exhaust_fan_rpm); | ||
1139 | device_create_file(&of_dev->dev, &dev_attr_cpu0_intake_fan_rpm); | ||
1140 | } else { | ||
1141 | device_create_file(&of_dev->dev, &dev_attr_cpu1_temperature); | ||
1142 | device_create_file(&of_dev->dev, &dev_attr_cpu1_voltage); | ||
1143 | device_create_file(&of_dev->dev, &dev_attr_cpu1_current); | ||
1144 | device_create_file(&of_dev->dev, &dev_attr_cpu1_exhaust_fan_rpm); | ||
1145 | device_create_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm); | ||
1146 | } | ||
1147 | |||
1148 | return 0; | ||
1149 | fail: | ||
1150 | if (state->monitor) | ||
1151 | detach_i2c_chip(state->monitor); | ||
1152 | state->monitor = NULL; | ||
1153 | |||
1154 | return -ENODEV; | ||
1155 | } | ||
1156 | |||
1157 | /* | ||
1158 | * Dispose of the state data for one CPU control loop | ||
1159 | */ | ||
1160 | static void dispose_cpu_state(struct cpu_pid_state *state) | ||
1161 | { | ||
1162 | if (state->monitor == NULL) | ||
1163 | return; | ||
1164 | |||
1165 | if (state->index == 0) { | ||
1166 | device_remove_file(&of_dev->dev, &dev_attr_cpu0_temperature); | ||
1167 | device_remove_file(&of_dev->dev, &dev_attr_cpu0_voltage); | ||
1168 | device_remove_file(&of_dev->dev, &dev_attr_cpu0_current); | ||
1169 | device_remove_file(&of_dev->dev, &dev_attr_cpu0_exhaust_fan_rpm); | ||
1170 | device_remove_file(&of_dev->dev, &dev_attr_cpu0_intake_fan_rpm); | ||
1171 | } else { | ||
1172 | device_remove_file(&of_dev->dev, &dev_attr_cpu1_temperature); | ||
1173 | device_remove_file(&of_dev->dev, &dev_attr_cpu1_voltage); | ||
1174 | device_remove_file(&of_dev->dev, &dev_attr_cpu1_current); | ||
1175 | device_remove_file(&of_dev->dev, &dev_attr_cpu1_exhaust_fan_rpm); | ||
1176 | device_remove_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm); | ||
1177 | } | ||
1178 | |||
1179 | detach_i2c_chip(state->monitor); | ||
1180 | state->monitor = NULL; | ||
1181 | } | ||
1182 | |||
1183 | /* | ||
1184 | * Motherboard backside & U3 heatsink fan control loop | ||
1185 | */ | ||
1186 | static void do_monitor_backside(struct backside_pid_state *state) | ||
1187 | { | ||
1188 | s32 temp, integral, derivative, fan_min; | ||
1189 | s64 integ_p, deriv_p, prop_p, sum; | ||
1190 | int i, rc; | ||
1191 | |||
1192 | if (--state->ticks != 0) | ||
1193 | return; | ||
1194 | state->ticks = backside_params.interval; | ||
1195 | |||
1196 | DBG("backside:\n"); | ||
1197 | |||
1198 | /* Check fan status */ | ||
1199 | rc = get_pwm_fan(BACKSIDE_FAN_PWM_INDEX); | ||
1200 | if (rc < 0) { | ||
1201 | printk(KERN_WARNING "Error %d reading backside fan !\n", rc); | ||
1202 | /* XXX What do we do now ? */ | ||
1203 | } else | ||
1204 | state->pwm = rc; | ||
1205 | DBG(" current pwm: %d\n", state->pwm); | ||
1206 | |||
1207 | /* Get some sensor readings */ | ||
1208 | temp = i2c_smbus_read_byte_data(state->monitor, MAX6690_EXT_TEMP) << 16; | ||
1209 | state->last_temp = temp; | ||
1210 | DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), | ||
1211 | FIX32TOPRINT(backside_params.input_target)); | ||
1212 | |||
1213 | /* Store temperature and error in history array */ | ||
1214 | state->cur_sample = (state->cur_sample + 1) % BACKSIDE_PID_HISTORY_SIZE; | ||
1215 | state->sample_history[state->cur_sample] = temp; | ||
1216 | state->error_history[state->cur_sample] = temp - backside_params.input_target; | ||
1217 | |||
1218 | /* If first loop, fill the history table */ | ||
1219 | if (state->first) { | ||
1220 | for (i = 0; i < (BACKSIDE_PID_HISTORY_SIZE - 1); i++) { | ||
1221 | state->cur_sample = (state->cur_sample + 1) % | ||
1222 | BACKSIDE_PID_HISTORY_SIZE; | ||
1223 | state->sample_history[state->cur_sample] = temp; | ||
1224 | state->error_history[state->cur_sample] = | ||
1225 | temp - backside_params.input_target; | ||
1226 | } | ||
1227 | state->first = 0; | ||
1228 | } | ||
1229 | |||
1230 | /* Calculate the integral term */ | ||
1231 | sum = 0; | ||
1232 | integral = 0; | ||
1233 | for (i = 0; i < BACKSIDE_PID_HISTORY_SIZE; i++) | ||
1234 | integral += state->error_history[i]; | ||
1235 | integral *= backside_params.interval; | ||
1236 | DBG(" integral: %08x\n", integral); | ||
1237 | integ_p = ((s64)backside_params.G_r) * (s64)integral; | ||
1238 | DBG(" integ_p: %d\n", (int)(integ_p >> 36)); | ||
1239 | sum += integ_p; | ||
1240 | |||
1241 | /* Calculate the derivative term */ | ||
1242 | derivative = state->error_history[state->cur_sample] - | ||
1243 | state->error_history[(state->cur_sample + BACKSIDE_PID_HISTORY_SIZE - 1) | ||
1244 | % BACKSIDE_PID_HISTORY_SIZE]; | ||
1245 | derivative /= backside_params.interval; | ||
1246 | deriv_p = ((s64)backside_params.G_d) * (s64)derivative; | ||
1247 | DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); | ||
1248 | sum += deriv_p; | ||
1249 | |||
1250 | /* Calculate the proportional term */ | ||
1251 | prop_p = ((s64)backside_params.G_p) * (s64)(state->error_history[state->cur_sample]); | ||
1252 | DBG(" prop_p: %d\n", (int)(prop_p >> 36)); | ||
1253 | sum += prop_p; | ||
1254 | |||
1255 | /* Scale sum */ | ||
1256 | sum >>= 36; | ||
1257 | |||
1258 | DBG(" sum: %d\n", (int)sum); | ||
1259 | if (backside_params.additive) | ||
1260 | state->pwm += (s32)sum; | ||
1261 | else | ||
1262 | state->pwm = sum; | ||
1263 | |||
1264 | /* Check for clamp */ | ||
1265 | fan_min = (dimm_output_clamp * 100) / 14000; | ||
1266 | fan_min = max(fan_min, backside_params.output_min); | ||
1267 | |||
1268 | state->pwm = max(state->pwm, fan_min); | ||
1269 | state->pwm = min(state->pwm, backside_params.output_max); | ||
1270 | |||
1271 | DBG("** BACKSIDE PWM: %d\n", (int)state->pwm); | ||
1272 | set_pwm_fan(BACKSIDE_FAN_PWM_INDEX, state->pwm); | ||
1273 | } | ||
1274 | |||
1275 | /* | ||
1276 | * Initialize the state structure for the backside fan control loop | ||
1277 | */ | ||
1278 | static int init_backside_state(struct backside_pid_state *state) | ||
1279 | { | ||
1280 | struct device_node *u3; | ||
1281 | int u3h = 1; /* conservative by default */ | ||
1282 | |||
1283 | /* | ||
1284 | * There are different PID params for machines with U3 and machines | ||
1285 | * with U3H, pick the right ones now | ||
1286 | */ | ||
1287 | u3 = of_find_node_by_path("/u3@0,f8000000"); | ||
1288 | if (u3 != NULL) { | ||
1289 | u32 *vers = (u32 *)get_property(u3, "device-rev", NULL); | ||
1290 | if (vers) | ||
1291 | if (((*vers) & 0x3f) < 0x34) | ||
1292 | u3h = 0; | ||
1293 | of_node_put(u3); | ||
1294 | } | ||
1295 | |||
1296 | if (rackmac) { | ||
1297 | backside_params.G_d = BACKSIDE_PID_RACK_G_d; | ||
1298 | backside_params.input_target = BACKSIDE_PID_RACK_INPUT_TARGET; | ||
1299 | backside_params.output_min = BACKSIDE_PID_U3H_OUTPUT_MIN; | ||
1300 | backside_params.interval = BACKSIDE_PID_RACK_INTERVAL; | ||
1301 | backside_params.G_p = BACKSIDE_PID_RACK_G_p; | ||
1302 | backside_params.G_r = BACKSIDE_PID_G_r; | ||
1303 | backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX; | ||
1304 | backside_params.additive = 0; | ||
1305 | } else if (u3h) { | ||
1306 | backside_params.G_d = BACKSIDE_PID_U3H_G_d; | ||
1307 | backside_params.input_target = BACKSIDE_PID_U3H_INPUT_TARGET; | ||
1308 | backside_params.output_min = BACKSIDE_PID_U3H_OUTPUT_MIN; | ||
1309 | backside_params.interval = BACKSIDE_PID_INTERVAL; | ||
1310 | backside_params.G_p = BACKSIDE_PID_G_p; | ||
1311 | backside_params.G_r = BACKSIDE_PID_G_r; | ||
1312 | backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX; | ||
1313 | backside_params.additive = 1; | ||
1314 | } else { | ||
1315 | backside_params.G_d = BACKSIDE_PID_U3_G_d; | ||
1316 | backside_params.input_target = BACKSIDE_PID_U3_INPUT_TARGET; | ||
1317 | backside_params.output_min = BACKSIDE_PID_U3_OUTPUT_MIN; | ||
1318 | backside_params.interval = BACKSIDE_PID_INTERVAL; | ||
1319 | backside_params.G_p = BACKSIDE_PID_G_p; | ||
1320 | backside_params.G_r = BACKSIDE_PID_G_r; | ||
1321 | backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX; | ||
1322 | backside_params.additive = 1; | ||
1323 | } | ||
1324 | |||
1325 | state->ticks = 1; | ||
1326 | state->first = 1; | ||
1327 | state->pwm = 50; | ||
1328 | |||
1329 | state->monitor = attach_i2c_chip(BACKSIDE_MAX_ID, "backside_temp"); | ||
1330 | if (state->monitor == NULL) | ||
1331 | return -ENODEV; | ||
1332 | |||
1333 | device_create_file(&of_dev->dev, &dev_attr_backside_temperature); | ||
1334 | device_create_file(&of_dev->dev, &dev_attr_backside_fan_pwm); | ||
1335 | |||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | /* | ||
1340 | * Dispose of the state data for the backside control loop | ||
1341 | */ | ||
1342 | static void dispose_backside_state(struct backside_pid_state *state) | ||
1343 | { | ||
1344 | if (state->monitor == NULL) | ||
1345 | return; | ||
1346 | |||
1347 | device_remove_file(&of_dev->dev, &dev_attr_backside_temperature); | ||
1348 | device_remove_file(&of_dev->dev, &dev_attr_backside_fan_pwm); | ||
1349 | |||
1350 | detach_i2c_chip(state->monitor); | ||
1351 | state->monitor = NULL; | ||
1352 | } | ||
1353 | |||
1354 | /* | ||
1355 | * Drives bay fan control loop | ||
1356 | */ | ||
1357 | static void do_monitor_drives(struct drives_pid_state *state) | ||
1358 | { | ||
1359 | s32 temp, integral, derivative; | ||
1360 | s64 integ_p, deriv_p, prop_p, sum; | ||
1361 | int i, rc; | ||
1362 | |||
1363 | if (--state->ticks != 0) | ||
1364 | return; | ||
1365 | state->ticks = DRIVES_PID_INTERVAL; | ||
1366 | |||
1367 | DBG("drives:\n"); | ||
1368 | |||
1369 | /* Check fan status */ | ||
1370 | rc = get_rpm_fan(DRIVES_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED); | ||
1371 | if (rc < 0) { | ||
1372 | printk(KERN_WARNING "Error %d reading drives fan !\n", rc); | ||
1373 | /* XXX What do we do now ? */ | ||
1374 | } else | ||
1375 | state->rpm = rc; | ||
1376 | DBG(" current rpm: %d\n", state->rpm); | ||
1377 | |||
1378 | /* Get some sensor readings */ | ||
1379 | temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8; | ||
1380 | state->last_temp = temp; | ||
1381 | DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), | ||
1382 | FIX32TOPRINT(DRIVES_PID_INPUT_TARGET)); | ||
1383 | |||
1384 | /* Store temperature and error in history array */ | ||
1385 | state->cur_sample = (state->cur_sample + 1) % DRIVES_PID_HISTORY_SIZE; | ||
1386 | state->sample_history[state->cur_sample] = temp; | ||
1387 | state->error_history[state->cur_sample] = temp - DRIVES_PID_INPUT_TARGET; | ||
1388 | |||
1389 | /* If first loop, fill the history table */ | ||
1390 | if (state->first) { | ||
1391 | for (i = 0; i < (DRIVES_PID_HISTORY_SIZE - 1); i++) { | ||
1392 | state->cur_sample = (state->cur_sample + 1) % | ||
1393 | DRIVES_PID_HISTORY_SIZE; | ||
1394 | state->sample_history[state->cur_sample] = temp; | ||
1395 | state->error_history[state->cur_sample] = | ||
1396 | temp - DRIVES_PID_INPUT_TARGET; | ||
1397 | } | ||
1398 | state->first = 0; | ||
1399 | } | ||
1400 | |||
1401 | /* Calculate the integral term */ | ||
1402 | sum = 0; | ||
1403 | integral = 0; | ||
1404 | for (i = 0; i < DRIVES_PID_HISTORY_SIZE; i++) | ||
1405 | integral += state->error_history[i]; | ||
1406 | integral *= DRIVES_PID_INTERVAL; | ||
1407 | DBG(" integral: %08x\n", integral); | ||
1408 | integ_p = ((s64)DRIVES_PID_G_r) * (s64)integral; | ||
1409 | DBG(" integ_p: %d\n", (int)(integ_p >> 36)); | ||
1410 | sum += integ_p; | ||
1411 | |||
1412 | /* Calculate the derivative term */ | ||
1413 | derivative = state->error_history[state->cur_sample] - | ||
1414 | state->error_history[(state->cur_sample + DRIVES_PID_HISTORY_SIZE - 1) | ||
1415 | % DRIVES_PID_HISTORY_SIZE]; | ||
1416 | derivative /= DRIVES_PID_INTERVAL; | ||
1417 | deriv_p = ((s64)DRIVES_PID_G_d) * (s64)derivative; | ||
1418 | DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); | ||
1419 | sum += deriv_p; | ||
1420 | |||
1421 | /* Calculate the proportional term */ | ||
1422 | prop_p = ((s64)DRIVES_PID_G_p) * (s64)(state->error_history[state->cur_sample]); | ||
1423 | DBG(" prop_p: %d\n", (int)(prop_p >> 36)); | ||
1424 | sum += prop_p; | ||
1425 | |||
1426 | /* Scale sum */ | ||
1427 | sum >>= 36; | ||
1428 | |||
1429 | DBG(" sum: %d\n", (int)sum); | ||
1430 | state->rpm += (s32)sum; | ||
1431 | |||
1432 | state->rpm = max(state->rpm, DRIVES_PID_OUTPUT_MIN); | ||
1433 | state->rpm = min(state->rpm, DRIVES_PID_OUTPUT_MAX); | ||
1434 | |||
1435 | DBG("** DRIVES RPM: %d\n", (int)state->rpm); | ||
1436 | set_rpm_fan(DRIVES_FAN_RPM_INDEX, state->rpm); | ||
1437 | } | ||
1438 | |||
1439 | /* | ||
1440 | * Initialize the state structure for the drives bay fan control loop | ||
1441 | */ | ||
1442 | static int init_drives_state(struct drives_pid_state *state) | ||
1443 | { | ||
1444 | state->ticks = 1; | ||
1445 | state->first = 1; | ||
1446 | state->rpm = 1000; | ||
1447 | |||
1448 | state->monitor = attach_i2c_chip(DRIVES_DALLAS_ID, "drives_temp"); | ||
1449 | if (state->monitor == NULL) | ||
1450 | return -ENODEV; | ||
1451 | |||
1452 | device_create_file(&of_dev->dev, &dev_attr_drives_temperature); | ||
1453 | device_create_file(&of_dev->dev, &dev_attr_drives_fan_rpm); | ||
1454 | |||
1455 | return 0; | ||
1456 | } | ||
1457 | |||
1458 | /* | ||
1459 | * Dispose of the state data for the drives control loop | ||
1460 | */ | ||
1461 | static void dispose_drives_state(struct drives_pid_state *state) | ||
1462 | { | ||
1463 | if (state->monitor == NULL) | ||
1464 | return; | ||
1465 | |||
1466 | device_remove_file(&of_dev->dev, &dev_attr_drives_temperature); | ||
1467 | device_remove_file(&of_dev->dev, &dev_attr_drives_fan_rpm); | ||
1468 | |||
1469 | detach_i2c_chip(state->monitor); | ||
1470 | state->monitor = NULL; | ||
1471 | } | ||
1472 | |||
1473 | /* | ||
1474 | * DIMMs temp control loop | ||
1475 | */ | ||
1476 | static void do_monitor_dimms(struct dimm_pid_state *state) | ||
1477 | { | ||
1478 | s32 temp, integral, derivative, fan_min; | ||
1479 | s64 integ_p, deriv_p, prop_p, sum; | ||
1480 | int i; | ||
1481 | |||
1482 | if (--state->ticks != 0) | ||
1483 | return; | ||
1484 | state->ticks = DIMM_PID_INTERVAL; | ||
1485 | |||
1486 | DBG("DIMM:\n"); | ||
1487 | |||
1488 | DBG(" current value: %d\n", state->output); | ||
1489 | |||
1490 | temp = read_lm87_reg(state->monitor, LM87_INT_TEMP); | ||
1491 | if (temp < 0) | ||
1492 | return; | ||
1493 | temp <<= 16; | ||
1494 | state->last_temp = temp; | ||
1495 | DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), | ||
1496 | FIX32TOPRINT(DIMM_PID_INPUT_TARGET)); | ||
1497 | |||
1498 | /* Store temperature and error in history array */ | ||
1499 | state->cur_sample = (state->cur_sample + 1) % DIMM_PID_HISTORY_SIZE; | ||
1500 | state->sample_history[state->cur_sample] = temp; | ||
1501 | state->error_history[state->cur_sample] = temp - DIMM_PID_INPUT_TARGET; | ||
1502 | |||
1503 | /* If first loop, fill the history table */ | ||
1504 | if (state->first) { | ||
1505 | for (i = 0; i < (DIMM_PID_HISTORY_SIZE - 1); i++) { | ||
1506 | state->cur_sample = (state->cur_sample + 1) % | ||
1507 | DIMM_PID_HISTORY_SIZE; | ||
1508 | state->sample_history[state->cur_sample] = temp; | ||
1509 | state->error_history[state->cur_sample] = | ||
1510 | temp - DIMM_PID_INPUT_TARGET; | ||
1511 | } | ||
1512 | state->first = 0; | ||
1513 | } | ||
1514 | |||
1515 | /* Calculate the integral term */ | ||
1516 | sum = 0; | ||
1517 | integral = 0; | ||
1518 | for (i = 0; i < DIMM_PID_HISTORY_SIZE; i++) | ||
1519 | integral += state->error_history[i]; | ||
1520 | integral *= DIMM_PID_INTERVAL; | ||
1521 | DBG(" integral: %08x\n", integral); | ||
1522 | integ_p = ((s64)DIMM_PID_G_r) * (s64)integral; | ||
1523 | DBG(" integ_p: %d\n", (int)(integ_p >> 36)); | ||
1524 | sum += integ_p; | ||
1525 | |||
1526 | /* Calculate the derivative term */ | ||
1527 | derivative = state->error_history[state->cur_sample] - | ||
1528 | state->error_history[(state->cur_sample + DIMM_PID_HISTORY_SIZE - 1) | ||
1529 | % DIMM_PID_HISTORY_SIZE]; | ||
1530 | derivative /= DIMM_PID_INTERVAL; | ||
1531 | deriv_p = ((s64)DIMM_PID_G_d) * (s64)derivative; | ||
1532 | DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); | ||
1533 | sum += deriv_p; | ||
1534 | |||
1535 | /* Calculate the proportional term */ | ||
1536 | prop_p = ((s64)DIMM_PID_G_p) * (s64)(state->error_history[state->cur_sample]); | ||
1537 | DBG(" prop_p: %d\n", (int)(prop_p >> 36)); | ||
1538 | sum += prop_p; | ||
1539 | |||
1540 | /* Scale sum */ | ||
1541 | sum >>= 36; | ||
1542 | |||
1543 | DBG(" sum: %d\n", (int)sum); | ||
1544 | state->output = (s32)sum; | ||
1545 | state->output = max(state->output, DIMM_PID_OUTPUT_MIN); | ||
1546 | state->output = min(state->output, DIMM_PID_OUTPUT_MAX); | ||
1547 | dimm_output_clamp = state->output; | ||
1548 | |||
1549 | DBG("** DIMM clamp value: %d\n", (int)state->output); | ||
1550 | |||
1551 | /* Backside PID is only every 5 seconds, force backside fan clamping now */ | ||
1552 | fan_min = (dimm_output_clamp * 100) / 14000; | ||
1553 | fan_min = max(fan_min, backside_params.output_min); | ||
1554 | if (backside_state.pwm < fan_min) { | ||
1555 | backside_state.pwm = fan_min; | ||
1556 | DBG(" -> applying clamp to backside fan now: %d !\n", fan_min); | ||
1557 | set_pwm_fan(BACKSIDE_FAN_PWM_INDEX, fan_min); | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1561 | /* | ||
1562 | * Initialize the state structure for the DIMM temp control loop | ||
1563 | */ | ||
1564 | static int init_dimms_state(struct dimm_pid_state *state) | ||
1565 | { | ||
1566 | state->ticks = 1; | ||
1567 | state->first = 1; | ||
1568 | state->output = 4000; | ||
1569 | |||
1570 | state->monitor = attach_i2c_chip(XSERVE_DIMMS_LM87, "dimms_temp"); | ||
1571 | if (state->monitor == NULL) | ||
1572 | return -ENODEV; | ||
1573 | |||
1574 | device_create_file(&of_dev->dev, &dev_attr_dimms_temperature); | ||
1575 | |||
1576 | return 0; | ||
1577 | } | ||
1578 | |||
1579 | /* | ||
1580 | * Dispose of the state data for the drives control loop | ||
1581 | */ | ||
1582 | static void dispose_dimms_state(struct dimm_pid_state *state) | ||
1583 | { | ||
1584 | if (state->monitor == NULL) | ||
1585 | return; | ||
1586 | |||
1587 | device_remove_file(&of_dev->dev, &dev_attr_dimms_temperature); | ||
1588 | |||
1589 | detach_i2c_chip(state->monitor); | ||
1590 | state->monitor = NULL; | ||
1591 | } | ||
1592 | |||
1593 | static int call_critical_overtemp(void) | ||
1594 | { | ||
1595 | char *argv[] = { critical_overtemp_path, NULL }; | ||
1596 | static char *envp[] = { "HOME=/", | ||
1597 | "TERM=linux", | ||
1598 | "PATH=/sbin:/usr/sbin:/bin:/usr/bin", | ||
1599 | NULL }; | ||
1600 | |||
1601 | return call_usermodehelper(critical_overtemp_path, argv, envp, 0); | ||
1602 | } | ||
1603 | |||
1604 | |||
1605 | /* | ||
1606 | * Here's the kernel thread that calls the various control loops | ||
1607 | */ | ||
1608 | static int main_control_loop(void *x) | ||
1609 | { | ||
1610 | daemonize("kfand"); | ||
1611 | |||
1612 | DBG("main_control_loop started\n"); | ||
1613 | |||
1614 | down(&driver_lock); | ||
1615 | |||
1616 | if (start_fcu() < 0) { | ||
1617 | printk(KERN_ERR "kfand: failed to start FCU\n"); | ||
1618 | up(&driver_lock); | ||
1619 | goto out; | ||
1620 | } | ||
1621 | |||
1622 | /* Set the PCI fan once for now */ | ||
1623 | set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); | ||
1624 | |||
1625 | /* Initialize ADCs */ | ||
1626 | initialize_adc(&cpu_state[0]); | ||
1627 | if (cpu_state[1].monitor != NULL) | ||
1628 | initialize_adc(&cpu_state[1]); | ||
1629 | |||
1630 | up(&driver_lock); | ||
1631 | |||
1632 | while (state == state_attached) { | ||
1633 | unsigned long elapsed, start; | ||
1634 | |||
1635 | start = jiffies; | ||
1636 | |||
1637 | down(&driver_lock); | ||
1638 | |||
1639 | /* First, we always calculate the new DIMMs state on an Xserve */ | ||
1640 | if (rackmac) | ||
1641 | do_monitor_dimms(&dimms_state); | ||
1642 | |||
1643 | /* Then, the CPUs */ | ||
1644 | if (cpu_pid_type == CPU_PID_TYPE_COMBINED) | ||
1645 | do_monitor_cpu_combined(); | ||
1646 | else if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) { | ||
1647 | do_monitor_cpu_rack(&cpu_state[0]); | ||
1648 | if (cpu_state[1].monitor != NULL) | ||
1649 | do_monitor_cpu_rack(&cpu_state[1]); | ||
1650 | // better deal with UP | ||
1651 | } else { | ||
1652 | do_monitor_cpu_split(&cpu_state[0]); | ||
1653 | if (cpu_state[1].monitor != NULL) | ||
1654 | do_monitor_cpu_split(&cpu_state[1]); | ||
1655 | // better deal with UP | ||
1656 | } | ||
1657 | /* Then, the rest */ | ||
1658 | do_monitor_backside(&backside_state); | ||
1659 | if (!rackmac) | ||
1660 | do_monitor_drives(&drives_state); | ||
1661 | up(&driver_lock); | ||
1662 | |||
1663 | if (critical_state == 1) { | ||
1664 | printk(KERN_WARNING "Temperature control detected a critical condition\n"); | ||
1665 | printk(KERN_WARNING "Attempting to shut down...\n"); | ||
1666 | if (call_critical_overtemp()) { | ||
1667 | printk(KERN_WARNING "Can't call %s, power off now!\n", | ||
1668 | critical_overtemp_path); | ||
1669 | machine_power_off(); | ||
1670 | } | ||
1671 | } | ||
1672 | if (critical_state > 0) | ||
1673 | critical_state++; | ||
1674 | if (critical_state > MAX_CRITICAL_STATE) { | ||
1675 | printk(KERN_WARNING "Shutdown timed out, power off now !\n"); | ||
1676 | machine_power_off(); | ||
1677 | } | ||
1678 | |||
1679 | // FIXME: Deal with signals | ||
1680 | set_current_state(TASK_INTERRUPTIBLE); | ||
1681 | elapsed = jiffies - start; | ||
1682 | if (elapsed < HZ) | ||
1683 | schedule_timeout(HZ - elapsed); | ||
1684 | } | ||
1685 | |||
1686 | out: | ||
1687 | DBG("main_control_loop ended\n"); | ||
1688 | |||
1689 | ctrl_task = 0; | ||
1690 | complete_and_exit(&ctrl_complete, 0); | ||
1691 | } | ||
1692 | |||
1693 | /* | ||
1694 | * Dispose the control loops when tearing down | ||
1695 | */ | ||
1696 | static void dispose_control_loops(void) | ||
1697 | { | ||
1698 | dispose_cpu_state(&cpu_state[0]); | ||
1699 | dispose_cpu_state(&cpu_state[1]); | ||
1700 | dispose_backside_state(&backside_state); | ||
1701 | dispose_drives_state(&drives_state); | ||
1702 | dispose_dimms_state(&dimms_state); | ||
1703 | } | ||
1704 | |||
1705 | /* | ||
1706 | * Create the control loops. U3-0 i2c bus is up, so we can now | ||
1707 | * get to the various sensors | ||
1708 | */ | ||
1709 | static int create_control_loops(void) | ||
1710 | { | ||
1711 | struct device_node *np; | ||
1712 | |||
1713 | /* Count CPUs from the device-tree, we don't care how many are | ||
1714 | * actually used by Linux | ||
1715 | */ | ||
1716 | cpu_count = 0; | ||
1717 | for (np = NULL; NULL != (np = of_find_node_by_type(np, "cpu"));) | ||
1718 | cpu_count++; | ||
1719 | |||
1720 | DBG("counted %d CPUs in the device-tree\n", cpu_count); | ||
1721 | |||
1722 | /* Decide the type of PID algorithm to use based on the presence of | ||
1723 | * the pumps, though that may not be the best way, that is good enough | ||
1724 | * for now | ||
1725 | */ | ||
1726 | if (rackmac) | ||
1727 | cpu_pid_type = CPU_PID_TYPE_RACKMAC; | ||
1728 | else if (machine_is_compatible("PowerMac7,3") | ||
1729 | && (cpu_count > 1) | ||
1730 | && fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID | ||
1731 | && fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) { | ||
1732 | printk(KERN_INFO "Liquid cooling pumps detected, using new algorithm !\n"); | ||
1733 | cpu_pid_type = CPU_PID_TYPE_COMBINED; | ||
1734 | } else | ||
1735 | cpu_pid_type = CPU_PID_TYPE_SPLIT; | ||
1736 | |||
1737 | /* Create control loops for everything. If any fail, everything | ||
1738 | * fails | ||
1739 | */ | ||
1740 | if (init_cpu_state(&cpu_state[0], 0)) | ||
1741 | goto fail; | ||
1742 | if (cpu_pid_type == CPU_PID_TYPE_COMBINED) | ||
1743 | fetch_cpu_pumps_minmax(); | ||
1744 | |||
1745 | if (cpu_count > 1 && init_cpu_state(&cpu_state[1], 1)) | ||
1746 | goto fail; | ||
1747 | if (init_backside_state(&backside_state)) | ||
1748 | goto fail; | ||
1749 | if (rackmac && init_dimms_state(&dimms_state)) | ||
1750 | goto fail; | ||
1751 | if (!rackmac && init_drives_state(&drives_state)) | ||
1752 | goto fail; | ||
1753 | |||
1754 | DBG("all control loops up !\n"); | ||
1755 | |||
1756 | return 0; | ||
1757 | |||
1758 | fail: | ||
1759 | DBG("failure creating control loops, disposing\n"); | ||
1760 | |||
1761 | dispose_control_loops(); | ||
1762 | |||
1763 | return -ENODEV; | ||
1764 | } | ||
1765 | |||
1766 | /* | ||
1767 | * Start the control loops after everything is up, that is create | ||
1768 | * the thread that will make them run | ||
1769 | */ | ||
1770 | static void start_control_loops(void) | ||
1771 | { | ||
1772 | init_completion(&ctrl_complete); | ||
1773 | |||
1774 | ctrl_task = kernel_thread(main_control_loop, NULL, SIGCHLD | CLONE_KERNEL); | ||
1775 | } | ||
1776 | |||
1777 | /* | ||
1778 | * Stop the control loops when tearing down | ||
1779 | */ | ||
1780 | static void stop_control_loops(void) | ||
1781 | { | ||
1782 | if (ctrl_task != 0) | ||
1783 | wait_for_completion(&ctrl_complete); | ||
1784 | } | ||
1785 | |||
1786 | /* | ||
1787 | * Attach to the i2c FCU after detecting U3-1 bus | ||
1788 | */ | ||
1789 | static int attach_fcu(void) | ||
1790 | { | ||
1791 | fcu = attach_i2c_chip(FAN_CTRLER_ID, "fcu"); | ||
1792 | if (fcu == NULL) | ||
1793 | return -ENODEV; | ||
1794 | |||
1795 | DBG("FCU attached\n"); | ||
1796 | |||
1797 | return 0; | ||
1798 | } | ||
1799 | |||
1800 | /* | ||
1801 | * Detach from the i2c FCU when tearing down | ||
1802 | */ | ||
1803 | static void detach_fcu(void) | ||
1804 | { | ||
1805 | if (fcu) | ||
1806 | detach_i2c_chip(fcu); | ||
1807 | fcu = NULL; | ||
1808 | } | ||
1809 | |||
1810 | /* | ||
1811 | * Attach to the i2c controller. We probe the various chips based | ||
1812 | * on the device-tree nodes and build everything for the driver to | ||
1813 | * run, we then kick the driver monitoring thread | ||
1814 | */ | ||
1815 | static int therm_pm72_attach(struct i2c_adapter *adapter) | ||
1816 | { | ||
1817 | down(&driver_lock); | ||
1818 | |||
1819 | /* Check state */ | ||
1820 | if (state == state_detached) | ||
1821 | state = state_attaching; | ||
1822 | if (state != state_attaching) { | ||
1823 | up(&driver_lock); | ||
1824 | return 0; | ||
1825 | } | ||
1826 | |||
1827 | /* Check if we are looking for one of these */ | ||
1828 | if (u3_0 == NULL && !strcmp(adapter->name, "u3 0")) { | ||
1829 | u3_0 = adapter; | ||
1830 | DBG("found U3-0\n"); | ||
1831 | if (k2 || !rackmac) | ||
1832 | if (create_control_loops()) | ||
1833 | u3_0 = NULL; | ||
1834 | } else if (u3_1 == NULL && !strcmp(adapter->name, "u3 1")) { | ||
1835 | u3_1 = adapter; | ||
1836 | DBG("found U3-1, attaching FCU\n"); | ||
1837 | if (attach_fcu()) | ||
1838 | u3_1 = NULL; | ||
1839 | } else if (k2 == NULL && !strcmp(adapter->name, "mac-io 0")) { | ||
1840 | k2 = adapter; | ||
1841 | DBG("Found K2\n"); | ||
1842 | if (u3_0 && rackmac) | ||
1843 | if (create_control_loops()) | ||
1844 | k2 = NULL; | ||
1845 | } | ||
1846 | /* We got all we need, start control loops */ | ||
1847 | if (u3_0 != NULL && u3_1 != NULL && (k2 || !rackmac)) { | ||
1848 | DBG("everything up, starting control loops\n"); | ||
1849 | state = state_attached; | ||
1850 | start_control_loops(); | ||
1851 | } | ||
1852 | up(&driver_lock); | ||
1853 | |||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | /* | ||
1858 | * Called on every adapter when the driver or the i2c controller | ||
1859 | * is going away. | ||
1860 | */ | ||
1861 | static int therm_pm72_detach(struct i2c_adapter *adapter) | ||
1862 | { | ||
1863 | down(&driver_lock); | ||
1864 | |||
1865 | if (state != state_detached) | ||
1866 | state = state_detaching; | ||
1867 | |||
1868 | /* Stop control loops if any */ | ||
1869 | DBG("stopping control loops\n"); | ||
1870 | up(&driver_lock); | ||
1871 | stop_control_loops(); | ||
1872 | down(&driver_lock); | ||
1873 | |||
1874 | if (u3_0 != NULL && !strcmp(adapter->name, "u3 0")) { | ||
1875 | DBG("lost U3-0, disposing control loops\n"); | ||
1876 | dispose_control_loops(); | ||
1877 | u3_0 = NULL; | ||
1878 | } | ||
1879 | |||
1880 | if (u3_1 != NULL && !strcmp(adapter->name, "u3 1")) { | ||
1881 | DBG("lost U3-1, detaching FCU\n"); | ||
1882 | detach_fcu(); | ||
1883 | u3_1 = NULL; | ||
1884 | } | ||
1885 | if (u3_0 == NULL && u3_1 == NULL) | ||
1886 | state = state_detached; | ||
1887 | |||
1888 | up(&driver_lock); | ||
1889 | |||
1890 | return 0; | ||
1891 | } | ||
1892 | |||
1893 | static int fan_check_loc_match(const char *loc, int fan) | ||
1894 | { | ||
1895 | char tmp[64]; | ||
1896 | char *c, *e; | ||
1897 | |||
1898 | strlcpy(tmp, fcu_fans[fan].loc, 64); | ||
1899 | |||
1900 | c = tmp; | ||
1901 | for (;;) { | ||
1902 | e = strchr(c, ','); | ||
1903 | if (e) | ||
1904 | *e = 0; | ||
1905 | if (strcmp(loc, c) == 0) | ||
1906 | return 1; | ||
1907 | if (e == NULL) | ||
1908 | break; | ||
1909 | c = e + 1; | ||
1910 | } | ||
1911 | return 0; | ||
1912 | } | ||
1913 | |||
1914 | static void fcu_lookup_fans(struct device_node *fcu_node) | ||
1915 | { | ||
1916 | struct device_node *np = NULL; | ||
1917 | int i; | ||
1918 | |||
1919 | /* The table is filled by default with values that are suitable | ||
1920 | * for the old machines without device-tree informations. We scan | ||
1921 | * the device-tree and override those values with whatever is | ||
1922 | * there | ||
1923 | */ | ||
1924 | |||
1925 | DBG("Looking up FCU controls in device-tree...\n"); | ||
1926 | |||
1927 | while ((np = of_get_next_child(fcu_node, np)) != NULL) { | ||
1928 | int type = -1; | ||
1929 | char *loc; | ||
1930 | u32 *reg; | ||
1931 | |||
1932 | DBG(" control: %s, type: %s\n", np->name, np->type); | ||
1933 | |||
1934 | /* Detect control type */ | ||
1935 | if (!strcmp(np->type, "fan-rpm-control") || | ||
1936 | !strcmp(np->type, "fan-rpm")) | ||
1937 | type = FCU_FAN_RPM; | ||
1938 | if (!strcmp(np->type, "fan-pwm-control") || | ||
1939 | !strcmp(np->type, "fan-pwm")) | ||
1940 | type = FCU_FAN_PWM; | ||
1941 | /* Only care about fans for now */ | ||
1942 | if (type == -1) | ||
1943 | continue; | ||
1944 | |||
1945 | /* Lookup for a matching location */ | ||
1946 | loc = (char *)get_property(np, "location", NULL); | ||
1947 | reg = (u32 *)get_property(np, "reg", NULL); | ||
1948 | if (loc == NULL || reg == NULL) | ||
1949 | continue; | ||
1950 | DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); | ||
1951 | |||
1952 | for (i = 0; i < FCU_FAN_COUNT; i++) { | ||
1953 | int fan_id; | ||
1954 | |||
1955 | if (!fan_check_loc_match(loc, i)) | ||
1956 | continue; | ||
1957 | DBG(" location match, index: %d\n", i); | ||
1958 | fcu_fans[i].id = FCU_FAN_ABSENT_ID; | ||
1959 | if (type != fcu_fans[i].type) { | ||
1960 | printk(KERN_WARNING "therm_pm72: Fan type mismatch " | ||
1961 | "in device-tree for %s\n", np->full_name); | ||
1962 | break; | ||
1963 | } | ||
1964 | if (type == FCU_FAN_RPM) | ||
1965 | fan_id = ((*reg) - 0x10) / 2; | ||
1966 | else | ||
1967 | fan_id = ((*reg) - 0x30) / 2; | ||
1968 | if (fan_id > 7) { | ||
1969 | printk(KERN_WARNING "therm_pm72: Can't parse " | ||
1970 | "fan ID in device-tree for %s\n", np->full_name); | ||
1971 | break; | ||
1972 | } | ||
1973 | DBG(" fan id -> %d, type -> %d\n", fan_id, type); | ||
1974 | fcu_fans[i].id = fan_id; | ||
1975 | } | ||
1976 | } | ||
1977 | |||
1978 | /* Now dump the array */ | ||
1979 | printk(KERN_INFO "Detected fan controls:\n"); | ||
1980 | for (i = 0; i < FCU_FAN_COUNT; i++) { | ||
1981 | if (fcu_fans[i].id == FCU_FAN_ABSENT_ID) | ||
1982 | continue; | ||
1983 | printk(KERN_INFO " %d: %s fan, id %d, location: %s\n", i, | ||
1984 | fcu_fans[i].type == FCU_FAN_RPM ? "RPM" : "PWM", | ||
1985 | fcu_fans[i].id, fcu_fans[i].loc); | ||
1986 | } | ||
1987 | } | ||
1988 | |||
1989 | static int fcu_of_probe(struct of_device* dev, const struct of_match *match) | ||
1990 | { | ||
1991 | int rc; | ||
1992 | |||
1993 | state = state_detached; | ||
1994 | |||
1995 | /* Lookup the fans in the device tree */ | ||
1996 | fcu_lookup_fans(dev->node); | ||
1997 | |||
1998 | /* Add the driver */ | ||
1999 | rc = i2c_add_driver(&therm_pm72_driver); | ||
2000 | if (rc < 0) | ||
2001 | return rc; | ||
2002 | return 0; | ||
2003 | } | ||
2004 | |||
2005 | static int fcu_of_remove(struct of_device* dev) | ||
2006 | { | ||
2007 | i2c_del_driver(&therm_pm72_driver); | ||
2008 | |||
2009 | return 0; | ||
2010 | } | ||
2011 | |||
2012 | static struct of_match fcu_of_match[] = | ||
2013 | { | ||
2014 | { | ||
2015 | .name = OF_ANY_MATCH, | ||
2016 | .type = "fcu", | ||
2017 | .compatible = OF_ANY_MATCH | ||
2018 | }, | ||
2019 | {}, | ||
2020 | }; | ||
2021 | |||
2022 | static struct of_platform_driver fcu_of_platform_driver = | ||
2023 | { | ||
2024 | .name = "temperature", | ||
2025 | .match_table = fcu_of_match, | ||
2026 | .probe = fcu_of_probe, | ||
2027 | .remove = fcu_of_remove | ||
2028 | }; | ||
2029 | |||
2030 | /* | ||
2031 | * Check machine type, attach to i2c controller | ||
2032 | */ | ||
2033 | static int __init therm_pm72_init(void) | ||
2034 | { | ||
2035 | struct device_node *np; | ||
2036 | |||
2037 | rackmac = machine_is_compatible("RackMac3,1"); | ||
2038 | |||
2039 | if (!machine_is_compatible("PowerMac7,2") && | ||
2040 | !machine_is_compatible("PowerMac7,3") && | ||
2041 | !rackmac) | ||
2042 | return -ENODEV; | ||
2043 | |||
2044 | printk(KERN_INFO "PowerMac G5 Thermal control driver %s\n", VERSION); | ||
2045 | |||
2046 | np = of_find_node_by_type(NULL, "fcu"); | ||
2047 | if (np == NULL) { | ||
2048 | /* Some machines have strangely broken device-tree */ | ||
2049 | np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e"); | ||
2050 | if (np == NULL) { | ||
2051 | printk(KERN_ERR "Can't find FCU in device-tree !\n"); | ||
2052 | return -ENODEV; | ||
2053 | } | ||
2054 | } | ||
2055 | of_dev = of_platform_device_create(np, "temperature"); | ||
2056 | if (of_dev == NULL) { | ||
2057 | printk(KERN_ERR "Can't register FCU platform device !\n"); | ||
2058 | return -ENODEV; | ||
2059 | } | ||
2060 | |||
2061 | of_register_driver(&fcu_of_platform_driver); | ||
2062 | |||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | static void __exit therm_pm72_exit(void) | ||
2067 | { | ||
2068 | of_unregister_driver(&fcu_of_platform_driver); | ||
2069 | |||
2070 | if (of_dev) | ||
2071 | of_device_unregister(of_dev); | ||
2072 | } | ||
2073 | |||
2074 | module_init(therm_pm72_init); | ||
2075 | module_exit(therm_pm72_exit); | ||
2076 | |||
2077 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
2078 | MODULE_DESCRIPTION("Driver for Apple's PowerMac G5 thermal control"); | ||
2079 | MODULE_LICENSE("GPL"); | ||
2080 | |||
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h new file mode 100644 index 000000000000..c17e61f9c418 --- /dev/null +++ b/drivers/macintosh/therm_pm72.h | |||
@@ -0,0 +1,297 @@ | |||
1 | #ifndef __THERM_PMAC_7_2_H__ | ||
2 | #define __THERM_PMAC_7_2_H__ | ||
3 | |||
4 | typedef unsigned short fu16; | ||
5 | typedef int fs32; | ||
6 | typedef short fs16; | ||
7 | |||
8 | struct mpu_data | ||
9 | { | ||
10 | u8 signature; /* 0x00 - EEPROM sig. */ | ||
11 | u8 bytes_used; /* 0x01 - Bytes used in eeprom (160 ?) */ | ||
12 | u8 size; /* 0x02 - EEPROM size (256 ?) */ | ||
13 | u8 version; /* 0x03 - EEPROM version */ | ||
14 | u32 data_revision; /* 0x04 - Dataset revision */ | ||
15 | u8 processor_bin_code[3]; /* 0x08 - Processor BIN code */ | ||
16 | u8 bin_code_expansion; /* 0x0b - ??? (padding ?) */ | ||
17 | u8 processor_num; /* 0x0c - Number of CPUs on this MPU */ | ||
18 | u8 input_mul_bus_div; /* 0x0d - Clock input multiplier/bus divider */ | ||
19 | u8 reserved1[2]; /* 0x0e - */ | ||
20 | u32 input_clk_freq_high; /* 0x10 - Input clock frequency high */ | ||
21 | u8 cpu_nb_target_cycles; /* 0x14 - ??? */ | ||
22 | u8 cpu_statlat; /* 0x15 - ??? */ | ||
23 | u8 cpu_snooplat; /* 0x16 - ??? */ | ||
24 | u8 cpu_snoopacc; /* 0x17 - ??? */ | ||
25 | u8 nb_paamwin; /* 0x18 - ??? */ | ||
26 | u8 nb_statlat; /* 0x19 - ??? */ | ||
27 | u8 nb_snooplat; /* 0x1a - ??? */ | ||
28 | u8 nb_snoopwin; /* 0x1b - ??? */ | ||
29 | u8 api_bus_mode; /* 0x1c - ??? */ | ||
30 | u8 reserved2[3]; /* 0x1d - */ | ||
31 | u32 input_clk_freq_low; /* 0x20 - Input clock frequency low */ | ||
32 | u8 processor_card_slot; /* 0x24 - Processor card slot number */ | ||
33 | u8 reserved3[2]; /* 0x25 - */ | ||
34 | u8 padjmax; /* 0x27 - Max power adjustment (Not in OF!) */ | ||
35 | u8 ttarget; /* 0x28 - Target temperature */ | ||
36 | u8 tmax; /* 0x29 - Max temperature */ | ||
37 | u8 pmaxh; /* 0x2a - Max power */ | ||
38 | u8 tguardband; /* 0x2b - Guardband temp ??? Hist. len in OSX */ | ||
39 | fs32 pid_gp; /* 0x2c - PID proportional gain */ | ||
40 | fs32 pid_gr; /* 0x30 - PID reset gain */ | ||
41 | fs32 pid_gd; /* 0x34 - PID derivative gain */ | ||
42 | fu16 voph; /* 0x38 - Vop High */ | ||
43 | fu16 vopl; /* 0x3a - Vop Low */ | ||
44 | fs16 nactual_die; /* 0x3c - nActual Die */ | ||
45 | fs16 nactual_heatsink; /* 0x3e - nActual Heatsink */ | ||
46 | fs16 nactual_system; /* 0x40 - nActual System */ | ||
47 | u16 calibration_flags; /* 0x42 - Calibration flags */ | ||
48 | fu16 mdiode; /* 0x44 - Diode M value (scaling factor) */ | ||
49 | fs16 bdiode; /* 0x46 - Diode B value (offset) */ | ||
50 | fs32 theta_heat_sink; /* 0x48 - Theta heat sink */ | ||
51 | u16 rminn_intake_fan; /* 0x4c - Intake fan min RPM */ | ||
52 | u16 rmaxn_intake_fan; /* 0x4e - Intake fan max RPM */ | ||
53 | u16 rminn_exhaust_fan; /* 0x50 - Exhaust fan min RPM */ | ||
54 | u16 rmaxn_exhaust_fan; /* 0x52 - Exhaust fan max RPM */ | ||
55 | u8 processor_part_num[8]; /* 0x54 - Processor part number XX pumps min/max */ | ||
56 | u32 processor_lot_num; /* 0x5c - Processor lot number */ | ||
57 | u8 orig_card_sernum[0x10]; /* 0x60 - Card original serial number */ | ||
58 | u8 curr_card_sernum[0x10]; /* 0x70 - Card current serial number */ | ||
59 | u8 mlb_sernum[0x18]; /* 0x80 - MLB serial number */ | ||
60 | u32 checksum1; /* 0x98 - */ | ||
61 | u32 checksum2; /* 0x9c - */ | ||
62 | }; /* Total size = 0xa0 */ | ||
63 | |||
64 | /* Display a 16.16 fixed point value */ | ||
65 | #define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) | ||
66 | |||
67 | /* | ||
68 | * Maximum number of seconds to be in critical state (after a | ||
69 | * normal shutdown attempt). If the machine isn't down after | ||
70 | * this counter elapses, we force an immediate machine power | ||
71 | * off. | ||
72 | */ | ||
73 | #define MAX_CRITICAL_STATE 30 | ||
74 | static char * critical_overtemp_path = "/sbin/critical_overtemp"; | ||
75 | |||
76 | /* | ||
77 | * This option is "weird" :) Basically, if you define this to 1 | ||
78 | * the control loop for the RPMs fans (not PWMs) will apply the | ||
79 | * correction factor obtained from the PID to the _actual_ RPM | ||
80 | * speed read from the FCU. | ||
81 | * If you define the below constant to 0, then it will be | ||
82 | * applied to the setpoint RPM speed, that is basically the | ||
83 | * speed we proviously "asked" for. | ||
84 | * | ||
85 | * I'm not sure which of these Apple's algorithm is supposed | ||
86 | * to use | ||
87 | */ | ||
88 | #define RPM_PID_USE_ACTUAL_SPEED 0 | ||
89 | |||
90 | /* | ||
91 | * i2c IDs. Currently, we hard code those and assume that | ||
92 | * the FCU is on U3 bus 1 while all sensors are on U3 bus | ||
93 | * 0. This appear to be safe enough for this first version | ||
94 | * of the driver, though I would accept any clean patch | ||
95 | * doing a better use of the device-tree without turning the | ||
96 | * while i2c registration mecanism into a racy mess | ||
97 | * | ||
98 | * Note: Xserve changed this. We have some bits on the K2 bus, | ||
99 | * which I arbitrarily set to 0x200. Ultimately, we really want | ||
100 | * too lookup these in the device-tree though | ||
101 | */ | ||
102 | #define FAN_CTRLER_ID 0x15e | ||
103 | #define SUPPLY_MONITOR_ID 0x58 | ||
104 | #define SUPPLY_MONITORB_ID 0x5a | ||
105 | #define DRIVES_DALLAS_ID 0x94 | ||
106 | #define BACKSIDE_MAX_ID 0x98 | ||
107 | #define XSERVE_DIMMS_LM87 0x25a | ||
108 | |||
109 | /* | ||
110 | * Some MAX6690, DS1775, LM87 register definitions | ||
111 | */ | ||
112 | #define MAX6690_INT_TEMP 0 | ||
113 | #define MAX6690_EXT_TEMP 1 | ||
114 | #define DS1775_TEMP 0 | ||
115 | #define LM87_INT_TEMP 0x27 | ||
116 | |||
117 | /* | ||
118 | * Scaling factors for the AD7417 ADC converters (except | ||
119 | * for the CPU diode which is obtained from the EEPROM). | ||
120 | * Those values are obtained from the property list of | ||
121 | * the darwin driver | ||
122 | */ | ||
123 | #define ADC_12V_CURRENT_SCALE 0x0320 /* _AD2 */ | ||
124 | #define ADC_CPU_VOLTAGE_SCALE 0x00a0 /* _AD3 */ | ||
125 | #define ADC_CPU_CURRENT_SCALE 0x1f40 /* _AD4 */ | ||
126 | |||
127 | /* | ||
128 | * PID factors for the U3/Backside fan control loop. We have 2 sets | ||
129 | * of values here, one set for U3 and one set for U3H | ||
130 | */ | ||
131 | #define BACKSIDE_FAN_PWM_DEFAULT_ID 1 | ||
132 | #define BACKSIDE_FAN_PWM_INDEX 0 | ||
133 | #define BACKSIDE_PID_U3_G_d 0x02800000 | ||
134 | #define BACKSIDE_PID_U3H_G_d 0x01400000 | ||
135 | #define BACKSIDE_PID_RACK_G_d 0x00500000 | ||
136 | #define BACKSIDE_PID_G_p 0x00500000 | ||
137 | #define BACKSIDE_PID_RACK_G_p 0x0004cccc | ||
138 | #define BACKSIDE_PID_G_r 0x00000000 | ||
139 | #define BACKSIDE_PID_U3_INPUT_TARGET 0x00410000 | ||
140 | #define BACKSIDE_PID_U3H_INPUT_TARGET 0x004b0000 | ||
141 | #define BACKSIDE_PID_RACK_INPUT_TARGET 0x00460000 | ||
142 | #define BACKSIDE_PID_INTERVAL 5 | ||
143 | #define BACKSIDE_PID_RACK_INTERVAL 1 | ||
144 | #define BACKSIDE_PID_OUTPUT_MAX 100 | ||
145 | #define BACKSIDE_PID_U3_OUTPUT_MIN 20 | ||
146 | #define BACKSIDE_PID_U3H_OUTPUT_MIN 20 | ||
147 | #define BACKSIDE_PID_HISTORY_SIZE 2 | ||
148 | |||
149 | struct basckside_pid_params | ||
150 | { | ||
151 | s32 G_d; | ||
152 | s32 G_p; | ||
153 | s32 G_r; | ||
154 | s32 input_target; | ||
155 | s32 output_min; | ||
156 | s32 output_max; | ||
157 | s32 interval; | ||
158 | int additive; | ||
159 | }; | ||
160 | |||
161 | struct backside_pid_state | ||
162 | { | ||
163 | int ticks; | ||
164 | struct i2c_client * monitor; | ||
165 | s32 sample_history[BACKSIDE_PID_HISTORY_SIZE]; | ||
166 | s32 error_history[BACKSIDE_PID_HISTORY_SIZE]; | ||
167 | int cur_sample; | ||
168 | s32 last_temp; | ||
169 | int pwm; | ||
170 | int first; | ||
171 | }; | ||
172 | |||
173 | /* | ||
174 | * PID factors for the Drive Bay fan control loop | ||
175 | */ | ||
176 | #define DRIVES_FAN_RPM_DEFAULT_ID 2 | ||
177 | #define DRIVES_FAN_RPM_INDEX 1 | ||
178 | #define DRIVES_PID_G_d 0x01e00000 | ||
179 | #define DRIVES_PID_G_p 0x00500000 | ||
180 | #define DRIVES_PID_G_r 0x00000000 | ||
181 | #define DRIVES_PID_INPUT_TARGET 0x00280000 | ||
182 | #define DRIVES_PID_INTERVAL 5 | ||
183 | #define DRIVES_PID_OUTPUT_MAX 4000 | ||
184 | #define DRIVES_PID_OUTPUT_MIN 300 | ||
185 | #define DRIVES_PID_HISTORY_SIZE 2 | ||
186 | |||
187 | struct drives_pid_state | ||
188 | { | ||
189 | int ticks; | ||
190 | struct i2c_client * monitor; | ||
191 | s32 sample_history[BACKSIDE_PID_HISTORY_SIZE]; | ||
192 | s32 error_history[BACKSIDE_PID_HISTORY_SIZE]; | ||
193 | int cur_sample; | ||
194 | s32 last_temp; | ||
195 | int rpm; | ||
196 | int first; | ||
197 | }; | ||
198 | |||
199 | #define SLOTS_FAN_PWM_DEFAULT_ID 2 | ||
200 | #define SLOTS_FAN_PWM_INDEX 2 | ||
201 | #define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */ | ||
202 | |||
203 | |||
204 | /* | ||
205 | * PID factors for the Xserve DIMM control loop | ||
206 | */ | ||
207 | #define DIMM_PID_G_d 0 | ||
208 | #define DIMM_PID_G_p 0 | ||
209 | #define DIMM_PID_G_r 0x6553600 | ||
210 | #define DIMM_PID_INPUT_TARGET 3276800 | ||
211 | #define DIMM_PID_INTERVAL 1 | ||
212 | #define DIMM_PID_OUTPUT_MAX 14000 | ||
213 | #define DIMM_PID_OUTPUT_MIN 4000 | ||
214 | #define DIMM_PID_HISTORY_SIZE 20 | ||
215 | |||
216 | struct dimm_pid_state | ||
217 | { | ||
218 | int ticks; | ||
219 | struct i2c_client * monitor; | ||
220 | s32 sample_history[DIMM_PID_HISTORY_SIZE]; | ||
221 | s32 error_history[DIMM_PID_HISTORY_SIZE]; | ||
222 | int cur_sample; | ||
223 | s32 last_temp; | ||
224 | int first; | ||
225 | int output; | ||
226 | }; | ||
227 | |||
228 | |||
229 | |||
230 | /* Desktops */ | ||
231 | |||
232 | #define CPUA_INTAKE_FAN_RPM_DEFAULT_ID 3 | ||
233 | #define CPUA_EXHAUST_FAN_RPM_DEFAULT_ID 4 | ||
234 | #define CPUB_INTAKE_FAN_RPM_DEFAULT_ID 5 | ||
235 | #define CPUB_EXHAUST_FAN_RPM_DEFAULT_ID 6 | ||
236 | |||
237 | #define CPUA_INTAKE_FAN_RPM_INDEX 3 | ||
238 | #define CPUA_EXHAUST_FAN_RPM_INDEX 4 | ||
239 | #define CPUB_INTAKE_FAN_RPM_INDEX 5 | ||
240 | #define CPUB_EXHAUST_FAN_RPM_INDEX 6 | ||
241 | |||
242 | #define CPU_INTAKE_SCALE 0x0000f852 | ||
243 | #define CPU_TEMP_HISTORY_SIZE 2 | ||
244 | #define CPU_POWER_HISTORY_SIZE 10 | ||
245 | #define CPU_PID_INTERVAL 1 | ||
246 | #define CPU_MAX_OVERTEMP 30 | ||
247 | |||
248 | #define CPUA_PUMP_RPM_INDEX 7 | ||
249 | #define CPUB_PUMP_RPM_INDEX 8 | ||
250 | #define CPU_PUMP_OUTPUT_MAX 3200 | ||
251 | #define CPU_PUMP_OUTPUT_MIN 1250 | ||
252 | |||
253 | /* Xserve */ | ||
254 | #define CPU_A1_FAN_RPM_INDEX 9 | ||
255 | #define CPU_A2_FAN_RPM_INDEX 10 | ||
256 | #define CPU_A3_FAN_RPM_INDEX 11 | ||
257 | #define CPU_B1_FAN_RPM_INDEX 12 | ||
258 | #define CPU_B2_FAN_RPM_INDEX 13 | ||
259 | #define CPU_B3_FAN_RPM_INDEX 14 | ||
260 | |||
261 | |||
262 | struct cpu_pid_state | ||
263 | { | ||
264 | int index; | ||
265 | struct i2c_client * monitor; | ||
266 | struct mpu_data mpu; | ||
267 | int overtemp; | ||
268 | s32 temp_history[CPU_TEMP_HISTORY_SIZE]; | ||
269 | int cur_temp; | ||
270 | s32 power_history[CPU_POWER_HISTORY_SIZE]; | ||
271 | s32 error_history[CPU_POWER_HISTORY_SIZE]; | ||
272 | int cur_power; | ||
273 | int count_power; | ||
274 | int rpm; | ||
275 | int intake_rpm; | ||
276 | s32 voltage; | ||
277 | s32 current_a; | ||
278 | s32 last_temp; | ||
279 | s32 last_power; | ||
280 | int first; | ||
281 | u8 adc_config; | ||
282 | s32 pump_min; | ||
283 | s32 pump_max; | ||
284 | }; | ||
285 | |||
286 | /* | ||
287 | * Driver state | ||
288 | */ | ||
289 | enum { | ||
290 | state_detached, | ||
291 | state_attaching, | ||
292 | state_attached, | ||
293 | state_detaching, | ||
294 | }; | ||
295 | |||
296 | |||
297 | #endif /* __THERM_PMAC_7_2_H__ */ | ||
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c new file mode 100644 index 000000000000..c153699d0f84 --- /dev/null +++ b/drivers/macintosh/therm_windtunnel.c | |||
@@ -0,0 +1,531 @@ | |||
1 | /* | ||
2 | * Creation Date: <2003/03/14 20:54:13 samuel> | ||
3 | * Time-stamp: <2004/03/20 14:20:59 samuel> | ||
4 | * | ||
5 | * <therm_windtunnel.c> | ||
6 | * | ||
7 | * The G4 "windtunnel" has a single fan controlled by an | ||
8 | * ADM1030 fan controller and a DS1775 thermostat. | ||
9 | * | ||
10 | * The fan controller is equipped with a temperature sensor | ||
11 | * which measures the case temperature. The DS1775 sensor | ||
12 | * measures the CPU temperature. This driver tunes the | ||
13 | * behavior of the fan. It is based upon empirical observations | ||
14 | * of the 'AppleFan' driver under Mac OS X. | ||
15 | * | ||
16 | * WARNING: This driver has only been testen on Apple's | ||
17 | * 1.25 MHz Dual G4 (March 03). It is tuned for a CPU | ||
18 | * temperatur around 57 C. | ||
19 | * | ||
20 | * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | ||
21 | * | ||
22 | * Loosely based upon 'thermostat.c' written by Benjamin Herrenschmidt | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or | ||
25 | * modify it under the terms of the GNU General Public License | ||
26 | * as published by the Free Software Foundation | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/config.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/sched.h> | ||
37 | #include <linux/i2c.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <asm/prom.h> | ||
41 | #include <asm/machdep.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/sections.h> | ||
45 | #include <asm/of_device.h> | ||
46 | |||
47 | #define LOG_TEMP 0 /* continously log temperature */ | ||
48 | |||
49 | #define I2C_DRIVERID_G4FAN 0x9001 /* fixme */ | ||
50 | |||
51 | static int do_probe( struct i2c_adapter *adapter, int addr, int kind); | ||
52 | |||
53 | /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */ | ||
54 | static unsigned short normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END }; | ||
55 | static unsigned short normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END }; | ||
56 | |||
57 | I2C_CLIENT_INSMOD; | ||
58 | |||
59 | static struct { | ||
60 | volatile int running; | ||
61 | struct completion completion; | ||
62 | pid_t poll_task; | ||
63 | |||
64 | struct semaphore lock; | ||
65 | struct of_device *of_dev; | ||
66 | |||
67 | struct i2c_client *thermostat; | ||
68 | struct i2c_client *fan; | ||
69 | |||
70 | int overheat_temp; /* 100% fan at this temp */ | ||
71 | int overheat_hyst; | ||
72 | int temp; | ||
73 | int casetemp; | ||
74 | int fan_level; /* active fan_table setting */ | ||
75 | |||
76 | int downind; | ||
77 | int upind; | ||
78 | |||
79 | int r0, r1, r20, r23, r25; /* saved register */ | ||
80 | } x; | ||
81 | |||
82 | #define T(x,y) (((x)<<8) | (y)*0x100/10 ) | ||
83 | |||
84 | static struct { | ||
85 | int fan_down_setting; | ||
86 | int temp; | ||
87 | int fan_up_setting; | ||
88 | } fan_table[] = { | ||
89 | { 11, T(0,0), 11 }, /* min fan */ | ||
90 | { 11, T(55,0), 11 }, | ||
91 | { 6, T(55,3), 11 }, | ||
92 | { 7, T(56,0), 11 }, | ||
93 | { 8, T(57,0), 8 }, | ||
94 | { 7, T(58,3), 7 }, | ||
95 | { 6, T(58,8), 6 }, | ||
96 | { 5, T(59,2), 5 }, | ||
97 | { 4, T(59,6), 4 }, | ||
98 | { 3, T(59,9), 3 }, | ||
99 | { 2, T(60,1), 2 }, | ||
100 | { 1, 0xfffff, 1 } /* on fire */ | ||
101 | }; | ||
102 | |||
103 | static void | ||
104 | print_temp( const char *s, int temp ) | ||
105 | { | ||
106 | printk("%s%d.%d C", s ? s : "", temp>>8, (temp & 255)*10/256 ); | ||
107 | } | ||
108 | |||
109 | static ssize_t | ||
110 | show_cpu_temperature( struct device *dev, char *buf ) | ||
111 | { | ||
112 | return sprintf(buf, "%d.%d\n", x.temp>>8, (x.temp & 255)*10/256 ); | ||
113 | } | ||
114 | |||
115 | static ssize_t | ||
116 | show_case_temperature( struct device *dev, char *buf ) | ||
117 | { | ||
118 | return sprintf(buf, "%d.%d\n", x.casetemp>>8, (x.casetemp & 255)*10/256 ); | ||
119 | } | ||
120 | |||
121 | static DEVICE_ATTR(cpu_temperature, S_IRUGO, show_cpu_temperature, NULL ); | ||
122 | static DEVICE_ATTR(case_temperature, S_IRUGO, show_case_temperature, NULL ); | ||
123 | |||
124 | |||
125 | |||
126 | /************************************************************************/ | ||
127 | /* controller thread */ | ||
128 | /************************************************************************/ | ||
129 | |||
130 | static int | ||
131 | write_reg( struct i2c_client *cl, int reg, int data, int len ) | ||
132 | { | ||
133 | u8 tmp[3]; | ||
134 | |||
135 | if( len < 1 || len > 2 || data < 0 ) | ||
136 | return -EINVAL; | ||
137 | |||
138 | tmp[0] = reg; | ||
139 | tmp[1] = (len == 1) ? data : (data >> 8); | ||
140 | tmp[2] = data; | ||
141 | len++; | ||
142 | |||
143 | if( i2c_master_send(cl, tmp, len) != len ) | ||
144 | return -ENODEV; | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int | ||
149 | read_reg( struct i2c_client *cl, int reg, int len ) | ||
150 | { | ||
151 | u8 buf[2]; | ||
152 | |||
153 | if( len != 1 && len != 2 ) | ||
154 | return -EINVAL; | ||
155 | buf[0] = reg; | ||
156 | if( i2c_master_send(cl, buf, 1) != 1 ) | ||
157 | return -ENODEV; | ||
158 | if( i2c_master_recv(cl, buf, len) != len ) | ||
159 | return -ENODEV; | ||
160 | return (len == 2)? ((unsigned int)buf[0] << 8) | buf[1] : buf[0]; | ||
161 | } | ||
162 | |||
163 | static void | ||
164 | tune_fan( int fan_setting ) | ||
165 | { | ||
166 | int val = (fan_setting << 3) | 7; | ||
167 | |||
168 | /* write_reg( x.fan, 0x24, val, 1 ); */ | ||
169 | write_reg( x.fan, 0x25, val, 1 ); | ||
170 | write_reg( x.fan, 0x20, 0, 1 ); | ||
171 | print_temp("CPU-temp: ", x.temp ); | ||
172 | if( x.casetemp ) | ||
173 | print_temp(", Case: ", x.casetemp ); | ||
174 | printk(", Fan: %d (tuned %+d)\n", 11-fan_setting, x.fan_level-fan_setting ); | ||
175 | |||
176 | x.fan_level = fan_setting; | ||
177 | } | ||
178 | |||
179 | static void | ||
180 | poll_temp( void ) | ||
181 | { | ||
182 | int temp, i, level, casetemp; | ||
183 | |||
184 | temp = read_reg( x.thermostat, 0, 2 ); | ||
185 | |||
186 | /* this actually occurs when the computer is loaded */ | ||
187 | if( temp < 0 ) | ||
188 | return; | ||
189 | |||
190 | casetemp = read_reg(x.fan, 0x0b, 1) << 8; | ||
191 | casetemp |= (read_reg(x.fan, 0x06, 1) & 0x7) << 5; | ||
192 | |||
193 | if( LOG_TEMP && x.temp != temp ) { | ||
194 | print_temp("CPU-temp: ", temp ); | ||
195 | print_temp(", Case: ", casetemp ); | ||
196 | printk(", Fan: %d\n", 11-x.fan_level ); | ||
197 | } | ||
198 | x.temp = temp; | ||
199 | x.casetemp = casetemp; | ||
200 | |||
201 | level = -1; | ||
202 | for( i=0; (temp & 0xffff) > fan_table[i].temp ; i++ ) | ||
203 | ; | ||
204 | if( i < x.downind ) | ||
205 | level = fan_table[i].fan_down_setting; | ||
206 | x.downind = i; | ||
207 | |||
208 | for( i=0; (temp & 0xffff) >= fan_table[i+1].temp ; i++ ) | ||
209 | ; | ||
210 | if( x.upind < i ) | ||
211 | level = fan_table[i].fan_up_setting; | ||
212 | x.upind = i; | ||
213 | |||
214 | if( level >= 0 ) | ||
215 | tune_fan( level ); | ||
216 | } | ||
217 | |||
218 | |||
219 | static void | ||
220 | setup_hardware( void ) | ||
221 | { | ||
222 | int val; | ||
223 | |||
224 | /* save registers (if we unload the module) */ | ||
225 | x.r0 = read_reg( x.fan, 0x00, 1 ); | ||
226 | x.r1 = read_reg( x.fan, 0x01, 1 ); | ||
227 | x.r20 = read_reg( x.fan, 0x20, 1 ); | ||
228 | x.r23 = read_reg( x.fan, 0x23, 1 ); | ||
229 | x.r25 = read_reg( x.fan, 0x25, 1 ); | ||
230 | |||
231 | /* improve measurement resolution (convergence time 1.5s) */ | ||
232 | if( (val=read_reg(x.thermostat, 1, 1)) >= 0 ) { | ||
233 | val |= 0x60; | ||
234 | if( write_reg( x.thermostat, 1, val, 1 ) ) | ||
235 | printk("Failed writing config register\n"); | ||
236 | } | ||
237 | /* disable interrupts and TAC input */ | ||
238 | write_reg( x.fan, 0x01, 0x01, 1 ); | ||
239 | /* enable filter */ | ||
240 | write_reg( x.fan, 0x23, 0x91, 1 ); | ||
241 | /* remote temp. controls fan */ | ||
242 | write_reg( x.fan, 0x00, 0x95, 1 ); | ||
243 | |||
244 | /* The thermostat (which besides measureing temperature controls | ||
245 | * has a THERM output which puts the fan on 100%) is usually | ||
246 | * set to kick in at 80 C (chip default). We reduce this a bit | ||
247 | * to be on the safe side (OSX doesn't)... | ||
248 | */ | ||
249 | if( x.overheat_temp == (80 << 8) ) { | ||
250 | x.overheat_temp = 65 << 8; | ||
251 | x.overheat_hyst = 60 << 8; | ||
252 | write_reg( x.thermostat, 2, x.overheat_hyst, 2 ); | ||
253 | write_reg( x.thermostat, 3, x.overheat_temp, 2 ); | ||
254 | |||
255 | print_temp("Reducing overheating limit to ", x.overheat_temp ); | ||
256 | print_temp(" (Hyst: ", x.overheat_hyst ); | ||
257 | printk(")\n"); | ||
258 | } | ||
259 | |||
260 | /* set an initial fan setting */ | ||
261 | x.downind = 0xffff; | ||
262 | x.upind = -1; | ||
263 | /* tune_fan( fan_up_table[x.upind].fan_setting ); */ | ||
264 | |||
265 | device_create_file( &x.of_dev->dev, &dev_attr_cpu_temperature ); | ||
266 | device_create_file( &x.of_dev->dev, &dev_attr_case_temperature ); | ||
267 | } | ||
268 | |||
269 | static void | ||
270 | restore_regs( void ) | ||
271 | { | ||
272 | device_remove_file( &x.of_dev->dev, &dev_attr_cpu_temperature ); | ||
273 | device_remove_file( &x.of_dev->dev, &dev_attr_case_temperature ); | ||
274 | |||
275 | write_reg( x.fan, 0x01, x.r1, 1 ); | ||
276 | write_reg( x.fan, 0x20, x.r20, 1 ); | ||
277 | write_reg( x.fan, 0x23, x.r23, 1 ); | ||
278 | write_reg( x.fan, 0x25, x.r25, 1 ); | ||
279 | write_reg( x.fan, 0x00, x.r0, 1 ); | ||
280 | } | ||
281 | |||
282 | static int | ||
283 | control_loop( void *dummy ) | ||
284 | { | ||
285 | daemonize("g4fand"); | ||
286 | |||
287 | down( &x.lock ); | ||
288 | setup_hardware(); | ||
289 | |||
290 | while( x.running ) { | ||
291 | up( &x.lock ); | ||
292 | |||
293 | msleep_interruptible(8000); | ||
294 | |||
295 | down( &x.lock ); | ||
296 | poll_temp(); | ||
297 | } | ||
298 | |||
299 | restore_regs(); | ||
300 | up( &x.lock ); | ||
301 | |||
302 | complete_and_exit( &x.completion, 0 ); | ||
303 | } | ||
304 | |||
305 | |||
306 | /************************************************************************/ | ||
307 | /* i2c probing and setup */ | ||
308 | /************************************************************************/ | ||
309 | |||
310 | static int | ||
311 | do_attach( struct i2c_adapter *adapter ) | ||
312 | { | ||
313 | int ret = 0; | ||
314 | |||
315 | if( strncmp(adapter->name, "uni-n", 5) ) | ||
316 | return 0; | ||
317 | |||
318 | if( !x.running ) { | ||
319 | ret = i2c_probe( adapter, &addr_data, &do_probe ); | ||
320 | if( x.thermostat && x.fan ) { | ||
321 | x.running = 1; | ||
322 | init_completion( &x.completion ); | ||
323 | x.poll_task = kernel_thread( control_loop, NULL, SIGCHLD | CLONE_KERNEL ); | ||
324 | } | ||
325 | } | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | static int | ||
330 | do_detach( struct i2c_client *client ) | ||
331 | { | ||
332 | int err; | ||
333 | |||
334 | if( (err=i2c_detach_client(client)) ) | ||
335 | printk(KERN_ERR "failed to detach thermostat client\n"); | ||
336 | else { | ||
337 | if( x.running ) { | ||
338 | x.running = 0; | ||
339 | wait_for_completion( &x.completion ); | ||
340 | } | ||
341 | if( client == x.thermostat ) | ||
342 | x.thermostat = NULL; | ||
343 | else if( client == x.fan ) | ||
344 | x.fan = NULL; | ||
345 | else { | ||
346 | printk(KERN_ERR "g4fan: bad client\n"); | ||
347 | } | ||
348 | kfree( client ); | ||
349 | } | ||
350 | return err; | ||
351 | } | ||
352 | |||
353 | static struct i2c_driver g4fan_driver = { | ||
354 | .owner = THIS_MODULE, | ||
355 | .name = "therm_windtunnel", | ||
356 | .id = I2C_DRIVERID_G4FAN, | ||
357 | .flags = I2C_DF_NOTIFY, | ||
358 | .attach_adapter = do_attach, | ||
359 | .detach_client = do_detach, | ||
360 | }; | ||
361 | |||
362 | static int | ||
363 | attach_fan( struct i2c_client *cl ) | ||
364 | { | ||
365 | if( x.fan ) | ||
366 | goto out; | ||
367 | |||
368 | /* check that this is an ADM1030 */ | ||
369 | if( read_reg(cl, 0x3d, 1) != 0x30 || read_reg(cl, 0x3e, 1) != 0x41 ) | ||
370 | goto out; | ||
371 | printk("ADM1030 fan controller [@%02x]\n", cl->addr ); | ||
372 | |||
373 | strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) ); | ||
374 | |||
375 | if( !i2c_attach_client(cl) ) | ||
376 | x.fan = cl; | ||
377 | out: | ||
378 | if( cl != x.fan ) | ||
379 | kfree( cl ); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int | ||
384 | attach_thermostat( struct i2c_client *cl ) | ||
385 | { | ||
386 | int hyst_temp, os_temp, temp; | ||
387 | |||
388 | if( x.thermostat ) | ||
389 | goto out; | ||
390 | |||
391 | if( (temp=read_reg(cl, 0, 2)) < 0 ) | ||
392 | goto out; | ||
393 | |||
394 | /* temperature sanity check */ | ||
395 | if( temp < 0x1600 || temp > 0x3c00 ) | ||
396 | goto out; | ||
397 | hyst_temp = read_reg(cl, 2, 2); | ||
398 | os_temp = read_reg(cl, 3, 2); | ||
399 | if( hyst_temp < 0 || os_temp < 0 ) | ||
400 | goto out; | ||
401 | |||
402 | printk("DS1775 digital thermometer [@%02x]\n", cl->addr ); | ||
403 | print_temp("Temp: ", temp ); | ||
404 | print_temp(" Hyst: ", hyst_temp ); | ||
405 | print_temp(" OS: ", os_temp ); | ||
406 | printk("\n"); | ||
407 | |||
408 | x.temp = temp; | ||
409 | x.overheat_temp = os_temp; | ||
410 | x.overheat_hyst = hyst_temp; | ||
411 | |||
412 | strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) ); | ||
413 | |||
414 | if( !i2c_attach_client(cl) ) | ||
415 | x.thermostat = cl; | ||
416 | out: | ||
417 | if( cl != x.thermostat ) | ||
418 | kfree( cl ); | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int | ||
423 | do_probe( struct i2c_adapter *adapter, int addr, int kind ) | ||
424 | { | ||
425 | struct i2c_client *cl; | ||
426 | |||
427 | if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA | ||
428 | | I2C_FUNC_SMBUS_WRITE_BYTE) ) | ||
429 | return 0; | ||
430 | |||
431 | if( !(cl=kmalloc(sizeof(*cl), GFP_KERNEL)) ) | ||
432 | return -ENOMEM; | ||
433 | memset( cl, 0, sizeof(struct i2c_client) ); | ||
434 | |||
435 | cl->addr = addr; | ||
436 | cl->adapter = adapter; | ||
437 | cl->driver = &g4fan_driver; | ||
438 | cl->flags = 0; | ||
439 | |||
440 | if( addr < 0x48 ) | ||
441 | return attach_fan( cl ); | ||
442 | return attach_thermostat( cl ); | ||
443 | } | ||
444 | |||
445 | |||
446 | /************************************************************************/ | ||
447 | /* initialization / cleanup */ | ||
448 | /************************************************************************/ | ||
449 | |||
450 | static int | ||
451 | therm_of_probe( struct of_device *dev, const struct of_match *match ) | ||
452 | { | ||
453 | return i2c_add_driver( &g4fan_driver ); | ||
454 | } | ||
455 | |||
456 | static int | ||
457 | therm_of_remove( struct of_device *dev ) | ||
458 | { | ||
459 | return i2c_del_driver( &g4fan_driver ); | ||
460 | } | ||
461 | |||
462 | static struct of_match therm_of_match[] = {{ | ||
463 | .name = "fan", | ||
464 | .type = OF_ANY_MATCH, | ||
465 | .compatible = "adm1030" | ||
466 | }, {} | ||
467 | }; | ||
468 | |||
469 | static struct of_platform_driver therm_of_driver = { | ||
470 | .name = "temperature", | ||
471 | .match_table = therm_of_match, | ||
472 | .probe = therm_of_probe, | ||
473 | .remove = therm_of_remove, | ||
474 | }; | ||
475 | |||
476 | struct apple_thermal_info { | ||
477 | u8 id; /* implementation ID */ | ||
478 | u8 fan_count; /* number of fans */ | ||
479 | u8 thermostat_count; /* number of thermostats */ | ||
480 | u8 unused; | ||
481 | }; | ||
482 | |||
483 | static int __init | ||
484 | g4fan_init( void ) | ||
485 | { | ||
486 | struct apple_thermal_info *info; | ||
487 | struct device_node *np; | ||
488 | |||
489 | init_MUTEX( &x.lock ); | ||
490 | |||
491 | if( !(np=of_find_node_by_name(NULL, "power-mgt")) ) | ||
492 | return -ENODEV; | ||
493 | info = (struct apple_thermal_info*)get_property(np, "thermal-info", NULL); | ||
494 | of_node_put(np); | ||
495 | |||
496 | if( !info || !machine_is_compatible("PowerMac3,6") ) | ||
497 | return -ENODEV; | ||
498 | |||
499 | if( info->id != 3 ) { | ||
500 | printk(KERN_ERR "therm_windtunnel: unsupported thermal design %d\n", info->id ); | ||
501 | return -ENODEV; | ||
502 | } | ||
503 | if( !(np=of_find_node_by_name(NULL, "fan")) ) | ||
504 | return -ENODEV; | ||
505 | x.of_dev = of_platform_device_create( np, "temperature" ); | ||
506 | of_node_put( np ); | ||
507 | |||
508 | if( !x.of_dev ) { | ||
509 | printk(KERN_ERR "Can't register fan controller!\n"); | ||
510 | return -ENODEV; | ||
511 | } | ||
512 | |||
513 | of_register_driver( &therm_of_driver ); | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static void __exit | ||
518 | g4fan_exit( void ) | ||
519 | { | ||
520 | of_unregister_driver( &therm_of_driver ); | ||
521 | |||
522 | if( x.of_dev ) | ||
523 | of_device_unregister( x.of_dev ); | ||
524 | } | ||
525 | |||
526 | module_init(g4fan_init); | ||
527 | module_exit(g4fan_exit); | ||
528 | |||
529 | MODULE_AUTHOR("Samuel Rydh <samuel@ibrium.se>"); | ||
530 | MODULE_DESCRIPTION("Apple G4 (windtunnel) fan controller"); | ||
531 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c new file mode 100644 index 000000000000..417deb5de108 --- /dev/null +++ b/drivers/macintosh/via-cuda.c | |||
@@ -0,0 +1,628 @@ | |||
1 | /* | ||
2 | * Device driver for the via-cuda on Apple Powermacs. | ||
3 | * | ||
4 | * The VIA (versatile interface adapter) interfaces to the CUDA, | ||
5 | * a 6805 microprocessor core which controls the ADB (Apple Desktop | ||
6 | * Bus) which connects to the keyboard and mouse. The CUDA also | ||
7 | * controls system power and the RTC (real time clock) chip. | ||
8 | * | ||
9 | * Copyright (C) 1996 Paul Mackerras. | ||
10 | */ | ||
11 | #include <stdarg.h> | ||
12 | #include <linux/config.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/adb.h> | ||
19 | #include <linux/cuda.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #ifdef CONFIG_PPC | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/machdep.h> | ||
25 | #else | ||
26 | #include <asm/macintosh.h> | ||
27 | #include <asm/macints.h> | ||
28 | #include <asm/machw.h> | ||
29 | #include <asm/mac_via.h> | ||
30 | #endif | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | static volatile unsigned char __iomem *via; | ||
36 | static DEFINE_SPINLOCK(cuda_lock); | ||
37 | |||
38 | #ifdef CONFIG_MAC | ||
39 | #define CUDA_IRQ IRQ_MAC_ADB | ||
40 | #define __openfirmware | ||
41 | #define eieio() | ||
42 | #else | ||
43 | #define CUDA_IRQ vias->intrs[0].line | ||
44 | #endif | ||
45 | |||
46 | /* VIA registers - spaced 0x200 bytes apart */ | ||
47 | #define RS 0x200 /* skip between registers */ | ||
48 | #define B 0 /* B-side data */ | ||
49 | #define A RS /* A-side data */ | ||
50 | #define DIRB (2*RS) /* B-side direction (1=output) */ | ||
51 | #define DIRA (3*RS) /* A-side direction (1=output) */ | ||
52 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
53 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
54 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
55 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
56 | #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ | ||
57 | #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ | ||
58 | #define SR (10*RS) /* Shift register */ | ||
59 | #define ACR (11*RS) /* Auxiliary control register */ | ||
60 | #define PCR (12*RS) /* Peripheral control register */ | ||
61 | #define IFR (13*RS) /* Interrupt flag register */ | ||
62 | #define IER (14*RS) /* Interrupt enable register */ | ||
63 | #define ANH (15*RS) /* A-side data, no handshake */ | ||
64 | |||
65 | /* Bits in B data register: all active low */ | ||
66 | #define TREQ 0x08 /* Transfer request (input) */ | ||
67 | #define TACK 0x10 /* Transfer acknowledge (output) */ | ||
68 | #define TIP 0x20 /* Transfer in progress (output) */ | ||
69 | |||
70 | /* Bits in ACR */ | ||
71 | #define SR_CTRL 0x1c /* Shift register control bits */ | ||
72 | #define SR_EXT 0x0c /* Shift on external clock */ | ||
73 | #define SR_OUT 0x10 /* Shift out if 1 */ | ||
74 | |||
75 | /* Bits in IFR and IER */ | ||
76 | #define IER_SET 0x80 /* set bits in IER */ | ||
77 | #define IER_CLR 0 /* clear bits in IER */ | ||
78 | #define SR_INT 0x04 /* Shift register full/empty */ | ||
79 | |||
80 | static enum cuda_state { | ||
81 | idle, | ||
82 | sent_first_byte, | ||
83 | sending, | ||
84 | reading, | ||
85 | read_done, | ||
86 | awaiting_reply | ||
87 | } cuda_state; | ||
88 | |||
89 | static struct adb_request *current_req; | ||
90 | static struct adb_request *last_req; | ||
91 | static unsigned char cuda_rbuf[16]; | ||
92 | static unsigned char *reply_ptr; | ||
93 | static int reading_reply; | ||
94 | static int data_index; | ||
95 | #ifdef CONFIG_PPC | ||
96 | static struct device_node *vias; | ||
97 | #endif | ||
98 | static int cuda_fully_inited = 0; | ||
99 | |||
100 | #ifdef CONFIG_ADB | ||
101 | static int cuda_probe(void); | ||
102 | static int cuda_init(void); | ||
103 | static int cuda_send_request(struct adb_request *req, int sync); | ||
104 | static int cuda_adb_autopoll(int devs); | ||
105 | static int cuda_reset_adb_bus(void); | ||
106 | #endif /* CONFIG_ADB */ | ||
107 | |||
108 | static int cuda_init_via(void); | ||
109 | static void cuda_start(void); | ||
110 | static irqreturn_t cuda_interrupt(int irq, void *arg, struct pt_regs *regs); | ||
111 | static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs); | ||
112 | void cuda_poll(void); | ||
113 | static int cuda_write(struct adb_request *req); | ||
114 | |||
115 | int cuda_request(struct adb_request *req, | ||
116 | void (*done)(struct adb_request *), int nbytes, ...); | ||
117 | |||
118 | #ifdef CONFIG_ADB | ||
119 | struct adb_driver via_cuda_driver = { | ||
120 | "CUDA", | ||
121 | cuda_probe, | ||
122 | cuda_init, | ||
123 | cuda_send_request, | ||
124 | cuda_adb_autopoll, | ||
125 | cuda_poll, | ||
126 | cuda_reset_adb_bus | ||
127 | }; | ||
128 | #endif /* CONFIG_ADB */ | ||
129 | |||
130 | #ifdef CONFIG_PPC | ||
131 | int __init | ||
132 | find_via_cuda(void) | ||
133 | { | ||
134 | int err; | ||
135 | struct adb_request req; | ||
136 | |||
137 | if (vias != 0) | ||
138 | return 1; | ||
139 | vias = find_devices("via-cuda"); | ||
140 | if (vias == 0) | ||
141 | return 0; | ||
142 | if (vias->next != 0) | ||
143 | printk(KERN_WARNING "Warning: only using 1st via-cuda\n"); | ||
144 | |||
145 | #if 0 | ||
146 | { int i; | ||
147 | |||
148 | printk("find_via_cuda: node = %p, addrs =", vias->node); | ||
149 | for (i = 0; i < vias->n_addrs; ++i) | ||
150 | printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size); | ||
151 | printk(", intrs ="); | ||
152 | for (i = 0; i < vias->n_intrs; ++i) | ||
153 | printk(" %x", vias->intrs[i].line); | ||
154 | printk("\n"); } | ||
155 | #endif | ||
156 | |||
157 | if (vias->n_addrs != 1 || vias->n_intrs != 1) { | ||
158 | printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n", | ||
159 | vias->n_addrs, vias->n_intrs); | ||
160 | if (vias->n_addrs < 1 || vias->n_intrs < 1) | ||
161 | return 0; | ||
162 | } | ||
163 | via = ioremap(vias->addrs->address, 0x2000); | ||
164 | |||
165 | cuda_state = idle; | ||
166 | sys_ctrler = SYS_CTRLER_CUDA; | ||
167 | |||
168 | err = cuda_init_via(); | ||
169 | if (err) { | ||
170 | printk(KERN_ERR "cuda_init_via() failed\n"); | ||
171 | via = NULL; | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /* Clear and enable interrupts, but only on PPC. On 68K it's done */ | ||
176 | /* for us by the main VIA driver in arch/m68k/mac/via.c */ | ||
177 | |||
178 | #ifndef CONFIG_MAC | ||
179 | out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ | ||
180 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ | ||
181 | #endif | ||
182 | |||
183 | /* enable autopoll */ | ||
184 | cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); | ||
185 | while (!req.complete) | ||
186 | cuda_poll(); | ||
187 | |||
188 | return 1; | ||
189 | } | ||
190 | #endif /* CONFIG_PPC */ | ||
191 | |||
192 | static int __init via_cuda_start(void) | ||
193 | { | ||
194 | if (via == NULL) | ||
195 | return -ENODEV; | ||
196 | |||
197 | #ifdef CONFIG_PPC | ||
198 | request_OF_resource(vias, 0, NULL); | ||
199 | #endif | ||
200 | |||
201 | if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { | ||
202 | printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); | ||
203 | return -EAGAIN; | ||
204 | } | ||
205 | |||
206 | printk("Macintosh CUDA driver v0.5 for Unified ADB.\n"); | ||
207 | |||
208 | cuda_fully_inited = 1; | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | device_initcall(via_cuda_start); | ||
213 | |||
214 | #ifdef CONFIG_ADB | ||
215 | static int | ||
216 | cuda_probe(void) | ||
217 | { | ||
218 | #ifdef CONFIG_PPC | ||
219 | if (sys_ctrler != SYS_CTRLER_CUDA) | ||
220 | return -ENODEV; | ||
221 | #else | ||
222 | if (macintosh_config->adb_type != MAC_ADB_CUDA) | ||
223 | return -ENODEV; | ||
224 | via = via1; | ||
225 | #endif | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int __init | ||
230 | cuda_init(void) | ||
231 | { | ||
232 | #ifdef CONFIG_PPC | ||
233 | if (via == NULL) | ||
234 | return -ENODEV; | ||
235 | return 0; | ||
236 | #else | ||
237 | int err = cuda_init_via(); | ||
238 | if (err) { | ||
239 | printk(KERN_ERR "cuda_init_via() failed\n"); | ||
240 | return -ENODEV; | ||
241 | } | ||
242 | |||
243 | return via_cuda_start(); | ||
244 | #endif | ||
245 | } | ||
246 | #endif /* CONFIG_ADB */ | ||
247 | |||
248 | #define WAIT_FOR(cond, what) \ | ||
249 | do { \ | ||
250 | int x; \ | ||
251 | for (x = 1000; !(cond); --x) { \ | ||
252 | if (x == 0) { \ | ||
253 | printk("Timeout waiting for " what "\n"); \ | ||
254 | return -ENXIO; \ | ||
255 | } \ | ||
256 | udelay(100); \ | ||
257 | } \ | ||
258 | } while (0) | ||
259 | |||
260 | static int | ||
261 | cuda_init_via(void) | ||
262 | { | ||
263 | out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ); /* TACK & TIP out */ | ||
264 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ | ||
265 | out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ | ||
266 | (void)in_8(&via[SR]); /* clear any left-over data */ | ||
267 | #ifndef CONFIG_MAC | ||
268 | out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ | ||
269 | (void)in_8(&via[IER]); | ||
270 | #endif | ||
271 | |||
272 | /* delay 4ms and then clear any pending interrupt */ | ||
273 | mdelay(4); | ||
274 | (void)in_8(&via[SR]); | ||
275 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | ||
276 | |||
277 | /* sync with the CUDA - assert TACK without TIP */ | ||
278 | out_8(&via[B], in_8(&via[B]) & ~TACK); | ||
279 | |||
280 | /* wait for the CUDA to assert TREQ in response */ | ||
281 | WAIT_FOR((in_8(&via[B]) & TREQ) == 0, "CUDA response to sync"); | ||
282 | |||
283 | /* wait for the interrupt and then clear it */ | ||
284 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); | ||
285 | (void)in_8(&via[SR]); | ||
286 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | ||
287 | |||
288 | /* finish the sync by negating TACK */ | ||
289 | out_8(&via[B], in_8(&via[B]) | TACK); | ||
290 | |||
291 | /* wait for the CUDA to negate TREQ and the corresponding interrupt */ | ||
292 | WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); | ||
293 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); | ||
294 | (void)in_8(&via[SR]); | ||
295 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | ||
296 | out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | #ifdef CONFIG_ADB | ||
302 | /* Send an ADB command */ | ||
303 | static int | ||
304 | cuda_send_request(struct adb_request *req, int sync) | ||
305 | { | ||
306 | int i; | ||
307 | |||
308 | if ((via == NULL) || !cuda_fully_inited) { | ||
309 | req->complete = 1; | ||
310 | return -ENXIO; | ||
311 | } | ||
312 | |||
313 | req->reply_expected = 1; | ||
314 | |||
315 | i = cuda_write(req); | ||
316 | if (i) | ||
317 | return i; | ||
318 | |||
319 | if (sync) { | ||
320 | while (!req->complete) | ||
321 | cuda_poll(); | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | |||
327 | /* Enable/disable autopolling */ | ||
328 | static int | ||
329 | cuda_adb_autopoll(int devs) | ||
330 | { | ||
331 | struct adb_request req; | ||
332 | |||
333 | if ((via == NULL) || !cuda_fully_inited) | ||
334 | return -ENXIO; | ||
335 | |||
336 | cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0)); | ||
337 | while (!req.complete) | ||
338 | cuda_poll(); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | /* Reset adb bus - how do we do this?? */ | ||
343 | static int | ||
344 | cuda_reset_adb_bus(void) | ||
345 | { | ||
346 | struct adb_request req; | ||
347 | |||
348 | if ((via == NULL) || !cuda_fully_inited) | ||
349 | return -ENXIO; | ||
350 | |||
351 | cuda_request(&req, NULL, 2, ADB_PACKET, 0); /* maybe? */ | ||
352 | while (!req.complete) | ||
353 | cuda_poll(); | ||
354 | return 0; | ||
355 | } | ||
356 | #endif /* CONFIG_ADB */ | ||
357 | /* Construct and send a cuda request */ | ||
358 | int | ||
359 | cuda_request(struct adb_request *req, void (*done)(struct adb_request *), | ||
360 | int nbytes, ...) | ||
361 | { | ||
362 | va_list list; | ||
363 | int i; | ||
364 | |||
365 | if (via == NULL) { | ||
366 | req->complete = 1; | ||
367 | return -ENXIO; | ||
368 | } | ||
369 | |||
370 | req->nbytes = nbytes; | ||
371 | req->done = done; | ||
372 | va_start(list, nbytes); | ||
373 | for (i = 0; i < nbytes; ++i) | ||
374 | req->data[i] = va_arg(list, int); | ||
375 | va_end(list); | ||
376 | req->reply_expected = 1; | ||
377 | return cuda_write(req); | ||
378 | } | ||
379 | |||
380 | static int | ||
381 | cuda_write(struct adb_request *req) | ||
382 | { | ||
383 | unsigned long flags; | ||
384 | |||
385 | if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) { | ||
386 | req->complete = 1; | ||
387 | return -EINVAL; | ||
388 | } | ||
389 | req->next = NULL; | ||
390 | req->sent = 0; | ||
391 | req->complete = 0; | ||
392 | req->reply_len = 0; | ||
393 | |||
394 | spin_lock_irqsave(&cuda_lock, flags); | ||
395 | if (current_req != 0) { | ||
396 | last_req->next = req; | ||
397 | last_req = req; | ||
398 | } else { | ||
399 | current_req = req; | ||
400 | last_req = req; | ||
401 | if (cuda_state == idle) | ||
402 | cuda_start(); | ||
403 | } | ||
404 | spin_unlock_irqrestore(&cuda_lock, flags); | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static void | ||
410 | cuda_start(void) | ||
411 | { | ||
412 | struct adb_request *req; | ||
413 | |||
414 | /* assert cuda_state == idle */ | ||
415 | /* get the packet to send */ | ||
416 | req = current_req; | ||
417 | if (req == 0) | ||
418 | return; | ||
419 | if ((in_8(&via[B]) & TREQ) == 0) | ||
420 | return; /* a byte is coming in from the CUDA */ | ||
421 | |||
422 | /* set the shift register to shift out and send a byte */ | ||
423 | out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT); | ||
424 | out_8(&via[SR], req->data[0]); | ||
425 | out_8(&via[B], in_8(&via[B]) & ~TIP); | ||
426 | cuda_state = sent_first_byte; | ||
427 | } | ||
428 | |||
429 | void | ||
430 | cuda_poll(void) | ||
431 | { | ||
432 | unsigned long flags; | ||
433 | |||
434 | /* cuda_interrupt only takes a normal lock, we disable | ||
435 | * interrupts here to avoid re-entering and thus deadlocking. | ||
436 | * An option would be to disable only the IRQ source with | ||
437 | * disable_irq(), would that work on m68k ? --BenH | ||
438 | */ | ||
439 | local_irq_save(flags); | ||
440 | cuda_interrupt(0, NULL, NULL); | ||
441 | local_irq_restore(flags); | ||
442 | } | ||
443 | |||
444 | static irqreturn_t | ||
445 | cuda_interrupt(int irq, void *arg, struct pt_regs *regs) | ||
446 | { | ||
447 | int status; | ||
448 | struct adb_request *req = NULL; | ||
449 | unsigned char ibuf[16]; | ||
450 | int ibuf_len = 0; | ||
451 | int complete = 0; | ||
452 | unsigned char virq; | ||
453 | |||
454 | spin_lock(&cuda_lock); | ||
455 | |||
456 | virq = in_8(&via[IFR]) & 0x7f; | ||
457 | out_8(&via[IFR], virq); | ||
458 | if ((virq & SR_INT) == 0) { | ||
459 | spin_unlock(&cuda_lock); | ||
460 | return IRQ_NONE; | ||
461 | } | ||
462 | |||
463 | status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); | ||
464 | /* printk("cuda_interrupt: state=%d status=%x\n", cuda_state, status); */ | ||
465 | switch (cuda_state) { | ||
466 | case idle: | ||
467 | /* CUDA has sent us the first byte of data - unsolicited */ | ||
468 | if (status != TREQ) | ||
469 | printk("cuda: state=idle, status=%x\n", status); | ||
470 | (void)in_8(&via[SR]); | ||
471 | out_8(&via[B], in_8(&via[B]) & ~TIP); | ||
472 | cuda_state = reading; | ||
473 | reply_ptr = cuda_rbuf; | ||
474 | reading_reply = 0; | ||
475 | break; | ||
476 | |||
477 | case awaiting_reply: | ||
478 | /* CUDA has sent us the first byte of data of a reply */ | ||
479 | if (status != TREQ) | ||
480 | printk("cuda: state=awaiting_reply, status=%x\n", status); | ||
481 | (void)in_8(&via[SR]); | ||
482 | out_8(&via[B], in_8(&via[B]) & ~TIP); | ||
483 | cuda_state = reading; | ||
484 | reply_ptr = current_req->reply; | ||
485 | reading_reply = 1; | ||
486 | break; | ||
487 | |||
488 | case sent_first_byte: | ||
489 | if (status == TREQ + TIP + SR_OUT) { | ||
490 | /* collision */ | ||
491 | out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT); | ||
492 | (void)in_8(&via[SR]); | ||
493 | out_8(&via[B], in_8(&via[B]) | TIP | TACK); | ||
494 | cuda_state = idle; | ||
495 | } else { | ||
496 | /* assert status == TIP + SR_OUT */ | ||
497 | if (status != TIP + SR_OUT) | ||
498 | printk("cuda: state=sent_first_byte status=%x\n", status); | ||
499 | out_8(&via[SR], current_req->data[1]); | ||
500 | out_8(&via[B], in_8(&via[B]) ^ TACK); | ||
501 | data_index = 2; | ||
502 | cuda_state = sending; | ||
503 | } | ||
504 | break; | ||
505 | |||
506 | case sending: | ||
507 | req = current_req; | ||
508 | if (data_index >= req->nbytes) { | ||
509 | out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT); | ||
510 | (void)in_8(&via[SR]); | ||
511 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); | ||
512 | req->sent = 1; | ||
513 | if (req->reply_expected) { | ||
514 | cuda_state = awaiting_reply; | ||
515 | } else { | ||
516 | current_req = req->next; | ||
517 | complete = 1; | ||
518 | /* not sure about this */ | ||
519 | cuda_state = idle; | ||
520 | cuda_start(); | ||
521 | } | ||
522 | } else { | ||
523 | out_8(&via[SR], req->data[data_index++]); | ||
524 | out_8(&via[B], in_8(&via[B]) ^ TACK); | ||
525 | } | ||
526 | break; | ||
527 | |||
528 | case reading: | ||
529 | *reply_ptr++ = in_8(&via[SR]); | ||
530 | if (status == TIP) { | ||
531 | /* that's all folks */ | ||
532 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); | ||
533 | cuda_state = read_done; | ||
534 | } else { | ||
535 | /* assert status == TIP | TREQ */ | ||
536 | if (status != TIP + TREQ) | ||
537 | printk("cuda: state=reading status=%x\n", status); | ||
538 | out_8(&via[B], in_8(&via[B]) ^ TACK); | ||
539 | } | ||
540 | break; | ||
541 | |||
542 | case read_done: | ||
543 | (void)in_8(&via[SR]); | ||
544 | if (reading_reply) { | ||
545 | req = current_req; | ||
546 | req->reply_len = reply_ptr - req->reply; | ||
547 | if (req->data[0] == ADB_PACKET) { | ||
548 | /* Have to adjust the reply from ADB commands */ | ||
549 | if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) { | ||
550 | /* the 0x2 bit indicates no response */ | ||
551 | req->reply_len = 0; | ||
552 | } else { | ||
553 | /* leave just the command and result bytes in the reply */ | ||
554 | req->reply_len -= 2; | ||
555 | memmove(req->reply, req->reply + 2, req->reply_len); | ||
556 | } | ||
557 | } | ||
558 | current_req = req->next; | ||
559 | complete = 1; | ||
560 | } else { | ||
561 | /* This is tricky. We must break the spinlock to call | ||
562 | * cuda_input. However, doing so means we might get | ||
563 | * re-entered from another CPU getting an interrupt | ||
564 | * or calling cuda_poll(). I ended up using the stack | ||
565 | * (it's only for 16 bytes) and moving the actual | ||
566 | * call to cuda_input to outside of the lock. | ||
567 | */ | ||
568 | ibuf_len = reply_ptr - cuda_rbuf; | ||
569 | memcpy(ibuf, cuda_rbuf, ibuf_len); | ||
570 | } | ||
571 | if (status == TREQ) { | ||
572 | out_8(&via[B], in_8(&via[B]) & ~TIP); | ||
573 | cuda_state = reading; | ||
574 | reply_ptr = cuda_rbuf; | ||
575 | reading_reply = 0; | ||
576 | } else { | ||
577 | cuda_state = idle; | ||
578 | cuda_start(); | ||
579 | } | ||
580 | break; | ||
581 | |||
582 | default: | ||
583 | printk("cuda_interrupt: unknown cuda_state %d?\n", cuda_state); | ||
584 | } | ||
585 | spin_unlock(&cuda_lock); | ||
586 | if (complete && req) { | ||
587 | void (*done)(struct adb_request *) = req->done; | ||
588 | mb(); | ||
589 | req->complete = 1; | ||
590 | /* Here, we assume that if the request has a done member, the | ||
591 | * struct request will survive to setting req->complete to 1 | ||
592 | */ | ||
593 | if (done) | ||
594 | (*done)(req); | ||
595 | } | ||
596 | if (ibuf_len) | ||
597 | cuda_input(ibuf, ibuf_len, regs); | ||
598 | return IRQ_HANDLED; | ||
599 | } | ||
600 | |||
601 | static void | ||
602 | cuda_input(unsigned char *buf, int nb, struct pt_regs *regs) | ||
603 | { | ||
604 | int i; | ||
605 | |||
606 | switch (buf[0]) { | ||
607 | case ADB_PACKET: | ||
608 | #ifdef CONFIG_XMON | ||
609 | if (nb == 5 && buf[2] == 0x2c) { | ||
610 | extern int xmon_wants_key, xmon_adb_keycode; | ||
611 | if (xmon_wants_key) { | ||
612 | xmon_adb_keycode = buf[3]; | ||
613 | return; | ||
614 | } | ||
615 | } | ||
616 | #endif /* CONFIG_XMON */ | ||
617 | #ifdef CONFIG_ADB | ||
618 | adb_input(buf+2, nb-2, regs, buf[1] & 0x40); | ||
619 | #endif /* CONFIG_ADB */ | ||
620 | break; | ||
621 | |||
622 | default: | ||
623 | printk("data from cuda (%d bytes):", nb); | ||
624 | for (i = 0; i < nb; ++i) | ||
625 | printk(" %.2x", buf[i]); | ||
626 | printk("\n"); | ||
627 | } | ||
628 | } | ||
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c new file mode 100644 index 000000000000..e9a159ad3022 --- /dev/null +++ b/drivers/macintosh/via-macii.c | |||
@@ -0,0 +1,653 @@ | |||
1 | /* | ||
2 | * Device driver for the via ADB on (many) Mac II-class machines | ||
3 | * | ||
4 | * Based on the original ADB keyboard handler Copyright (c) 1997 Alan Cox | ||
5 | * Also derived from code Copyright (C) 1996 Paul Mackerras. | ||
6 | * | ||
7 | * With various updates provided over the years by Michael Schmitz, | ||
8 | * Guideo Koerber and others. | ||
9 | * | ||
10 | * Rewrite for Unified ADB by Joshua M. Thompson (funaho@jurai.org) | ||
11 | * | ||
12 | * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. | ||
13 | * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org> | ||
14 | * - Big overhaul, should actually work now. | ||
15 | */ | ||
16 | |||
17 | #include <stdarg.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/adb.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <asm/macintosh.h> | ||
27 | #include <asm/macints.h> | ||
28 | #include <asm/machw.h> | ||
29 | #include <asm/mac_via.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/system.h> | ||
32 | |||
33 | static volatile unsigned char *via; | ||
34 | |||
35 | /* VIA registers - spaced 0x200 bytes apart */ | ||
36 | #define RS 0x200 /* skip between registers */ | ||
37 | #define B 0 /* B-side data */ | ||
38 | #define A RS /* A-side data */ | ||
39 | #define DIRB (2*RS) /* B-side direction (1=output) */ | ||
40 | #define DIRA (3*RS) /* A-side direction (1=output) */ | ||
41 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
42 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
43 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
44 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
45 | #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ | ||
46 | #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ | ||
47 | #define SR (10*RS) /* Shift register */ | ||
48 | #define ACR (11*RS) /* Auxiliary control register */ | ||
49 | #define PCR (12*RS) /* Peripheral control register */ | ||
50 | #define IFR (13*RS) /* Interrupt flag register */ | ||
51 | #define IER (14*RS) /* Interrupt enable register */ | ||
52 | #define ANH (15*RS) /* A-side data, no handshake */ | ||
53 | |||
54 | /* Bits in B data register: all active low */ | ||
55 | #define TREQ 0x08 /* Transfer request (input) */ | ||
56 | #define TACK 0x10 /* Transfer acknowledge (output) */ | ||
57 | #define TIP 0x20 /* Transfer in progress (output) */ | ||
58 | #define ST_MASK 0x30 /* mask for selecting ADB state bits */ | ||
59 | |||
60 | /* Bits in ACR */ | ||
61 | #define SR_CTRL 0x1c /* Shift register control bits */ | ||
62 | #define SR_EXT 0x0c /* Shift on external clock */ | ||
63 | #define SR_OUT 0x10 /* Shift out if 1 */ | ||
64 | |||
65 | /* Bits in IFR and IER */ | ||
66 | #define IER_SET 0x80 /* set bits in IER */ | ||
67 | #define IER_CLR 0 /* clear bits in IER */ | ||
68 | #define SR_INT 0x04 /* Shift register full/empty */ | ||
69 | #define SR_DATA 0x08 /* Shift register data */ | ||
70 | #define SR_CLOCK 0x10 /* Shift register clock */ | ||
71 | |||
72 | /* ADB transaction states according to GMHW */ | ||
73 | #define ST_CMD 0x00 /* ADB state: command byte */ | ||
74 | #define ST_EVEN 0x10 /* ADB state: even data byte */ | ||
75 | #define ST_ODD 0x20 /* ADB state: odd data byte */ | ||
76 | #define ST_IDLE 0x30 /* ADB state: idle, nothing to send */ | ||
77 | |||
78 | static int macii_init_via(void); | ||
79 | static void macii_start(void); | ||
80 | static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs); | ||
81 | static void macii_retransmit(int); | ||
82 | static void macii_queue_poll(void); | ||
83 | |||
84 | static int macii_probe(void); | ||
85 | static int macii_init(void); | ||
86 | static int macii_send_request(struct adb_request *req, int sync); | ||
87 | static int macii_write(struct adb_request *req); | ||
88 | static int macii_autopoll(int devs); | ||
89 | static void macii_poll(void); | ||
90 | static int macii_reset_bus(void); | ||
91 | |||
92 | struct adb_driver via_macii_driver = { | ||
93 | "Mac II", | ||
94 | macii_probe, | ||
95 | macii_init, | ||
96 | macii_send_request, | ||
97 | macii_autopoll, | ||
98 | macii_poll, | ||
99 | macii_reset_bus | ||
100 | }; | ||
101 | |||
102 | static enum macii_state { | ||
103 | idle, | ||
104 | sending, | ||
105 | reading, | ||
106 | read_done, | ||
107 | awaiting_reply | ||
108 | } macii_state; | ||
109 | |||
110 | static int need_poll = 0; | ||
111 | static int command_byte = 0; | ||
112 | static int last_reply = 0; | ||
113 | static int last_active = 0; | ||
114 | |||
115 | static struct adb_request *current_req; | ||
116 | static struct adb_request *last_req; | ||
117 | static struct adb_request *retry_req; | ||
118 | static unsigned char reply_buf[16]; | ||
119 | static unsigned char *reply_ptr; | ||
120 | static int reply_len; | ||
121 | static int reading_reply; | ||
122 | static int data_index; | ||
123 | static int first_byte; | ||
124 | static int prefix_len; | ||
125 | static int status = ST_IDLE|TREQ; | ||
126 | static int last_status; | ||
127 | static int driver_running = 0; | ||
128 | |||
129 | /* debug level 10 required for ADB logging (should be && debug_adb, ideally) */ | ||
130 | |||
131 | /* Check for MacII style ADB */ | ||
132 | static int macii_probe(void) | ||
133 | { | ||
134 | if (macintosh_config->adb_type != MAC_ADB_II) return -ENODEV; | ||
135 | |||
136 | via = via1; | ||
137 | |||
138 | printk("adb: Mac II ADB Driver v1.0 for Unified ADB\n"); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /* Initialize the driver */ | ||
143 | int macii_init(void) | ||
144 | { | ||
145 | unsigned long flags; | ||
146 | int err; | ||
147 | |||
148 | local_irq_save(flags); | ||
149 | |||
150 | err = macii_init_via(); | ||
151 | if (err) return err; | ||
152 | |||
153 | err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB", | ||
154 | macii_interrupt); | ||
155 | if (err) return err; | ||
156 | |||
157 | macii_state = idle; | ||
158 | local_irq_restore(flags); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /* initialize the hardware */ | ||
163 | static int macii_init_via(void) | ||
164 | { | ||
165 | unsigned char x; | ||
166 | |||
167 | /* Set the lines up. We want TREQ as input TACK|TIP as output */ | ||
168 | via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; | ||
169 | |||
170 | /* Set up state: idle */ | ||
171 | via[B] |= ST_IDLE; | ||
172 | last_status = via[B] & (ST_MASK|TREQ); | ||
173 | |||
174 | /* Shift register on input */ | ||
175 | via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; | ||
176 | |||
177 | /* Wipe any pending data and int */ | ||
178 | x = via[SR]; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */ | ||
184 | static void macii_queue_poll(void) | ||
185 | { | ||
186 | static int device = 0; | ||
187 | static int in_poll=0; | ||
188 | static struct adb_request req; | ||
189 | unsigned long flags; | ||
190 | |||
191 | if (in_poll) printk("macii_queue_poll: double poll!\n"); | ||
192 | |||
193 | in_poll++; | ||
194 | if (++device > 15) device = 1; | ||
195 | |||
196 | adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1, | ||
197 | ADB_READREG(device, 0)); | ||
198 | |||
199 | local_irq_save(flags); | ||
200 | |||
201 | req.next = current_req; | ||
202 | current_req = &req; | ||
203 | |||
204 | local_irq_restore(flags); | ||
205 | macii_start(); | ||
206 | in_poll--; | ||
207 | } | ||
208 | |||
209 | /* Send an ADB retransmit (Talk, appended to the request queue) */ | ||
210 | static void macii_retransmit(int device) | ||
211 | { | ||
212 | static int in_retransmit = 0; | ||
213 | static struct adb_request rt; | ||
214 | unsigned long flags; | ||
215 | |||
216 | if (in_retransmit) printk("macii_retransmit: double retransmit!\n"); | ||
217 | |||
218 | in_retransmit++; | ||
219 | |||
220 | adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1, | ||
221 | ADB_READREG(device, 0)); | ||
222 | |||
223 | local_irq_save(flags); | ||
224 | |||
225 | if (current_req != NULL) { | ||
226 | last_req->next = &rt; | ||
227 | last_req = &rt; | ||
228 | } else { | ||
229 | current_req = &rt; | ||
230 | last_req = &rt; | ||
231 | } | ||
232 | |||
233 | if (macii_state == idle) macii_start(); | ||
234 | |||
235 | local_irq_restore(flags); | ||
236 | in_retransmit--; | ||
237 | } | ||
238 | |||
239 | /* Send an ADB request; if sync, poll out the reply 'till it's done */ | ||
240 | static int macii_send_request(struct adb_request *req, int sync) | ||
241 | { | ||
242 | int i; | ||
243 | |||
244 | i = macii_write(req); | ||
245 | if (i) return i; | ||
246 | |||
247 | if (sync) { | ||
248 | while (!req->complete) macii_poll(); | ||
249 | } | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | /* Send an ADB request */ | ||
254 | static int macii_write(struct adb_request *req) | ||
255 | { | ||
256 | unsigned long flags; | ||
257 | |||
258 | if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { | ||
259 | req->complete = 1; | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | req->next = 0; | ||
264 | req->sent = 0; | ||
265 | req->complete = 0; | ||
266 | req->reply_len = 0; | ||
267 | |||
268 | local_irq_save(flags); | ||
269 | |||
270 | if (current_req != NULL) { | ||
271 | last_req->next = req; | ||
272 | last_req = req; | ||
273 | } else { | ||
274 | current_req = req; | ||
275 | last_req = req; | ||
276 | if (macii_state == idle) macii_start(); | ||
277 | } | ||
278 | |||
279 | local_irq_restore(flags); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | /* Start auto-polling */ | ||
284 | static int macii_autopoll(int devs) | ||
285 | { | ||
286 | /* Just ping a random default address */ | ||
287 | if (!(current_req || retry_req)) | ||
288 | macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /* Prod the chip without interrupts */ | ||
293 | static void macii_poll(void) | ||
294 | { | ||
295 | unsigned long flags; | ||
296 | |||
297 | local_irq_save(flags); | ||
298 | if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0); | ||
299 | local_irq_restore(flags); | ||
300 | } | ||
301 | |||
302 | /* Reset the bus */ | ||
303 | static int macii_reset_bus(void) | ||
304 | { | ||
305 | static struct adb_request req; | ||
306 | |||
307 | /* Command = 0, Address = ignored */ | ||
308 | adb_request(&req, NULL, 0, 1, ADB_BUSRESET); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | /* Start sending ADB packet */ | ||
314 | static void macii_start(void) | ||
315 | { | ||
316 | unsigned long flags; | ||
317 | struct adb_request *req; | ||
318 | |||
319 | req = current_req; | ||
320 | if (!req) return; | ||
321 | |||
322 | /* assert macii_state == idle */ | ||
323 | if (macii_state != idle) { | ||
324 | printk("macii_start: called while driver busy (%p %x %x)!\n", | ||
325 | req, macii_state, (uint) via1[B] & (ST_MASK|TREQ)); | ||
326 | return; | ||
327 | } | ||
328 | |||
329 | local_irq_save(flags); | ||
330 | |||
331 | /* | ||
332 | * IRQ signaled ?? (means ADB controller wants to send, or might | ||
333 | * be end of packet if we were reading) | ||
334 | */ | ||
335 | #if 0 /* FIXME: This is broke broke broke, for some reason */ | ||
336 | if ((via[B] & TREQ) == 0) { | ||
337 | printk("macii_start: weird poll stuff. huh?\n"); | ||
338 | /* | ||
339 | * FIXME - we need to restart this on a timer | ||
340 | * or a collision at boot hangs us. | ||
341 | * Never set macii_state to idle here, or macii_start | ||
342 | * won't be called again from send_request! | ||
343 | * (need to re-check other cases ...) | ||
344 | */ | ||
345 | /* | ||
346 | * if the interrupt handler set the need_poll | ||
347 | * flag, it's hopefully a SRQ poll or re-Talk | ||
348 | * so we try to send here anyway | ||
349 | */ | ||
350 | if (!need_poll) { | ||
351 | if (console_loglevel == 10) | ||
352 | printk("macii_start: device busy - retry %p state %d status %x!\n", | ||
353 | req, macii_state, | ||
354 | (uint) via[B] & (ST_MASK|TREQ)); | ||
355 | retry_req = req; | ||
356 | /* set ADB status here ? */ | ||
357 | local_irq_restore(flags); | ||
358 | return; | ||
359 | } else { | ||
360 | need_poll = 0; | ||
361 | } | ||
362 | } | ||
363 | #endif | ||
364 | /* | ||
365 | * Another retry pending? (sanity check) | ||
366 | */ | ||
367 | if (retry_req) { | ||
368 | retry_req = NULL; | ||
369 | } | ||
370 | |||
371 | /* Now send it. Be careful though, that first byte of the request */ | ||
372 | /* is actually ADB_PACKET; the real data begins at index 1! */ | ||
373 | |||
374 | /* store command byte */ | ||
375 | command_byte = req->data[1]; | ||
376 | /* Output mode */ | ||
377 | via[ACR] |= SR_OUT; | ||
378 | /* Load data */ | ||
379 | via[SR] = req->data[1]; | ||
380 | /* set ADB state to 'command' */ | ||
381 | via[B] = (via[B] & ~ST_MASK) | ST_CMD; | ||
382 | |||
383 | macii_state = sending; | ||
384 | data_index = 2; | ||
385 | |||
386 | local_irq_restore(flags); | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * The notorious ADB interrupt handler - does all of the protocol handling, | ||
391 | * except for starting new send operations. Relies heavily on the ADB | ||
392 | * controller sending and receiving data, thereby generating SR interrupts | ||
393 | * for us. This means there has to be always activity on the ADB bus, otherwise | ||
394 | * the whole process dies and has to be re-kicked by sending TALK requests ... | ||
395 | * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type | ||
396 | * ADB the problem isn't solved yet (retransmit of the latest active TALK seems | ||
397 | * a good choice; either on timeout or on a timer interrupt). | ||
398 | * | ||
399 | * The basic ADB state machine was left unchanged from the original MacII code | ||
400 | * by Alan Cox, which was based on the CUDA driver for PowerMac. | ||
401 | * The syntax of the ADB status lines seems to be totally different on MacII, | ||
402 | * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for | ||
403 | * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start | ||
404 | * and end of a receive packet are signaled by asserting /IRQ on the interrupt | ||
405 | * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on | ||
406 | * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the | ||
407 | * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB | ||
408 | * protocol with a logic analyzer!!) | ||
409 | * | ||
410 | * Note: As of 21/10/97, the MacII ADB part works including timeout detection | ||
411 | * and retransmit (Talk to the last active device). | ||
412 | */ | ||
413 | static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs) | ||
414 | { | ||
415 | int x, adbdir; | ||
416 | unsigned long flags; | ||
417 | struct adb_request *req; | ||
418 | |||
419 | last_status = status; | ||
420 | |||
421 | /* prevent races due to SCSI enabling ints */ | ||
422 | local_irq_save(flags); | ||
423 | |||
424 | if (driver_running) { | ||
425 | local_irq_restore(flags); | ||
426 | return IRQ_NONE; | ||
427 | } | ||
428 | |||
429 | driver_running = 1; | ||
430 | |||
431 | status = via[B] & (ST_MASK|TREQ); | ||
432 | adbdir = via[ACR] & SR_OUT; | ||
433 | |||
434 | switch (macii_state) { | ||
435 | case idle: | ||
436 | x = via[SR]; | ||
437 | first_byte = x; | ||
438 | /* set ADB state = even for first data byte */ | ||
439 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
440 | |||
441 | reply_buf[0] = first_byte; /* was command_byte?? */ | ||
442 | reply_ptr = reply_buf + 1; | ||
443 | reply_len = 1; | ||
444 | prefix_len = 1; | ||
445 | reading_reply = 0; | ||
446 | |||
447 | macii_state = reading; | ||
448 | break; | ||
449 | |||
450 | case awaiting_reply: | ||
451 | /* handshake etc. for II ?? */ | ||
452 | x = via[SR]; | ||
453 | first_byte = x; | ||
454 | /* set ADB state = even for first data byte */ | ||
455 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
456 | |||
457 | current_req->reply[0] = first_byte; | ||
458 | reply_ptr = current_req->reply + 1; | ||
459 | reply_len = 1; | ||
460 | prefix_len = 1; | ||
461 | reading_reply = 1; | ||
462 | |||
463 | macii_state = reading; | ||
464 | break; | ||
465 | |||
466 | case sending: | ||
467 | req = current_req; | ||
468 | if (data_index >= req->nbytes) { | ||
469 | /* print an error message if a listen command has no data */ | ||
470 | if (((command_byte & 0x0C) == 0x08) | ||
471 | /* && (console_loglevel == 10) */ | ||
472 | && (data_index == 2)) | ||
473 | printk("MacII ADB: listen command with no data: %x!\n", | ||
474 | command_byte); | ||
475 | /* reset to shift in */ | ||
476 | via[ACR] &= ~SR_OUT; | ||
477 | x = via[SR]; | ||
478 | /* set ADB state idle - might get SRQ */ | ||
479 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
480 | |||
481 | req->sent = 1; | ||
482 | |||
483 | if (req->reply_expected) { | ||
484 | macii_state = awaiting_reply; | ||
485 | } else { | ||
486 | req->complete = 1; | ||
487 | current_req = req->next; | ||
488 | if (req->done) (*req->done)(req); | ||
489 | macii_state = idle; | ||
490 | if (current_req || retry_req) | ||
491 | macii_start(); | ||
492 | else | ||
493 | macii_retransmit((command_byte & 0xF0) >> 4); | ||
494 | } | ||
495 | } else { | ||
496 | via[SR] = req->data[data_index++]; | ||
497 | |||
498 | if ( (via[B] & ST_MASK) == ST_CMD ) { | ||
499 | /* just sent the command byte, set to EVEN */ | ||
500 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
501 | } else { | ||
502 | /* invert state bits, toggle ODD/EVEN */ | ||
503 | via[B] ^= ST_MASK; | ||
504 | } | ||
505 | } | ||
506 | break; | ||
507 | |||
508 | case reading: | ||
509 | |||
510 | /* timeout / SRQ handling for II hw */ | ||
511 | if( (first_byte == 0xFF && (reply_len-prefix_len)==2 | ||
512 | && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) || | ||
513 | ((reply_len-prefix_len)==3 | ||
514 | && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)) | ||
515 | { | ||
516 | /* | ||
517 | * possible timeout (in fact, most probably a | ||
518 | * timeout, since SRQ can't be signaled without | ||
519 | * transfer on the bus). | ||
520 | * The last three bytes seen were FF, together | ||
521 | * with the starting byte (in case we started | ||
522 | * on 'idle' or 'awaiting_reply') this probably | ||
523 | * makes four. So this is mostl likely #5! | ||
524 | * The timeout signal is a pattern 1 0 1 0 0.. | ||
525 | * on /INT, meaning we missed it :-( | ||
526 | */ | ||
527 | x = via[SR]; | ||
528 | if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n"); | ||
529 | |||
530 | if ((status & TREQ) == (last_status & TREQ)) { | ||
531 | /* Not a timeout. Unsolicited SRQ? weird. */ | ||
532 | /* Terminate the SRQ packet and poll */ | ||
533 | need_poll = 1; | ||
534 | } | ||
535 | /* There's no packet to get, so reply is blank */ | ||
536 | via[B] ^= ST_MASK; | ||
537 | reply_ptr -= (reply_len-prefix_len); | ||
538 | reply_len = prefix_len; | ||
539 | macii_state = read_done; | ||
540 | break; | ||
541 | } /* end timeout / SRQ handling for II hw. */ | ||
542 | |||
543 | if((reply_len-prefix_len)>3 | ||
544 | && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) | ||
545 | { | ||
546 | /* SRQ tacked on data packet */ | ||
547 | /* Terminate the packet (SRQ never ends) */ | ||
548 | x = via[SR]; | ||
549 | macii_state = read_done; | ||
550 | reply_len -= 3; | ||
551 | reply_ptr -= 3; | ||
552 | need_poll = 1; | ||
553 | /* need to continue; next byte not seen else */ | ||
554 | } else { | ||
555 | /* Sanity check */ | ||
556 | if (reply_len > 15) reply_len = 0; | ||
557 | /* read byte */ | ||
558 | x = via[SR]; | ||
559 | *reply_ptr = x; | ||
560 | reply_ptr++; | ||
561 | reply_len++; | ||
562 | } | ||
563 | /* The usual handshake ... */ | ||
564 | |||
565 | /* | ||
566 | * NetBSD hints that the next to last byte | ||
567 | * is sent with IRQ !! | ||
568 | * Guido found out it's the last one (0x0), | ||
569 | * but IRQ should be asserted already. | ||
570 | * Problem with timeout detection: First | ||
571 | * transition to /IRQ might be second | ||
572 | * byte of timeout packet! | ||
573 | * Timeouts are signaled by 4x FF. | ||
574 | */ | ||
575 | if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */ | ||
576 | /* invert state bits, toggle ODD/EVEN */ | ||
577 | via[B] ^= ST_MASK; | ||
578 | |||
579 | /* adjust packet length */ | ||
580 | reply_len--; | ||
581 | reply_ptr--; | ||
582 | macii_state = read_done; | ||
583 | } else { | ||
584 | /* not caught: ST_CMD */ | ||
585 | /* required for re-entry 'reading'! */ | ||
586 | if ((status & ST_MASK) == ST_IDLE) { | ||
587 | /* (in)sanity check - set even */ | ||
588 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
589 | } else { | ||
590 | /* invert state bits */ | ||
591 | via[B] ^= ST_MASK; | ||
592 | } | ||
593 | } | ||
594 | break; | ||
595 | |||
596 | case read_done: | ||
597 | x = via[SR]; | ||
598 | if (reading_reply) { | ||
599 | req = current_req; | ||
600 | req->reply_len = reply_ptr - req->reply; | ||
601 | req->complete = 1; | ||
602 | current_req = req->next; | ||
603 | if (req->done) (*req->done)(req); | ||
604 | } else { | ||
605 | adb_input(reply_buf, reply_ptr - reply_buf, | ||
606 | regs, 0); | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * remember this device ID; it's the latest we got a | ||
611 | * reply from! | ||
612 | */ | ||
613 | last_reply = command_byte; | ||
614 | last_active = (command_byte & 0xF0) >> 4; | ||
615 | |||
616 | /* SRQ seen before, initiate poll now */ | ||
617 | if (need_poll) { | ||
618 | macii_state = idle; | ||
619 | macii_queue_poll(); | ||
620 | need_poll = 0; | ||
621 | break; | ||
622 | } | ||
623 | |||
624 | /* set ADB state to idle */ | ||
625 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
626 | |||
627 | /* /IRQ seen, so the ADB controller has data for us */ | ||
628 | if ((via[B] & TREQ) != 0) { | ||
629 | macii_state = reading; | ||
630 | |||
631 | reply_buf[0] = command_byte; | ||
632 | reply_ptr = reply_buf + 1; | ||
633 | reply_len = 1; | ||
634 | prefix_len = 1; | ||
635 | reading_reply = 0; | ||
636 | } else { | ||
637 | /* no IRQ, send next packet or wait */ | ||
638 | macii_state = idle; | ||
639 | if (current_req) | ||
640 | macii_start(); | ||
641 | else | ||
642 | macii_retransmit(last_active); | ||
643 | } | ||
644 | break; | ||
645 | |||
646 | default: | ||
647 | break; | ||
648 | } | ||
649 | /* reset mutex and interrupts */ | ||
650 | driver_running = 0; | ||
651 | local_irq_restore(flags); | ||
652 | return IRQ_HANDLED; | ||
653 | } | ||
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c new file mode 100644 index 000000000000..a1966975d58f --- /dev/null +++ b/drivers/macintosh/via-maciisi.c | |||
@@ -0,0 +1,661 @@ | |||
1 | /* | ||
2 | * Device driver for the IIsi-style ADB on some Mac LC and II-class machines | ||
3 | * | ||
4 | * Based on via-cuda.c and via-macii.c, as well as the original | ||
5 | * adb-bus.c, which in turn is somewhat influenced by (but uses no | ||
6 | * code from) the NetBSD HWDIRECT ADB code. Original IIsi driver work | ||
7 | * was done by Robert Thompson and integrated into the old style | ||
8 | * driver by Michael Schmitz. | ||
9 | * | ||
10 | * Original sources (c) Alan Cox, Paul Mackerras, and others. | ||
11 | * | ||
12 | * Rewritten for Unified ADB by David Huggins-Daines <dhd@debian.org> | ||
13 | * | ||
14 | * 7/13/2000- extensive changes by Andrew McPherson <andrew@macduff.dhs.org> | ||
15 | * Works about 30% of the time now. | ||
16 | */ | ||
17 | |||
18 | #include <linux/types.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/adb.h> | ||
23 | #include <linux/cuda.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <asm/macintosh.h> | ||
27 | #include <asm/macints.h> | ||
28 | #include <asm/machw.h> | ||
29 | #include <asm/mac_via.h> | ||
30 | |||
31 | static volatile unsigned char *via; | ||
32 | |||
33 | /* VIA registers - spaced 0x200 bytes apart - only the ones we actually use */ | ||
34 | #define RS 0x200 /* skip between registers */ | ||
35 | #define B 0 /* B-side data */ | ||
36 | #define A RS /* A-side data */ | ||
37 | #define DIRB (2*RS) /* B-side direction (1=output) */ | ||
38 | #define DIRA (3*RS) /* A-side direction (1=output) */ | ||
39 | #define SR (10*RS) /* Shift register */ | ||
40 | #define ACR (11*RS) /* Auxiliary control register */ | ||
41 | #define IFR (13*RS) /* Interrupt flag register */ | ||
42 | #define IER (14*RS) /* Interrupt enable register */ | ||
43 | |||
44 | /* Bits in B data register: all active low */ | ||
45 | #define TREQ 0x08 /* Transfer request (input) */ | ||
46 | #define TACK 0x10 /* Transfer acknowledge (output) */ | ||
47 | #define TIP 0x20 /* Transfer in progress (output) */ | ||
48 | #define ST_MASK 0x30 /* mask for selecting ADB state bits */ | ||
49 | |||
50 | /* Bits in ACR */ | ||
51 | #define SR_CTRL 0x1c /* Shift register control bits */ | ||
52 | #define SR_EXT 0x0c /* Shift on external clock */ | ||
53 | #define SR_OUT 0x10 /* Shift out if 1 */ | ||
54 | |||
55 | /* Bits in IFR and IER */ | ||
56 | #define IER_SET 0x80 /* set bits in IER */ | ||
57 | #define IER_CLR 0 /* clear bits in IER */ | ||
58 | #define SR_INT 0x04 /* Shift register full/empty */ | ||
59 | #define SR_DATA 0x08 /* Shift register data */ | ||
60 | #define SR_CLOCK 0x10 /* Shift register clock */ | ||
61 | |||
62 | #define ADB_DELAY 150 | ||
63 | |||
64 | #undef DEBUG_MACIISI_ADB | ||
65 | |||
66 | static struct adb_request* current_req = NULL; | ||
67 | static struct adb_request* last_req = NULL; | ||
68 | static unsigned char maciisi_rbuf[16]; | ||
69 | static unsigned char *reply_ptr = NULL; | ||
70 | static int data_index; | ||
71 | static int reading_reply; | ||
72 | static int reply_len; | ||
73 | static int tmp; | ||
74 | static int need_sync; | ||
75 | |||
76 | static enum maciisi_state { | ||
77 | idle, | ||
78 | sending, | ||
79 | reading, | ||
80 | } maciisi_state; | ||
81 | |||
82 | static int maciisi_probe(void); | ||
83 | static int maciisi_init(void); | ||
84 | static int maciisi_send_request(struct adb_request* req, int sync); | ||
85 | static void maciisi_sync(struct adb_request *req); | ||
86 | static int maciisi_write(struct adb_request* req); | ||
87 | static irqreturn_t maciisi_interrupt(int irq, void* arg, struct pt_regs* regs); | ||
88 | static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs); | ||
89 | static int maciisi_init_via(void); | ||
90 | static void maciisi_poll(void); | ||
91 | static int maciisi_start(void); | ||
92 | |||
93 | struct adb_driver via_maciisi_driver = { | ||
94 | "Mac IIsi", | ||
95 | maciisi_probe, | ||
96 | maciisi_init, | ||
97 | maciisi_send_request, | ||
98 | NULL, /* maciisi_adb_autopoll, */ | ||
99 | maciisi_poll, | ||
100 | NULL /* maciisi_reset_adb_bus */ | ||
101 | }; | ||
102 | |||
103 | static int | ||
104 | maciisi_probe(void) | ||
105 | { | ||
106 | if (macintosh_config->adb_type != MAC_ADB_IISI) | ||
107 | return -ENODEV; | ||
108 | |||
109 | via = via1; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | maciisi_init(void) | ||
115 | { | ||
116 | int err; | ||
117 | |||
118 | if (via == NULL) | ||
119 | return -ENODEV; | ||
120 | |||
121 | if ((err = maciisi_init_via())) { | ||
122 | printk(KERN_ERR "maciisi_init: maciisi_init_via() failed, code %d\n", err); | ||
123 | via = NULL; | ||
124 | return err; | ||
125 | } | ||
126 | |||
127 | if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, | ||
128 | "ADB", maciisi_interrupt)) { | ||
129 | printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB); | ||
130 | return -EAGAIN; | ||
131 | } | ||
132 | |||
133 | printk("adb: Mac IIsi driver v0.2 for Unified ADB.\n"); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* Flush data from the ADB controller */ | ||
138 | static void | ||
139 | maciisi_stfu(void) | ||
140 | { | ||
141 | int status = via[B] & (TIP|TREQ); | ||
142 | |||
143 | if (status & TREQ) { | ||
144 | #ifdef DEBUG_MACIISI_ADB | ||
145 | printk (KERN_DEBUG "maciisi_stfu called with TREQ high!\n"); | ||
146 | #endif | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | udelay(ADB_DELAY); | ||
151 | via[ACR] &= ~SR_OUT; | ||
152 | via[IER] = IER_CLR | SR_INT; | ||
153 | |||
154 | udelay(ADB_DELAY); | ||
155 | |||
156 | status = via[B] & (TIP|TREQ); | ||
157 | |||
158 | if (!(status & TREQ)) | ||
159 | { | ||
160 | via[B] |= TIP; | ||
161 | |||
162 | while(1) | ||
163 | { | ||
164 | int poll_timeout = ADB_DELAY * 5; | ||
165 | /* Poll for SR interrupt */ | ||
166 | while (!(via[IFR] & SR_INT) && poll_timeout-- > 0) | ||
167 | status = via[B] & (TIP|TREQ); | ||
168 | |||
169 | tmp = via[SR]; /* Clear shift register */ | ||
170 | #ifdef DEBUG_MACIISI_ADB | ||
171 | printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d data %x\n", | ||
172 | status, poll_timeout, tmp); | ||
173 | #endif | ||
174 | if(via[B] & TREQ) | ||
175 | break; | ||
176 | |||
177 | /* ACK on-off */ | ||
178 | via[B] |= TACK; | ||
179 | udelay(ADB_DELAY); | ||
180 | via[B] &= ~TACK; | ||
181 | } | ||
182 | |||
183 | /* end frame */ | ||
184 | via[B] &= ~TIP; | ||
185 | udelay(ADB_DELAY); | ||
186 | } | ||
187 | |||
188 | via[IER] = IER_SET | SR_INT; | ||
189 | } | ||
190 | |||
191 | /* All specifically VIA-related initialization goes here */ | ||
192 | static int | ||
193 | maciisi_init_via(void) | ||
194 | { | ||
195 | int i; | ||
196 | |||
197 | /* Set the lines up. We want TREQ as input TACK|TIP as output */ | ||
198 | via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; | ||
199 | /* Shift register on input */ | ||
200 | via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; | ||
201 | #ifdef DEBUG_MACIISI_ADB | ||
202 | printk(KERN_DEBUG "maciisi_init_via: initial status %x\n", via[B] & (TIP|TREQ)); | ||
203 | #endif | ||
204 | /* Wipe any pending data and int */ | ||
205 | tmp = via[SR]; | ||
206 | /* Enable keyboard interrupts */ | ||
207 | via[IER] = IER_SET | SR_INT; | ||
208 | /* Set initial state: idle */ | ||
209 | via[B] &= ~(TACK|TIP); | ||
210 | /* Clear interrupt bit */ | ||
211 | via[IFR] = SR_INT; | ||
212 | |||
213 | for(i = 0; i < 60; i++) { | ||
214 | udelay(ADB_DELAY); | ||
215 | maciisi_stfu(); | ||
216 | udelay(ADB_DELAY); | ||
217 | if(via[B] & TREQ) | ||
218 | break; | ||
219 | } | ||
220 | if (i == 60) | ||
221 | printk(KERN_ERR "maciisi_init_via: bus jam?\n"); | ||
222 | |||
223 | maciisi_state = idle; | ||
224 | need_sync = 0; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | /* Send a request, possibly waiting for a reply */ | ||
230 | static int | ||
231 | maciisi_send_request(struct adb_request* req, int sync) | ||
232 | { | ||
233 | int i; | ||
234 | |||
235 | #ifdef DEBUG_MACIISI_ADB | ||
236 | static int dump_packet = 0; | ||
237 | #endif | ||
238 | |||
239 | if (via == NULL) { | ||
240 | req->complete = 1; | ||
241 | return -ENXIO; | ||
242 | } | ||
243 | |||
244 | #ifdef DEBUG_MACIISI_ADB | ||
245 | if (dump_packet) { | ||
246 | printk(KERN_DEBUG "maciisi_send_request:"); | ||
247 | for (i = 0; i < req->nbytes; i++) { | ||
248 | printk(" %.2x", req->data[i]); | ||
249 | } | ||
250 | printk(" sync %d\n", sync); | ||
251 | } | ||
252 | #endif | ||
253 | |||
254 | req->reply_expected = 1; | ||
255 | |||
256 | i = maciisi_write(req); | ||
257 | if (i) | ||
258 | { | ||
259 | /* Normally, if a packet requires syncing, that happens at the end of | ||
260 | * maciisi_send_request. But if the transfer fails, it will be restarted | ||
261 | * by maciisi_interrupt(). We use need_sync to tell maciisi_interrupt | ||
262 | * when to sync a packet that it sends out. | ||
263 | * | ||
264 | * Suggestions on a better way to do this are welcome. | ||
265 | */ | ||
266 | if(i == -EBUSY && sync) | ||
267 | need_sync = 1; | ||
268 | else | ||
269 | need_sync = 0; | ||
270 | return i; | ||
271 | } | ||
272 | if(sync) | ||
273 | maciisi_sync(req); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* Poll the ADB chip until the request completes */ | ||
279 | static void maciisi_sync(struct adb_request *req) | ||
280 | { | ||
281 | int count = 0; | ||
282 | |||
283 | #ifdef DEBUG_MACIISI_ADB | ||
284 | printk(KERN_DEBUG "maciisi_sync called\n"); | ||
285 | #endif | ||
286 | |||
287 | /* If for some reason the ADB chip shuts up on us, we want to avoid an endless loop. */ | ||
288 | while (!req->complete && count++ < 50) { | ||
289 | maciisi_poll(); | ||
290 | } | ||
291 | /* This could be BAD... when the ADB controller doesn't respond | ||
292 | * for this long, it's probably not coming back :-( */ | ||
293 | if(count >= 50) /* Hopefully shouldn't happen */ | ||
294 | printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); | ||
295 | } | ||
296 | |||
297 | /* Enqueue a request, and run the queue if possible */ | ||
298 | static int | ||
299 | maciisi_write(struct adb_request* req) | ||
300 | { | ||
301 | unsigned long flags; | ||
302 | int i; | ||
303 | |||
304 | /* We will accept CUDA packets - the VIA sends them to us, so | ||
305 | it figures that we should be able to send them to it */ | ||
306 | if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) { | ||
307 | printk(KERN_ERR "maciisi_write: packet too small or not an ADB or CUDA packet\n"); | ||
308 | req->complete = 1; | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | req->next = 0; | ||
312 | req->sent = 0; | ||
313 | req->complete = 0; | ||
314 | req->reply_len = 0; | ||
315 | |||
316 | local_irq_save(flags); | ||
317 | |||
318 | if (current_req) { | ||
319 | last_req->next = req; | ||
320 | last_req = req; | ||
321 | } else { | ||
322 | current_req = req; | ||
323 | last_req = req; | ||
324 | } | ||
325 | if (maciisi_state == idle) | ||
326 | { | ||
327 | i = maciisi_start(); | ||
328 | if(i != 0) | ||
329 | { | ||
330 | local_irq_restore(flags); | ||
331 | return i; | ||
332 | } | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | #ifdef DEBUG_MACIISI_ADB | ||
337 | printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state); | ||
338 | #endif | ||
339 | local_irq_restore(flags); | ||
340 | return -EBUSY; | ||
341 | } | ||
342 | |||
343 | local_irq_restore(flags); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int | ||
349 | maciisi_start(void) | ||
350 | { | ||
351 | struct adb_request* req; | ||
352 | int status; | ||
353 | |||
354 | #ifdef DEBUG_MACIISI_ADB | ||
355 | status = via[B] & (TIP | TREQ); | ||
356 | |||
357 | printk(KERN_DEBUG "maciisi_start called, state=%d, status=%x, ifr=%x\n", maciisi_state, status, via[IFR]); | ||
358 | #endif | ||
359 | |||
360 | if (maciisi_state != idle) { | ||
361 | /* shouldn't happen */ | ||
362 | printk(KERN_ERR "maciisi_start: maciisi_start called when driver busy!\n"); | ||
363 | return -EBUSY; | ||
364 | } | ||
365 | |||
366 | req = current_req; | ||
367 | if (req == NULL) | ||
368 | return -EINVAL; | ||
369 | |||
370 | status = via[B] & (TIP|TREQ); | ||
371 | if (!(status & TREQ)) { | ||
372 | #ifdef DEBUG_MACIISI_ADB | ||
373 | printk(KERN_DEBUG "maciisi_start: bus busy - aborting\n"); | ||
374 | #endif | ||
375 | return -EBUSY; | ||
376 | } | ||
377 | |||
378 | /* Okay, send */ | ||
379 | #ifdef DEBUG_MACIISI_ADB | ||
380 | printk(KERN_DEBUG "maciisi_start: sending\n"); | ||
381 | #endif | ||
382 | /* Set state to active */ | ||
383 | via[B] |= TIP; | ||
384 | /* ACK off */ | ||
385 | via[B] &= ~TACK; | ||
386 | /* Delay */ | ||
387 | udelay(ADB_DELAY); | ||
388 | /* Shift out and send */ | ||
389 | via[ACR] |= SR_OUT; | ||
390 | via[SR] = req->data[0]; | ||
391 | data_index = 1; | ||
392 | /* ACK on */ | ||
393 | via[B] |= TACK; | ||
394 | maciisi_state = sending; | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | void | ||
400 | maciisi_poll(void) | ||
401 | { | ||
402 | unsigned long flags; | ||
403 | |||
404 | local_irq_save(flags); | ||
405 | if (via[IFR] & SR_INT) { | ||
406 | maciisi_interrupt(0, 0, 0); | ||
407 | } | ||
408 | else /* avoid calling this function too quickly in a loop */ | ||
409 | udelay(ADB_DELAY); | ||
410 | |||
411 | local_irq_restore(flags); | ||
412 | } | ||
413 | |||
414 | /* Shift register interrupt - this is *supposed* to mean that the | ||
415 | register is either full or empty. In practice, I have no idea what | ||
416 | it means :( */ | ||
417 | static irqreturn_t | ||
418 | maciisi_interrupt(int irq, void* arg, struct pt_regs* regs) | ||
419 | { | ||
420 | int status; | ||
421 | struct adb_request *req; | ||
422 | #ifdef DEBUG_MACIISI_ADB | ||
423 | static int dump_reply = 0; | ||
424 | #endif | ||
425 | int i; | ||
426 | unsigned long flags; | ||
427 | |||
428 | local_irq_save(flags); | ||
429 | |||
430 | status = via[B] & (TIP|TREQ); | ||
431 | #ifdef DEBUG_MACIISI_ADB | ||
432 | printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]); | ||
433 | #endif | ||
434 | |||
435 | if (!(via[IFR] & SR_INT)) { | ||
436 | /* Shouldn't happen, we hope */ | ||
437 | printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n"); | ||
438 | local_irq_restore(flags); | ||
439 | return IRQ_NONE; | ||
440 | } | ||
441 | |||
442 | /* Clear the interrupt */ | ||
443 | /* via[IFR] = SR_INT; */ | ||
444 | |||
445 | switch_start: | ||
446 | switch (maciisi_state) { | ||
447 | case idle: | ||
448 | if (status & TIP) | ||
449 | printk(KERN_ERR "maciisi_interrupt: state is idle but TIP asserted!\n"); | ||
450 | |||
451 | if(!reading_reply) | ||
452 | udelay(ADB_DELAY); | ||
453 | /* Shift in */ | ||
454 | via[ACR] &= ~SR_OUT; | ||
455 | /* Signal start of frame */ | ||
456 | via[B] |= TIP; | ||
457 | /* Clear the interrupt (throw this value on the floor, it's useless) */ | ||
458 | tmp = via[SR]; | ||
459 | /* ACK adb chip, high-low */ | ||
460 | via[B] |= TACK; | ||
461 | udelay(ADB_DELAY); | ||
462 | via[B] &= ~TACK; | ||
463 | reply_len = 0; | ||
464 | maciisi_state = reading; | ||
465 | if (reading_reply) { | ||
466 | reply_ptr = current_req->reply; | ||
467 | } else { | ||
468 | reply_ptr = maciisi_rbuf; | ||
469 | } | ||
470 | break; | ||
471 | |||
472 | case sending: | ||
473 | /* via[SR]; */ | ||
474 | /* Set ACK off */ | ||
475 | via[B] &= ~TACK; | ||
476 | req = current_req; | ||
477 | |||
478 | if (!(status & TREQ)) { | ||
479 | /* collision */ | ||
480 | printk(KERN_ERR "maciisi_interrupt: send collision\n"); | ||
481 | /* Set idle and input */ | ||
482 | via[ACR] &= ~SR_OUT; | ||
483 | tmp = via[SR]; | ||
484 | via[B] &= ~TIP; | ||
485 | /* Must re-send */ | ||
486 | reading_reply = 0; | ||
487 | reply_len = 0; | ||
488 | maciisi_state = idle; | ||
489 | udelay(ADB_DELAY); | ||
490 | /* process this now, because the IFR has been cleared */ | ||
491 | goto switch_start; | ||
492 | } | ||
493 | |||
494 | udelay(ADB_DELAY); | ||
495 | |||
496 | if (data_index >= req->nbytes) { | ||
497 | /* Sent the whole packet, put the bus back in idle state */ | ||
498 | /* Shift in, we are about to read a reply (hopefully) */ | ||
499 | via[ACR] &= ~SR_OUT; | ||
500 | tmp = via[SR]; | ||
501 | /* End of frame */ | ||
502 | via[B] &= ~TIP; | ||
503 | req->sent = 1; | ||
504 | maciisi_state = idle; | ||
505 | if (req->reply_expected) { | ||
506 | /* Note: only set this once we've | ||
507 | successfully sent the packet */ | ||
508 | reading_reply = 1; | ||
509 | } else { | ||
510 | current_req = req->next; | ||
511 | if (req->done) | ||
512 | (*req->done)(req); | ||
513 | /* Do any queued requests now */ | ||
514 | i = maciisi_start(); | ||
515 | if(i == 0 && need_sync) { | ||
516 | /* Packet needs to be synced */ | ||
517 | maciisi_sync(current_req); | ||
518 | } | ||
519 | if(i != -EBUSY) | ||
520 | need_sync = 0; | ||
521 | } | ||
522 | } else { | ||
523 | /* Sending more stuff */ | ||
524 | /* Shift out */ | ||
525 | via[ACR] |= SR_OUT; | ||
526 | /* Write */ | ||
527 | via[SR] = req->data[data_index++]; | ||
528 | /* Signal 'byte ready' */ | ||
529 | via[B] |= TACK; | ||
530 | } | ||
531 | break; | ||
532 | |||
533 | case reading: | ||
534 | /* Shift in */ | ||
535 | /* via[ACR] &= ~SR_OUT; */ /* Not in 2.2 */ | ||
536 | if (reply_len++ > 16) { | ||
537 | printk(KERN_ERR "maciisi_interrupt: reply too long, aborting read\n"); | ||
538 | via[B] |= TACK; | ||
539 | udelay(ADB_DELAY); | ||
540 | via[B] &= ~(TACK|TIP); | ||
541 | maciisi_state = idle; | ||
542 | i = maciisi_start(); | ||
543 | if(i == 0 && need_sync) { | ||
544 | /* Packet needs to be synced */ | ||
545 | maciisi_sync(current_req); | ||
546 | } | ||
547 | if(i != -EBUSY) | ||
548 | need_sync = 0; | ||
549 | break; | ||
550 | } | ||
551 | /* Read data */ | ||
552 | *reply_ptr++ = via[SR]; | ||
553 | status = via[B] & (TIP|TREQ); | ||
554 | /* ACK on/off */ | ||
555 | via[B] |= TACK; | ||
556 | udelay(ADB_DELAY); | ||
557 | via[B] &= ~TACK; | ||
558 | if (!(status & TREQ)) | ||
559 | break; /* more stuff to deal with */ | ||
560 | |||
561 | /* end of frame */ | ||
562 | via[B] &= ~TIP; | ||
563 | tmp = via[SR]; /* That's what happens in 2.2 */ | ||
564 | udelay(ADB_DELAY); /* Give controller time to recover */ | ||
565 | |||
566 | /* end of packet, deal with it */ | ||
567 | if (reading_reply) { | ||
568 | req = current_req; | ||
569 | req->reply_len = reply_ptr - req->reply; | ||
570 | if (req->data[0] == ADB_PACKET) { | ||
571 | /* Have to adjust the reply from ADB commands */ | ||
572 | if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) { | ||
573 | /* the 0x2 bit indicates no response */ | ||
574 | req->reply_len = 0; | ||
575 | } else { | ||
576 | /* leave just the command and result bytes in the reply */ | ||
577 | req->reply_len -= 2; | ||
578 | memmove(req->reply, req->reply + 2, req->reply_len); | ||
579 | } | ||
580 | } | ||
581 | #ifdef DEBUG_MACIISI_ADB | ||
582 | if (dump_reply) { | ||
583 | int i; | ||
584 | printk(KERN_DEBUG "maciisi_interrupt: reply is "); | ||
585 | for (i = 0; i < req->reply_len; ++i) | ||
586 | printk(" %.2x", req->reply[i]); | ||
587 | printk("\n"); | ||
588 | } | ||
589 | #endif | ||
590 | req->complete = 1; | ||
591 | current_req = req->next; | ||
592 | if (req->done) | ||
593 | (*req->done)(req); | ||
594 | /* Obviously, we got it */ | ||
595 | reading_reply = 0; | ||
596 | } else { | ||
597 | maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf, regs); | ||
598 | } | ||
599 | maciisi_state = idle; | ||
600 | status = via[B] & (TIP|TREQ); | ||
601 | if (!(status & TREQ)) { | ||
602 | /* Timeout?! More likely, another packet coming in already */ | ||
603 | #ifdef DEBUG_MACIISI_ADB | ||
604 | printk(KERN_DEBUG "extra data after packet: status %x ifr %x\n", | ||
605 | status, via[IFR]); | ||
606 | #endif | ||
607 | #if 0 | ||
608 | udelay(ADB_DELAY); | ||
609 | via[B] |= TIP; | ||
610 | |||
611 | maciisi_state = reading; | ||
612 | reading_reply = 0; | ||
613 | reply_ptr = maciisi_rbuf; | ||
614 | #else | ||
615 | /* Process the packet now */ | ||
616 | reading_reply = 0; | ||
617 | goto switch_start; | ||
618 | #endif | ||
619 | /* We used to do this... but the controller might actually have data for us */ | ||
620 | /* maciisi_stfu(); */ | ||
621 | } | ||
622 | else { | ||
623 | /* Do any queued requests now if possible */ | ||
624 | i = maciisi_start(); | ||
625 | if(i == 0 && need_sync) { | ||
626 | /* Packet needs to be synced */ | ||
627 | maciisi_sync(current_req); | ||
628 | } | ||
629 | if(i != -EBUSY) | ||
630 | need_sync = 0; | ||
631 | } | ||
632 | break; | ||
633 | |||
634 | default: | ||
635 | printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state); | ||
636 | } | ||
637 | local_irq_restore(flags); | ||
638 | return IRQ_HANDLED; | ||
639 | } | ||
640 | |||
641 | static void | ||
642 | maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs) | ||
643 | { | ||
644 | #ifdef DEBUG_MACIISI_ADB | ||
645 | int i; | ||
646 | #endif | ||
647 | |||
648 | switch (buf[0]) { | ||
649 | case ADB_PACKET: | ||
650 | adb_input(buf+2, nb-2, regs, buf[1] & 0x40); | ||
651 | break; | ||
652 | default: | ||
653 | #ifdef DEBUG_MACIISI_ADB | ||
654 | printk(KERN_DEBUG "data from IIsi ADB (%d bytes):", nb); | ||
655 | for (i = 0; i < nb; ++i) | ||
656 | printk(" %.2x", buf[i]); | ||
657 | printk("\n"); | ||
658 | #endif | ||
659 | break; | ||
660 | } | ||
661 | } | ||
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c new file mode 100644 index 000000000000..cea1e758eb46 --- /dev/null +++ b/drivers/macintosh/via-pmu.c | |||
@@ -0,0 +1,3147 @@ | |||
1 | /* | ||
2 | * Device driver for the via-pmu on Apple Powermacs. | ||
3 | * | ||
4 | * The VIA (versatile interface adapter) interfaces to the PMU, | ||
5 | * a 6805 microprocessor core whose primary function is to control | ||
6 | * battery charging and system power on the PowerBook 3400 and 2400. | ||
7 | * The PMU also controls the ADB (Apple Desktop Bus) which connects | ||
8 | * to the keyboard and mouse, as well as the non-volatile RAM | ||
9 | * and the RTC (real time clock) chip. | ||
10 | * | ||
11 | * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi. | ||
12 | * Copyright (C) 2001-2002 Benjamin Herrenschmidt | ||
13 | * | ||
14 | * THIS DRIVER IS BECOMING A TOTAL MESS ! | ||
15 | * - Cleanup atomically disabling reply to PMU events after | ||
16 | * a sleep or a freq. switch | ||
17 | * - Move sleep code out of here to pmac_pm, merge into new | ||
18 | * common PM infrastructure | ||
19 | * - Move backlight code out as well | ||
20 | * - Save/Restore PCI space properly | ||
21 | * | ||
22 | */ | ||
23 | #include <stdarg.h> | ||
24 | #include <linux/config.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/miscdevice.h> | ||
31 | #include <linux/blkdev.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/adb.h> | ||
36 | #include <linux/pmu.h> | ||
37 | #include <linux/cuda.h> | ||
38 | #include <linux/smp_lock.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/spinlock.h> | ||
41 | #include <linux/pm.h> | ||
42 | #include <linux/proc_fs.h> | ||
43 | #include <linux/init.h> | ||
44 | #include <linux/interrupt.h> | ||
45 | #include <linux/device.h> | ||
46 | #include <linux/sysdev.h> | ||
47 | #include <linux/suspend.h> | ||
48 | #include <linux/syscalls.h> | ||
49 | #include <linux/cpu.h> | ||
50 | #include <asm/prom.h> | ||
51 | #include <asm/machdep.h> | ||
52 | #include <asm/io.h> | ||
53 | #include <asm/pgtable.h> | ||
54 | #include <asm/system.h> | ||
55 | #include <asm/sections.h> | ||
56 | #include <asm/irq.h> | ||
57 | #include <asm/pmac_feature.h> | ||
58 | #include <asm/uaccess.h> | ||
59 | #include <asm/mmu_context.h> | ||
60 | #include <asm/cputable.h> | ||
61 | #include <asm/time.h> | ||
62 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
63 | #include <asm/backlight.h> | ||
64 | #endif | ||
65 | |||
66 | /* Some compile options */ | ||
67 | #undef SUSPEND_USES_PMU | ||
68 | #define DEBUG_SLEEP | ||
69 | #undef HACKED_PCI_SAVE | ||
70 | |||
71 | /* Misc minor number allocated for /dev/pmu */ | ||
72 | #define PMU_MINOR 154 | ||
73 | |||
74 | /* How many iterations between battery polls */ | ||
75 | #define BATTERY_POLLING_COUNT 2 | ||
76 | |||
77 | static volatile unsigned char __iomem *via; | ||
78 | |||
79 | /* VIA registers - spaced 0x200 bytes apart */ | ||
80 | #define RS 0x200 /* skip between registers */ | ||
81 | #define B 0 /* B-side data */ | ||
82 | #define A RS /* A-side data */ | ||
83 | #define DIRB (2*RS) /* B-side direction (1=output) */ | ||
84 | #define DIRA (3*RS) /* A-side direction (1=output) */ | ||
85 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
86 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
87 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
88 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
89 | #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ | ||
90 | #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ | ||
91 | #define SR (10*RS) /* Shift register */ | ||
92 | #define ACR (11*RS) /* Auxiliary control register */ | ||
93 | #define PCR (12*RS) /* Peripheral control register */ | ||
94 | #define IFR (13*RS) /* Interrupt flag register */ | ||
95 | #define IER (14*RS) /* Interrupt enable register */ | ||
96 | #define ANH (15*RS) /* A-side data, no handshake */ | ||
97 | |||
98 | /* Bits in B data register: both active low */ | ||
99 | #define TACK 0x08 /* Transfer acknowledge (input) */ | ||
100 | #define TREQ 0x10 /* Transfer request (output) */ | ||
101 | |||
102 | /* Bits in ACR */ | ||
103 | #define SR_CTRL 0x1c /* Shift register control bits */ | ||
104 | #define SR_EXT 0x0c /* Shift on external clock */ | ||
105 | #define SR_OUT 0x10 /* Shift out if 1 */ | ||
106 | |||
107 | /* Bits in IFR and IER */ | ||
108 | #define IER_SET 0x80 /* set bits in IER */ | ||
109 | #define IER_CLR 0 /* clear bits in IER */ | ||
110 | #define SR_INT 0x04 /* Shift register full/empty */ | ||
111 | #define CB2_INT 0x08 | ||
112 | #define CB1_INT 0x10 /* transition on CB1 input */ | ||
113 | |||
114 | static volatile enum pmu_state { | ||
115 | idle, | ||
116 | sending, | ||
117 | intack, | ||
118 | reading, | ||
119 | reading_intr, | ||
120 | locked, | ||
121 | } pmu_state; | ||
122 | |||
123 | static volatile enum int_data_state { | ||
124 | int_data_empty, | ||
125 | int_data_fill, | ||
126 | int_data_ready, | ||
127 | int_data_flush | ||
128 | } int_data_state[2] = { int_data_empty, int_data_empty }; | ||
129 | |||
130 | static struct adb_request *current_req; | ||
131 | static struct adb_request *last_req; | ||
132 | static struct adb_request *req_awaiting_reply; | ||
133 | static unsigned char interrupt_data[2][32]; | ||
134 | static int interrupt_data_len[2]; | ||
135 | static int int_data_last; | ||
136 | static unsigned char *reply_ptr; | ||
137 | static int data_index; | ||
138 | static int data_len; | ||
139 | static volatile int adb_int_pending; | ||
140 | static volatile int disable_poll; | ||
141 | static struct adb_request bright_req_1, bright_req_2; | ||
142 | static struct device_node *vias; | ||
143 | static int pmu_kind = PMU_UNKNOWN; | ||
144 | static int pmu_fully_inited = 0; | ||
145 | static int pmu_has_adb; | ||
146 | static unsigned char __iomem *gpio_reg = NULL; | ||
147 | static int gpio_irq = -1; | ||
148 | static int gpio_irq_enabled = -1; | ||
149 | static volatile int pmu_suspended = 0; | ||
150 | static spinlock_t pmu_lock; | ||
151 | static u8 pmu_intr_mask; | ||
152 | static int pmu_version; | ||
153 | static int drop_interrupts; | ||
154 | #ifdef CONFIG_PMAC_PBOOK | ||
155 | static int option_lid_wakeup = 1; | ||
156 | static int sleep_in_progress; | ||
157 | #endif /* CONFIG_PMAC_PBOOK */ | ||
158 | static unsigned long async_req_locks; | ||
159 | static unsigned int pmu_irq_stats[11]; | ||
160 | |||
161 | static struct proc_dir_entry *proc_pmu_root; | ||
162 | static struct proc_dir_entry *proc_pmu_info; | ||
163 | static struct proc_dir_entry *proc_pmu_irqstats; | ||
164 | static struct proc_dir_entry *proc_pmu_options; | ||
165 | static int option_server_mode; | ||
166 | |||
167 | #ifdef CONFIG_PMAC_PBOOK | ||
168 | int pmu_battery_count; | ||
169 | int pmu_cur_battery; | ||
170 | unsigned int pmu_power_flags; | ||
171 | struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; | ||
172 | static int query_batt_timer = BATTERY_POLLING_COUNT; | ||
173 | static struct adb_request batt_req; | ||
174 | static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; | ||
175 | #endif /* CONFIG_PMAC_PBOOK */ | ||
176 | |||
177 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | ||
178 | extern int disable_kernel_backlight; | ||
179 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | ||
180 | |||
181 | int __fake_sleep; | ||
182 | int asleep; | ||
183 | struct notifier_block *sleep_notifier_list; | ||
184 | |||
185 | #ifdef CONFIG_ADB | ||
186 | static int adb_dev_map = 0; | ||
187 | static int pmu_adb_flags; | ||
188 | |||
189 | static int pmu_probe(void); | ||
190 | static int pmu_init(void); | ||
191 | static int pmu_send_request(struct adb_request *req, int sync); | ||
192 | static int pmu_adb_autopoll(int devs); | ||
193 | static int pmu_adb_reset_bus(void); | ||
194 | #endif /* CONFIG_ADB */ | ||
195 | |||
196 | static int init_pmu(void); | ||
197 | static int pmu_queue_request(struct adb_request *req); | ||
198 | static void pmu_start(void); | ||
199 | static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs); | ||
200 | static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs); | ||
201 | static int proc_get_info(char *page, char **start, off_t off, | ||
202 | int count, int *eof, void *data); | ||
203 | static int proc_get_irqstats(char *page, char **start, off_t off, | ||
204 | int count, int *eof, void *data); | ||
205 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
206 | static int pmu_set_backlight_level(int level, void* data); | ||
207 | static int pmu_set_backlight_enable(int on, int level, void* data); | ||
208 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
209 | #ifdef CONFIG_PMAC_PBOOK | ||
210 | static void pmu_pass_intr(unsigned char *data, int len); | ||
211 | static int proc_get_batt(char *page, char **start, off_t off, | ||
212 | int count, int *eof, void *data); | ||
213 | #endif /* CONFIG_PMAC_PBOOK */ | ||
214 | static int proc_read_options(char *page, char **start, off_t off, | ||
215 | int count, int *eof, void *data); | ||
216 | static int proc_write_options(struct file *file, const char __user *buffer, | ||
217 | unsigned long count, void *data); | ||
218 | |||
219 | #ifdef CONFIG_ADB | ||
220 | struct adb_driver via_pmu_driver = { | ||
221 | "PMU", | ||
222 | pmu_probe, | ||
223 | pmu_init, | ||
224 | pmu_send_request, | ||
225 | pmu_adb_autopoll, | ||
226 | pmu_poll_adb, | ||
227 | pmu_adb_reset_bus | ||
228 | }; | ||
229 | #endif /* CONFIG_ADB */ | ||
230 | |||
231 | extern void low_sleep_handler(void); | ||
232 | extern void enable_kernel_altivec(void); | ||
233 | extern void enable_kernel_fp(void); | ||
234 | |||
235 | #ifdef DEBUG_SLEEP | ||
236 | int pmu_polled_request(struct adb_request *req); | ||
237 | int pmu_wink(struct adb_request *req); | ||
238 | #endif | ||
239 | |||
240 | /* | ||
241 | * This table indicates for each PMU opcode: | ||
242 | * - the number of data bytes to be sent with the command, or -1 | ||
243 | * if a length byte should be sent, | ||
244 | * - the number of response bytes which the PMU will return, or | ||
245 | * -1 if it will send a length byte. | ||
246 | */ | ||
247 | static const s8 pmu_data_len[256][2] __openfirmwaredata = { | ||
248 | /* 0 1 2 3 4 5 6 7 */ | ||
249 | /*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
250 | /*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
251 | /*10*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
252 | /*18*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0, 0}, | ||
253 | /*20*/ {-1, 0},{ 0, 0},{ 2, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
254 | /*28*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0,-1}, | ||
255 | /*30*/ { 4, 0},{20, 0},{-1, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
256 | /*38*/ { 0, 4},{ 0,20},{ 2,-1},{ 2, 1},{ 3,-1},{-1,-1},{-1,-1},{ 4, 0}, | ||
257 | /*40*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
258 | /*48*/ { 0, 1},{ 0, 1},{-1,-1},{ 1, 0},{ 1, 0},{-1,-1},{-1,-1},{-1,-1}, | ||
259 | /*50*/ { 1, 0},{ 0, 0},{ 2, 0},{ 2, 0},{-1, 0},{ 1, 0},{ 3, 0},{ 1, 0}, | ||
260 | /*58*/ { 0, 1},{ 1, 0},{ 0, 2},{ 0, 2},{ 0,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
261 | /*60*/ { 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
262 | /*68*/ { 0, 3},{ 0, 3},{ 0, 2},{ 0, 8},{ 0,-1},{ 0,-1},{-1,-1},{-1,-1}, | ||
263 | /*70*/ { 1, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
264 | /*78*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{ 5, 1},{ 4, 1},{ 4, 1}, | ||
265 | /*80*/ { 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
266 | /*88*/ { 0, 5},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
267 | /*90*/ { 1, 0},{ 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
268 | /*98*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
269 | /*a0*/ { 2, 0},{ 2, 0},{ 2, 0},{ 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0}, | ||
270 | /*a8*/ { 1, 1},{ 1, 0},{ 3, 0},{ 2, 0},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
271 | /*b0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
272 | /*b8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
273 | /*c0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
274 | /*c8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
275 | /*d0*/ { 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
276 | /*d8*/ { 1, 1},{ 1, 1},{-1,-1},{-1,-1},{ 0, 1},{ 0,-1},{-1,-1},{-1,-1}, | ||
277 | /*e0*/ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{ 4, 0},{-1, 0},{-1, 0}, | ||
278 | /*e8*/ { 3,-1},{-1,-1},{ 0, 1},{-1,-1},{ 0,-1},{-1,-1},{-1,-1},{ 0, 0}, | ||
279 | /*f0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
280 | /*f8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
281 | }; | ||
282 | |||
283 | static char *pbook_type[] = { | ||
284 | "Unknown PowerBook", | ||
285 | "PowerBook 2400/3400/3500(G3)", | ||
286 | "PowerBook G3 Series", | ||
287 | "1999 PowerBook G3", | ||
288 | "Core99" | ||
289 | }; | ||
290 | |||
291 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
292 | static struct backlight_controller pmu_backlight_controller = { | ||
293 | pmu_set_backlight_enable, | ||
294 | pmu_set_backlight_level | ||
295 | }; | ||
296 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
297 | |||
298 | int __openfirmware | ||
299 | find_via_pmu(void) | ||
300 | { | ||
301 | if (via != 0) | ||
302 | return 1; | ||
303 | vias = find_devices("via-pmu"); | ||
304 | if (vias == 0) | ||
305 | return 0; | ||
306 | if (vias->next != 0) | ||
307 | printk(KERN_WARNING "Warning: only using 1st via-pmu\n"); | ||
308 | |||
309 | if (vias->n_addrs < 1 || vias->n_intrs < 1) { | ||
310 | printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n", | ||
311 | vias->n_addrs, vias->n_intrs); | ||
312 | if (vias->n_addrs < 1 || vias->n_intrs < 1) | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | spin_lock_init(&pmu_lock); | ||
317 | |||
318 | pmu_has_adb = 1; | ||
319 | |||
320 | pmu_intr_mask = PMU_INT_PCEJECT | | ||
321 | PMU_INT_SNDBRT | | ||
322 | PMU_INT_ADB | | ||
323 | PMU_INT_TICK; | ||
324 | |||
325 | if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0) | ||
326 | || device_is_compatible(vias->parent, "ohare"))) | ||
327 | pmu_kind = PMU_OHARE_BASED; | ||
328 | else if (device_is_compatible(vias->parent, "paddington")) | ||
329 | pmu_kind = PMU_PADDINGTON_BASED; | ||
330 | else if (device_is_compatible(vias->parent, "heathrow")) | ||
331 | pmu_kind = PMU_HEATHROW_BASED; | ||
332 | else if (device_is_compatible(vias->parent, "Keylargo") | ||
333 | || device_is_compatible(vias->parent, "K2-Keylargo")) { | ||
334 | struct device_node *gpio, *gpiop; | ||
335 | |||
336 | pmu_kind = PMU_KEYLARGO_BASED; | ||
337 | pmu_has_adb = (find_type_devices("adb") != NULL); | ||
338 | pmu_intr_mask = PMU_INT_PCEJECT | | ||
339 | PMU_INT_SNDBRT | | ||
340 | PMU_INT_ADB | | ||
341 | PMU_INT_TICK | | ||
342 | PMU_INT_ENVIRONMENT; | ||
343 | |||
344 | gpiop = find_devices("gpio"); | ||
345 | if (gpiop && gpiop->n_addrs) { | ||
346 | gpio_reg = ioremap(gpiop->addrs->address, 0x10); | ||
347 | gpio = find_devices("extint-gpio1"); | ||
348 | if (gpio == NULL) | ||
349 | gpio = find_devices("pmu-interrupt"); | ||
350 | if (gpio && gpio->parent == gpiop && gpio->n_intrs) | ||
351 | gpio_irq = gpio->intrs[0].line; | ||
352 | } | ||
353 | } else | ||
354 | pmu_kind = PMU_UNKNOWN; | ||
355 | |||
356 | via = ioremap(vias->addrs->address, 0x2000); | ||
357 | |||
358 | out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ | ||
359 | out_8(&via[IFR], 0x7f); /* clear IFR */ | ||
360 | |||
361 | pmu_state = idle; | ||
362 | |||
363 | if (!init_pmu()) { | ||
364 | via = NULL; | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n", | ||
369 | PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version); | ||
370 | |||
371 | sys_ctrler = SYS_CTRLER_PMU; | ||
372 | |||
373 | return 1; | ||
374 | } | ||
375 | |||
376 | #ifdef CONFIG_ADB | ||
377 | static int __openfirmware | ||
378 | pmu_probe(void) | ||
379 | { | ||
380 | return vias == NULL? -ENODEV: 0; | ||
381 | } | ||
382 | |||
383 | static int __init | ||
384 | pmu_init(void) | ||
385 | { | ||
386 | if (vias == NULL) | ||
387 | return -ENODEV; | ||
388 | return 0; | ||
389 | } | ||
390 | #endif /* CONFIG_ADB */ | ||
391 | |||
392 | /* | ||
393 | * We can't wait until pmu_init gets called, that happens too late. | ||
394 | * It happens after IDE and SCSI initialization, which can take a few | ||
395 | * seconds, and by that time the PMU could have given up on us and | ||
396 | * turned us off. | ||
397 | * Thus this is called with arch_initcall rather than device_initcall. | ||
398 | */ | ||
399 | static int __init via_pmu_start(void) | ||
400 | { | ||
401 | if (vias == NULL) | ||
402 | return -ENODEV; | ||
403 | |||
404 | bright_req_1.complete = 1; | ||
405 | bright_req_2.complete = 1; | ||
406 | #ifdef CONFIG_PMAC_PBOOK | ||
407 | batt_req.complete = 1; | ||
408 | #endif | ||
409 | |||
410 | if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", | ||
411 | (void *)0)) { | ||
412 | printk(KERN_ERR "VIA-PMU: can't get irq %d\n", | ||
413 | vias->intrs[0].line); | ||
414 | return -EAGAIN; | ||
415 | } | ||
416 | |||
417 | if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) { | ||
418 | if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0)) | ||
419 | printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq); | ||
420 | gpio_irq_enabled = 1; | ||
421 | } | ||
422 | |||
423 | /* Enable interrupts */ | ||
424 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); | ||
425 | |||
426 | pmu_fully_inited = 1; | ||
427 | |||
428 | /* Make sure PMU settle down before continuing. This is _very_ important | ||
429 | * since the IDE probe may shut interrupts down for quite a bit of time. If | ||
430 | * a PMU communication is pending while this happens, the PMU may timeout | ||
431 | * Not that on Core99 machines, the PMU keeps sending us environement | ||
432 | * messages, we should find a way to either fix IDE or make it call | ||
433 | * pmu_suspend() before masking interrupts. This can also happens while | ||
434 | * scolling with some fbdevs. | ||
435 | */ | ||
436 | do { | ||
437 | pmu_poll(); | ||
438 | } while (pmu_state != idle); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | arch_initcall(via_pmu_start); | ||
444 | |||
445 | /* | ||
446 | * This has to be done after pci_init, which is a subsys_initcall. | ||
447 | */ | ||
448 | static int __init via_pmu_dev_init(void) | ||
449 | { | ||
450 | if (vias == NULL) | ||
451 | return -ENODEV; | ||
452 | |||
453 | #ifndef CONFIG_PPC64 | ||
454 | request_OF_resource(vias, 0, NULL); | ||
455 | #endif | ||
456 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
457 | /* Enable backlight */ | ||
458 | register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); | ||
459 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
460 | |||
461 | #ifdef CONFIG_PMAC_PBOOK | ||
462 | if (machine_is_compatible("AAPL,3400/2400") || | ||
463 | machine_is_compatible("AAPL,3500")) { | ||
464 | int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
465 | NULL, PMAC_MB_INFO_MODEL, 0); | ||
466 | pmu_battery_count = 1; | ||
467 | if (mb == PMAC_TYPE_COMET) | ||
468 | pmu_batteries[0].flags |= PMU_BATT_TYPE_COMET; | ||
469 | else | ||
470 | pmu_batteries[0].flags |= PMU_BATT_TYPE_HOOPER; | ||
471 | } else if (machine_is_compatible("AAPL,PowerBook1998") || | ||
472 | machine_is_compatible("PowerBook1,1")) { | ||
473 | pmu_battery_count = 2; | ||
474 | pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; | ||
475 | pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; | ||
476 | } else { | ||
477 | struct device_node* prim = find_devices("power-mgt"); | ||
478 | u32 *prim_info = NULL; | ||
479 | if (prim) | ||
480 | prim_info = (u32 *)get_property(prim, "prim-info", NULL); | ||
481 | if (prim_info) { | ||
482 | /* Other stuffs here yet unknown */ | ||
483 | pmu_battery_count = (prim_info[6] >> 16) & 0xff; | ||
484 | pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; | ||
485 | if (pmu_battery_count > 1) | ||
486 | pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; | ||
487 | } | ||
488 | } | ||
489 | #endif /* CONFIG_PMAC_PBOOK */ | ||
490 | /* Create /proc/pmu */ | ||
491 | proc_pmu_root = proc_mkdir("pmu", NULL); | ||
492 | if (proc_pmu_root) { | ||
493 | #ifdef CONFIG_PMAC_PBOOK | ||
494 | int i; | ||
495 | |||
496 | for (i=0; i<pmu_battery_count; i++) { | ||
497 | char title[16]; | ||
498 | sprintf(title, "battery_%d", i); | ||
499 | proc_pmu_batt[i] = create_proc_read_entry(title, 0, proc_pmu_root, | ||
500 | proc_get_batt, (void *)i); | ||
501 | } | ||
502 | #endif /* CONFIG_PMAC_PBOOK */ | ||
503 | |||
504 | proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root, | ||
505 | proc_get_info, NULL); | ||
506 | proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root, | ||
507 | proc_get_irqstats, NULL); | ||
508 | proc_pmu_options = create_proc_entry("options", 0600, proc_pmu_root); | ||
509 | if (proc_pmu_options) { | ||
510 | proc_pmu_options->nlink = 1; | ||
511 | proc_pmu_options->read_proc = proc_read_options; | ||
512 | proc_pmu_options->write_proc = proc_write_options; | ||
513 | } | ||
514 | } | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | device_initcall(via_pmu_dev_init); | ||
519 | |||
520 | static int __openfirmware | ||
521 | init_pmu(void) | ||
522 | { | ||
523 | int timeout; | ||
524 | struct adb_request req; | ||
525 | |||
526 | out_8(&via[B], via[B] | TREQ); /* negate TREQ */ | ||
527 | out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK); /* TACK in, TREQ out */ | ||
528 | |||
529 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); | ||
530 | timeout = 100000; | ||
531 | while (!req.complete) { | ||
532 | if (--timeout < 0) { | ||
533 | printk(KERN_ERR "init_pmu: no response from PMU\n"); | ||
534 | return 0; | ||
535 | } | ||
536 | udelay(10); | ||
537 | pmu_poll(); | ||
538 | } | ||
539 | |||
540 | /* ack all pending interrupts */ | ||
541 | timeout = 100000; | ||
542 | interrupt_data[0][0] = 1; | ||
543 | while (interrupt_data[0][0] || pmu_state != idle) { | ||
544 | if (--timeout < 0) { | ||
545 | printk(KERN_ERR "init_pmu: timed out acking intrs\n"); | ||
546 | return 0; | ||
547 | } | ||
548 | if (pmu_state == idle) | ||
549 | adb_int_pending = 1; | ||
550 | via_pmu_interrupt(0, NULL, NULL); | ||
551 | udelay(10); | ||
552 | } | ||
553 | |||
554 | /* Tell PMU we are ready. */ | ||
555 | if (pmu_kind == PMU_KEYLARGO_BASED) { | ||
556 | pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); | ||
557 | while (!req.complete) | ||
558 | pmu_poll(); | ||
559 | } | ||
560 | |||
561 | /* Read PMU version */ | ||
562 | pmu_request(&req, NULL, 1, PMU_GET_VERSION); | ||
563 | pmu_wait_complete(&req); | ||
564 | if (req.reply_len > 0) | ||
565 | pmu_version = req.reply[0]; | ||
566 | |||
567 | /* Read server mode setting */ | ||
568 | if (pmu_kind == PMU_KEYLARGO_BASED) { | ||
569 | pmu_request(&req, NULL, 2, PMU_POWER_EVENTS, | ||
570 | PMU_PWR_GET_POWERUP_EVENTS); | ||
571 | pmu_wait_complete(&req); | ||
572 | if (req.reply_len == 2) { | ||
573 | if (req.reply[1] & PMU_PWR_WAKEUP_AC_INSERT) | ||
574 | option_server_mode = 1; | ||
575 | printk(KERN_INFO "via-pmu: Server Mode is %s\n", | ||
576 | option_server_mode ? "enabled" : "disabled"); | ||
577 | } | ||
578 | } | ||
579 | return 1; | ||
580 | } | ||
581 | |||
582 | int | ||
583 | pmu_get_model(void) | ||
584 | { | ||
585 | return pmu_kind; | ||
586 | } | ||
587 | |||
588 | #ifndef CONFIG_PPC64 | ||
589 | static inline void wakeup_decrementer(void) | ||
590 | { | ||
591 | set_dec(tb_ticks_per_jiffy); | ||
592 | /* No currently-supported powerbook has a 601, | ||
593 | * so use get_tbl, not native | ||
594 | */ | ||
595 | last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); | ||
596 | } | ||
597 | #endif | ||
598 | |||
599 | static void pmu_set_server_mode(int server_mode) | ||
600 | { | ||
601 | struct adb_request req; | ||
602 | |||
603 | if (pmu_kind != PMU_KEYLARGO_BASED) | ||
604 | return; | ||
605 | |||
606 | option_server_mode = server_mode; | ||
607 | pmu_request(&req, NULL, 2, PMU_POWER_EVENTS, PMU_PWR_GET_POWERUP_EVENTS); | ||
608 | pmu_wait_complete(&req); | ||
609 | if (req.reply_len < 2) | ||
610 | return; | ||
611 | if (server_mode) | ||
612 | pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, | ||
613 | PMU_PWR_SET_POWERUP_EVENTS, | ||
614 | req.reply[0], PMU_PWR_WAKEUP_AC_INSERT); | ||
615 | else | ||
616 | pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, | ||
617 | PMU_PWR_CLR_POWERUP_EVENTS, | ||
618 | req.reply[0], PMU_PWR_WAKEUP_AC_INSERT); | ||
619 | pmu_wait_complete(&req); | ||
620 | } | ||
621 | |||
622 | #ifdef CONFIG_PMAC_PBOOK | ||
623 | |||
624 | /* This new version of the code for 2400/3400/3500 powerbooks | ||
625 | * is inspired from the implementation in gkrellm-pmu | ||
626 | */ | ||
627 | static void __pmac | ||
628 | done_battery_state_ohare(struct adb_request* req) | ||
629 | { | ||
630 | /* format: | ||
631 | * [0] : flags | ||
632 | * 0x01 : AC indicator | ||
633 | * 0x02 : charging | ||
634 | * 0x04 : battery exist | ||
635 | * 0x08 : | ||
636 | * 0x10 : | ||
637 | * 0x20 : full charged | ||
638 | * 0x40 : pcharge reset | ||
639 | * 0x80 : battery exist | ||
640 | * | ||
641 | * [1][2] : battery voltage | ||
642 | * [3] : CPU temperature | ||
643 | * [4] : battery temperature | ||
644 | * [5] : current | ||
645 | * [6][7] : pcharge | ||
646 | * --tkoba | ||
647 | */ | ||
648 | unsigned int bat_flags = PMU_BATT_TYPE_HOOPER; | ||
649 | long pcharge, charge, vb, vmax, lmax; | ||
650 | long vmax_charging, vmax_charged; | ||
651 | long amperage, voltage, time, max; | ||
652 | int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
653 | NULL, PMAC_MB_INFO_MODEL, 0); | ||
654 | |||
655 | if (req->reply[0] & 0x01) | ||
656 | pmu_power_flags |= PMU_PWR_AC_PRESENT; | ||
657 | else | ||
658 | pmu_power_flags &= ~PMU_PWR_AC_PRESENT; | ||
659 | |||
660 | if (mb == PMAC_TYPE_COMET) { | ||
661 | vmax_charged = 189; | ||
662 | vmax_charging = 213; | ||
663 | lmax = 6500; | ||
664 | } else { | ||
665 | vmax_charged = 330; | ||
666 | vmax_charging = 330; | ||
667 | lmax = 6500; | ||
668 | } | ||
669 | vmax = vmax_charged; | ||
670 | |||
671 | /* If battery installed */ | ||
672 | if (req->reply[0] & 0x04) { | ||
673 | bat_flags |= PMU_BATT_PRESENT; | ||
674 | if (req->reply[0] & 0x02) | ||
675 | bat_flags |= PMU_BATT_CHARGING; | ||
676 | vb = (req->reply[1] << 8) | req->reply[2]; | ||
677 | voltage = (vb * 265 + 72665) / 10; | ||
678 | amperage = req->reply[5]; | ||
679 | if ((req->reply[0] & 0x01) == 0) { | ||
680 | if (amperage > 200) | ||
681 | vb += ((amperage - 200) * 15)/100; | ||
682 | } else if (req->reply[0] & 0x02) { | ||
683 | vb = (vb * 97) / 100; | ||
684 | vmax = vmax_charging; | ||
685 | } | ||
686 | charge = (100 * vb) / vmax; | ||
687 | if (req->reply[0] & 0x40) { | ||
688 | pcharge = (req->reply[6] << 8) + req->reply[7]; | ||
689 | if (pcharge > lmax) | ||
690 | pcharge = lmax; | ||
691 | pcharge *= 100; | ||
692 | pcharge = 100 - pcharge / lmax; | ||
693 | if (pcharge < charge) | ||
694 | charge = pcharge; | ||
695 | } | ||
696 | if (amperage > 0) | ||
697 | time = (charge * 16440) / amperage; | ||
698 | else | ||
699 | time = 0; | ||
700 | max = 100; | ||
701 | amperage = -amperage; | ||
702 | } else | ||
703 | charge = max = amperage = voltage = time = 0; | ||
704 | |||
705 | pmu_batteries[pmu_cur_battery].flags = bat_flags; | ||
706 | pmu_batteries[pmu_cur_battery].charge = charge; | ||
707 | pmu_batteries[pmu_cur_battery].max_charge = max; | ||
708 | pmu_batteries[pmu_cur_battery].amperage = amperage; | ||
709 | pmu_batteries[pmu_cur_battery].voltage = voltage; | ||
710 | pmu_batteries[pmu_cur_battery].time_remaining = time; | ||
711 | |||
712 | clear_bit(0, &async_req_locks); | ||
713 | } | ||
714 | |||
715 | static void __pmac | ||
716 | done_battery_state_smart(struct adb_request* req) | ||
717 | { | ||
718 | /* format: | ||
719 | * [0] : format of this structure (known: 3,4,5) | ||
720 | * [1] : flags | ||
721 | * | ||
722 | * format 3 & 4: | ||
723 | * | ||
724 | * [2] : charge | ||
725 | * [3] : max charge | ||
726 | * [4] : current | ||
727 | * [5] : voltage | ||
728 | * | ||
729 | * format 5: | ||
730 | * | ||
731 | * [2][3] : charge | ||
732 | * [4][5] : max charge | ||
733 | * [6][7] : current | ||
734 | * [8][9] : voltage | ||
735 | */ | ||
736 | |||
737 | unsigned int bat_flags = PMU_BATT_TYPE_SMART; | ||
738 | int amperage; | ||
739 | unsigned int capa, max, voltage; | ||
740 | |||
741 | if (req->reply[1] & 0x01) | ||
742 | pmu_power_flags |= PMU_PWR_AC_PRESENT; | ||
743 | else | ||
744 | pmu_power_flags &= ~PMU_PWR_AC_PRESENT; | ||
745 | |||
746 | |||
747 | capa = max = amperage = voltage = 0; | ||
748 | |||
749 | if (req->reply[1] & 0x04) { | ||
750 | bat_flags |= PMU_BATT_PRESENT; | ||
751 | switch(req->reply[0]) { | ||
752 | case 3: | ||
753 | case 4: capa = req->reply[2]; | ||
754 | max = req->reply[3]; | ||
755 | amperage = *((signed char *)&req->reply[4]); | ||
756 | voltage = req->reply[5]; | ||
757 | break; | ||
758 | case 5: capa = (req->reply[2] << 8) | req->reply[3]; | ||
759 | max = (req->reply[4] << 8) | req->reply[5]; | ||
760 | amperage = *((signed short *)&req->reply[6]); | ||
761 | voltage = (req->reply[8] << 8) | req->reply[9]; | ||
762 | break; | ||
763 | default: | ||
764 | printk(KERN_WARNING "pmu.c : unrecognized battery info, len: %d, %02x %02x %02x %02x\n", | ||
765 | req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]); | ||
766 | break; | ||
767 | } | ||
768 | } | ||
769 | |||
770 | if ((req->reply[1] & 0x01) && (amperage > 0)) | ||
771 | bat_flags |= PMU_BATT_CHARGING; | ||
772 | |||
773 | pmu_batteries[pmu_cur_battery].flags = bat_flags; | ||
774 | pmu_batteries[pmu_cur_battery].charge = capa; | ||
775 | pmu_batteries[pmu_cur_battery].max_charge = max; | ||
776 | pmu_batteries[pmu_cur_battery].amperage = amperage; | ||
777 | pmu_batteries[pmu_cur_battery].voltage = voltage; | ||
778 | if (amperage) { | ||
779 | if ((req->reply[1] & 0x01) && (amperage > 0)) | ||
780 | pmu_batteries[pmu_cur_battery].time_remaining | ||
781 | = ((max-capa) * 3600) / amperage; | ||
782 | else | ||
783 | pmu_batteries[pmu_cur_battery].time_remaining | ||
784 | = (capa * 3600) / (-amperage); | ||
785 | } else | ||
786 | pmu_batteries[pmu_cur_battery].time_remaining = 0; | ||
787 | |||
788 | pmu_cur_battery = (pmu_cur_battery + 1) % pmu_battery_count; | ||
789 | |||
790 | clear_bit(0, &async_req_locks); | ||
791 | } | ||
792 | |||
793 | static void __pmac | ||
794 | query_battery_state(void) | ||
795 | { | ||
796 | if (test_and_set_bit(0, &async_req_locks)) | ||
797 | return; | ||
798 | if (pmu_kind == PMU_OHARE_BASED) | ||
799 | pmu_request(&batt_req, done_battery_state_ohare, | ||
800 | 1, PMU_BATTERY_STATE); | ||
801 | else | ||
802 | pmu_request(&batt_req, done_battery_state_smart, | ||
803 | 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); | ||
804 | } | ||
805 | |||
806 | #endif /* CONFIG_PMAC_PBOOK */ | ||
807 | |||
808 | static int __pmac | ||
809 | proc_get_info(char *page, char **start, off_t off, | ||
810 | int count, int *eof, void *data) | ||
811 | { | ||
812 | char* p = page; | ||
813 | |||
814 | p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION); | ||
815 | p += sprintf(p, "PMU firmware version : %02x\n", pmu_version); | ||
816 | #ifdef CONFIG_PMAC_PBOOK | ||
817 | p += sprintf(p, "AC Power : %d\n", | ||
818 | ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0)); | ||
819 | p += sprintf(p, "Battery count : %d\n", pmu_battery_count); | ||
820 | #endif /* CONFIG_PMAC_PBOOK */ | ||
821 | |||
822 | return p - page; | ||
823 | } | ||
824 | |||
825 | static int __pmac | ||
826 | proc_get_irqstats(char *page, char **start, off_t off, | ||
827 | int count, int *eof, void *data) | ||
828 | { | ||
829 | int i; | ||
830 | char* p = page; | ||
831 | static const char *irq_names[] = { | ||
832 | "Total CB1 triggered events", | ||
833 | "Total GPIO1 triggered events", | ||
834 | "PC-Card eject button", | ||
835 | "Sound/Brightness button", | ||
836 | "ADB message", | ||
837 | "Battery state change", | ||
838 | "Environment interrupt", | ||
839 | "Tick timer", | ||
840 | "Ghost interrupt (zero len)", | ||
841 | "Empty interrupt (empty mask)", | ||
842 | "Max irqs in a row" | ||
843 | }; | ||
844 | |||
845 | for (i=0; i<11; i++) { | ||
846 | p += sprintf(p, " %2u: %10u (%s)\n", | ||
847 | i, pmu_irq_stats[i], irq_names[i]); | ||
848 | } | ||
849 | return p - page; | ||
850 | } | ||
851 | |||
852 | #ifdef CONFIG_PMAC_PBOOK | ||
853 | static int __pmac | ||
854 | proc_get_batt(char *page, char **start, off_t off, | ||
855 | int count, int *eof, void *data) | ||
856 | { | ||
857 | int batnum = (int)data; | ||
858 | char *p = page; | ||
859 | |||
860 | p += sprintf(p, "\n"); | ||
861 | p += sprintf(p, "flags : %08x\n", | ||
862 | pmu_batteries[batnum].flags); | ||
863 | p += sprintf(p, "charge : %d\n", | ||
864 | pmu_batteries[batnum].charge); | ||
865 | p += sprintf(p, "max_charge : %d\n", | ||
866 | pmu_batteries[batnum].max_charge); | ||
867 | p += sprintf(p, "current : %d\n", | ||
868 | pmu_batteries[batnum].amperage); | ||
869 | p += sprintf(p, "voltage : %d\n", | ||
870 | pmu_batteries[batnum].voltage); | ||
871 | p += sprintf(p, "time rem. : %d\n", | ||
872 | pmu_batteries[batnum].time_remaining); | ||
873 | |||
874 | return p - page; | ||
875 | } | ||
876 | #endif /* CONFIG_PMAC_PBOOK */ | ||
877 | |||
878 | static int __pmac | ||
879 | proc_read_options(char *page, char **start, off_t off, | ||
880 | int count, int *eof, void *data) | ||
881 | { | ||
882 | char *p = page; | ||
883 | |||
884 | #ifdef CONFIG_PMAC_PBOOK | ||
885 | if (pmu_kind == PMU_KEYLARGO_BASED && | ||
886 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) | ||
887 | p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); | ||
888 | #endif /* CONFIG_PMAC_PBOOK */ | ||
889 | if (pmu_kind == PMU_KEYLARGO_BASED) | ||
890 | p += sprintf(p, "server_mode=%d\n", option_server_mode); | ||
891 | |||
892 | return p - page; | ||
893 | } | ||
894 | |||
895 | static int __pmac | ||
896 | proc_write_options(struct file *file, const char __user *buffer, | ||
897 | unsigned long count, void *data) | ||
898 | { | ||
899 | char tmp[33]; | ||
900 | char *label, *val; | ||
901 | unsigned long fcount = count; | ||
902 | |||
903 | if (!count) | ||
904 | return -EINVAL; | ||
905 | if (count > 32) | ||
906 | count = 32; | ||
907 | if (copy_from_user(tmp, buffer, count)) | ||
908 | return -EFAULT; | ||
909 | tmp[count] = 0; | ||
910 | |||
911 | label = tmp; | ||
912 | while(*label == ' ') | ||
913 | label++; | ||
914 | val = label; | ||
915 | while(*val && (*val != '=')) { | ||
916 | if (*val == ' ') | ||
917 | *val = 0; | ||
918 | val++; | ||
919 | } | ||
920 | if ((*val) == 0) | ||
921 | return -EINVAL; | ||
922 | *(val++) = 0; | ||
923 | while(*val == ' ') | ||
924 | val++; | ||
925 | #ifdef CONFIG_PMAC_PBOOK | ||
926 | if (pmu_kind == PMU_KEYLARGO_BASED && | ||
927 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) | ||
928 | if (!strcmp(label, "lid_wakeup")) | ||
929 | option_lid_wakeup = ((*val) == '1'); | ||
930 | #endif /* CONFIG_PMAC_PBOOK */ | ||
931 | if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) { | ||
932 | int new_value; | ||
933 | new_value = ((*val) == '1'); | ||
934 | if (new_value != option_server_mode) | ||
935 | pmu_set_server_mode(new_value); | ||
936 | } | ||
937 | return fcount; | ||
938 | } | ||
939 | |||
940 | #ifdef CONFIG_ADB | ||
941 | /* Send an ADB command */ | ||
942 | static int __pmac | ||
943 | pmu_send_request(struct adb_request *req, int sync) | ||
944 | { | ||
945 | int i, ret; | ||
946 | |||
947 | if ((vias == NULL) || (!pmu_fully_inited)) { | ||
948 | req->complete = 1; | ||
949 | return -ENXIO; | ||
950 | } | ||
951 | |||
952 | ret = -EINVAL; | ||
953 | |||
954 | switch (req->data[0]) { | ||
955 | case PMU_PACKET: | ||
956 | for (i = 0; i < req->nbytes - 1; ++i) | ||
957 | req->data[i] = req->data[i+1]; | ||
958 | --req->nbytes; | ||
959 | if (pmu_data_len[req->data[0]][1] != 0) { | ||
960 | req->reply[0] = ADB_RET_OK; | ||
961 | req->reply_len = 1; | ||
962 | } else | ||
963 | req->reply_len = 0; | ||
964 | ret = pmu_queue_request(req); | ||
965 | break; | ||
966 | case CUDA_PACKET: | ||
967 | switch (req->data[1]) { | ||
968 | case CUDA_GET_TIME: | ||
969 | if (req->nbytes != 2) | ||
970 | break; | ||
971 | req->data[0] = PMU_READ_RTC; | ||
972 | req->nbytes = 1; | ||
973 | req->reply_len = 3; | ||
974 | req->reply[0] = CUDA_PACKET; | ||
975 | req->reply[1] = 0; | ||
976 | req->reply[2] = CUDA_GET_TIME; | ||
977 | ret = pmu_queue_request(req); | ||
978 | break; | ||
979 | case CUDA_SET_TIME: | ||
980 | if (req->nbytes != 6) | ||
981 | break; | ||
982 | req->data[0] = PMU_SET_RTC; | ||
983 | req->nbytes = 5; | ||
984 | for (i = 1; i <= 4; ++i) | ||
985 | req->data[i] = req->data[i+1]; | ||
986 | req->reply_len = 3; | ||
987 | req->reply[0] = CUDA_PACKET; | ||
988 | req->reply[1] = 0; | ||
989 | req->reply[2] = CUDA_SET_TIME; | ||
990 | ret = pmu_queue_request(req); | ||
991 | break; | ||
992 | } | ||
993 | break; | ||
994 | case ADB_PACKET: | ||
995 | if (!pmu_has_adb) | ||
996 | return -ENXIO; | ||
997 | for (i = req->nbytes - 1; i > 1; --i) | ||
998 | req->data[i+2] = req->data[i]; | ||
999 | req->data[3] = req->nbytes - 2; | ||
1000 | req->data[2] = pmu_adb_flags; | ||
1001 | /*req->data[1] = req->data[1];*/ | ||
1002 | req->data[0] = PMU_ADB_CMD; | ||
1003 | req->nbytes += 2; | ||
1004 | req->reply_expected = 1; | ||
1005 | req->reply_len = 0; | ||
1006 | ret = pmu_queue_request(req); | ||
1007 | break; | ||
1008 | } | ||
1009 | if (ret) { | ||
1010 | req->complete = 1; | ||
1011 | return ret; | ||
1012 | } | ||
1013 | |||
1014 | if (sync) | ||
1015 | while (!req->complete) | ||
1016 | pmu_poll(); | ||
1017 | |||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | /* Enable/disable autopolling */ | ||
1022 | static int __pmac | ||
1023 | pmu_adb_autopoll(int devs) | ||
1024 | { | ||
1025 | struct adb_request req; | ||
1026 | |||
1027 | if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb) | ||
1028 | return -ENXIO; | ||
1029 | |||
1030 | if (devs) { | ||
1031 | adb_dev_map = devs; | ||
1032 | pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86, | ||
1033 | adb_dev_map >> 8, adb_dev_map); | ||
1034 | pmu_adb_flags = 2; | ||
1035 | } else { | ||
1036 | pmu_request(&req, NULL, 1, PMU_ADB_POLL_OFF); | ||
1037 | pmu_adb_flags = 0; | ||
1038 | } | ||
1039 | while (!req.complete) | ||
1040 | pmu_poll(); | ||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | /* Reset the ADB bus */ | ||
1045 | static int __pmac | ||
1046 | pmu_adb_reset_bus(void) | ||
1047 | { | ||
1048 | struct adb_request req; | ||
1049 | int save_autopoll = adb_dev_map; | ||
1050 | |||
1051 | if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb) | ||
1052 | return -ENXIO; | ||
1053 | |||
1054 | /* anyone got a better idea?? */ | ||
1055 | pmu_adb_autopoll(0); | ||
1056 | |||
1057 | req.nbytes = 5; | ||
1058 | req.done = NULL; | ||
1059 | req.data[0] = PMU_ADB_CMD; | ||
1060 | req.data[1] = 0; | ||
1061 | req.data[2] = ADB_BUSRESET; | ||
1062 | req.data[3] = 0; | ||
1063 | req.data[4] = 0; | ||
1064 | req.reply_len = 0; | ||
1065 | req.reply_expected = 1; | ||
1066 | if (pmu_queue_request(&req) != 0) { | ||
1067 | printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n"); | ||
1068 | return -EIO; | ||
1069 | } | ||
1070 | pmu_wait_complete(&req); | ||
1071 | |||
1072 | if (save_autopoll != 0) | ||
1073 | pmu_adb_autopoll(save_autopoll); | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | #endif /* CONFIG_ADB */ | ||
1078 | |||
1079 | /* Construct and send a pmu request */ | ||
1080 | int __openfirmware | ||
1081 | pmu_request(struct adb_request *req, void (*done)(struct adb_request *), | ||
1082 | int nbytes, ...) | ||
1083 | { | ||
1084 | va_list list; | ||
1085 | int i; | ||
1086 | |||
1087 | if (vias == NULL) | ||
1088 | return -ENXIO; | ||
1089 | |||
1090 | if (nbytes < 0 || nbytes > 32) { | ||
1091 | printk(KERN_ERR "pmu_request: bad nbytes (%d)\n", nbytes); | ||
1092 | req->complete = 1; | ||
1093 | return -EINVAL; | ||
1094 | } | ||
1095 | req->nbytes = nbytes; | ||
1096 | req->done = done; | ||
1097 | va_start(list, nbytes); | ||
1098 | for (i = 0; i < nbytes; ++i) | ||
1099 | req->data[i] = va_arg(list, int); | ||
1100 | va_end(list); | ||
1101 | req->reply_len = 0; | ||
1102 | req->reply_expected = 0; | ||
1103 | return pmu_queue_request(req); | ||
1104 | } | ||
1105 | |||
1106 | int __pmac | ||
1107 | pmu_queue_request(struct adb_request *req) | ||
1108 | { | ||
1109 | unsigned long flags; | ||
1110 | int nsend; | ||
1111 | |||
1112 | if (via == NULL) { | ||
1113 | req->complete = 1; | ||
1114 | return -ENXIO; | ||
1115 | } | ||
1116 | if (req->nbytes <= 0) { | ||
1117 | req->complete = 1; | ||
1118 | return 0; | ||
1119 | } | ||
1120 | nsend = pmu_data_len[req->data[0]][0]; | ||
1121 | if (nsend >= 0 && req->nbytes != nsend + 1) { | ||
1122 | req->complete = 1; | ||
1123 | return -EINVAL; | ||
1124 | } | ||
1125 | |||
1126 | req->next = NULL; | ||
1127 | req->sent = 0; | ||
1128 | req->complete = 0; | ||
1129 | |||
1130 | spin_lock_irqsave(&pmu_lock, flags); | ||
1131 | if (current_req != 0) { | ||
1132 | last_req->next = req; | ||
1133 | last_req = req; | ||
1134 | } else { | ||
1135 | current_req = req; | ||
1136 | last_req = req; | ||
1137 | if (pmu_state == idle) | ||
1138 | pmu_start(); | ||
1139 | } | ||
1140 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | static inline void | ||
1146 | wait_for_ack(void) | ||
1147 | { | ||
1148 | /* Sightly increased the delay, I had one occurrence of the message | ||
1149 | * reported | ||
1150 | */ | ||
1151 | int timeout = 4000; | ||
1152 | while ((in_8(&via[B]) & TACK) == 0) { | ||
1153 | if (--timeout < 0) { | ||
1154 | printk(KERN_ERR "PMU not responding (!ack)\n"); | ||
1155 | return; | ||
1156 | } | ||
1157 | udelay(10); | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | /* New PMU seems to be very sensitive to those timings, so we make sure | ||
1162 | * PCI is flushed immediately */ | ||
1163 | static inline void | ||
1164 | send_byte(int x) | ||
1165 | { | ||
1166 | volatile unsigned char __iomem *v = via; | ||
1167 | |||
1168 | out_8(&v[ACR], in_8(&v[ACR]) | SR_OUT | SR_EXT); | ||
1169 | out_8(&v[SR], x); | ||
1170 | out_8(&v[B], in_8(&v[B]) & ~TREQ); /* assert TREQ */ | ||
1171 | (void)in_8(&v[B]); | ||
1172 | } | ||
1173 | |||
1174 | static inline void | ||
1175 | recv_byte(void) | ||
1176 | { | ||
1177 | volatile unsigned char __iomem *v = via; | ||
1178 | |||
1179 | out_8(&v[ACR], (in_8(&v[ACR]) & ~SR_OUT) | SR_EXT); | ||
1180 | in_8(&v[SR]); /* resets SR */ | ||
1181 | out_8(&v[B], in_8(&v[B]) & ~TREQ); | ||
1182 | (void)in_8(&v[B]); | ||
1183 | } | ||
1184 | |||
1185 | static inline void | ||
1186 | pmu_done(struct adb_request *req) | ||
1187 | { | ||
1188 | void (*done)(struct adb_request *) = req->done; | ||
1189 | mb(); | ||
1190 | req->complete = 1; | ||
1191 | /* Here, we assume that if the request has a done member, the | ||
1192 | * struct request will survive to setting req->complete to 1 | ||
1193 | */ | ||
1194 | if (done) | ||
1195 | (*done)(req); | ||
1196 | } | ||
1197 | |||
1198 | static void __pmac | ||
1199 | pmu_start(void) | ||
1200 | { | ||
1201 | struct adb_request *req; | ||
1202 | |||
1203 | /* assert pmu_state == idle */ | ||
1204 | /* get the packet to send */ | ||
1205 | req = current_req; | ||
1206 | if (req == 0 || pmu_state != idle | ||
1207 | || (/*req->reply_expected && */req_awaiting_reply)) | ||
1208 | return; | ||
1209 | |||
1210 | pmu_state = sending; | ||
1211 | data_index = 1; | ||
1212 | data_len = pmu_data_len[req->data[0]][0]; | ||
1213 | |||
1214 | /* Sounds safer to make sure ACK is high before writing. This helped | ||
1215 | * kill a problem with ADB and some iBooks | ||
1216 | */ | ||
1217 | wait_for_ack(); | ||
1218 | /* set the shift register to shift out and send a byte */ | ||
1219 | send_byte(req->data[0]); | ||
1220 | } | ||
1221 | |||
1222 | void __openfirmware | ||
1223 | pmu_poll(void) | ||
1224 | { | ||
1225 | if (!via) | ||
1226 | return; | ||
1227 | if (disable_poll) | ||
1228 | return; | ||
1229 | via_pmu_interrupt(0, NULL, NULL); | ||
1230 | } | ||
1231 | |||
1232 | void __openfirmware | ||
1233 | pmu_poll_adb(void) | ||
1234 | { | ||
1235 | if (!via) | ||
1236 | return; | ||
1237 | if (disable_poll) | ||
1238 | return; | ||
1239 | /* Kicks ADB read when PMU is suspended */ | ||
1240 | adb_int_pending = 1; | ||
1241 | do { | ||
1242 | via_pmu_interrupt(0, NULL, NULL); | ||
1243 | } while (pmu_suspended && (adb_int_pending || pmu_state != idle | ||
1244 | || req_awaiting_reply)); | ||
1245 | } | ||
1246 | |||
1247 | void __openfirmware | ||
1248 | pmu_wait_complete(struct adb_request *req) | ||
1249 | { | ||
1250 | if (!via) | ||
1251 | return; | ||
1252 | while((pmu_state != idle && pmu_state != locked) || !req->complete) | ||
1253 | via_pmu_interrupt(0, NULL, NULL); | ||
1254 | } | ||
1255 | |||
1256 | /* This function loops until the PMU is idle and prevents it from | ||
1257 | * anwsering to ADB interrupts. pmu_request can still be called. | ||
1258 | * This is done to avoid spurrious shutdowns when we know we'll have | ||
1259 | * interrupts switched off for a long time | ||
1260 | */ | ||
1261 | void __openfirmware | ||
1262 | pmu_suspend(void) | ||
1263 | { | ||
1264 | unsigned long flags; | ||
1265 | #ifdef SUSPEND_USES_PMU | ||
1266 | struct adb_request *req; | ||
1267 | #endif | ||
1268 | if (!via) | ||
1269 | return; | ||
1270 | |||
1271 | spin_lock_irqsave(&pmu_lock, flags); | ||
1272 | pmu_suspended++; | ||
1273 | if (pmu_suspended > 1) { | ||
1274 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1275 | return; | ||
1276 | } | ||
1277 | |||
1278 | do { | ||
1279 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1280 | if (req_awaiting_reply) | ||
1281 | adb_int_pending = 1; | ||
1282 | via_pmu_interrupt(0, NULL, NULL); | ||
1283 | spin_lock_irqsave(&pmu_lock, flags); | ||
1284 | if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) { | ||
1285 | #ifdef SUSPEND_USES_PMU | ||
1286 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0); | ||
1287 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1288 | while(!req.complete) | ||
1289 | pmu_poll(); | ||
1290 | #else /* SUSPEND_USES_PMU */ | ||
1291 | if (gpio_irq >= 0) | ||
1292 | disable_irq_nosync(gpio_irq); | ||
1293 | out_8(&via[IER], CB1_INT | IER_CLR); | ||
1294 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1295 | #endif /* SUSPEND_USES_PMU */ | ||
1296 | break; | ||
1297 | } | ||
1298 | } while (1); | ||
1299 | } | ||
1300 | |||
1301 | void __openfirmware | ||
1302 | pmu_resume(void) | ||
1303 | { | ||
1304 | unsigned long flags; | ||
1305 | |||
1306 | if (!via || (pmu_suspended < 1)) | ||
1307 | return; | ||
1308 | |||
1309 | spin_lock_irqsave(&pmu_lock, flags); | ||
1310 | pmu_suspended--; | ||
1311 | if (pmu_suspended > 0) { | ||
1312 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1313 | return; | ||
1314 | } | ||
1315 | adb_int_pending = 1; | ||
1316 | #ifdef SUSPEND_USES_PMU | ||
1317 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); | ||
1318 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1319 | while(!req.complete) | ||
1320 | pmu_poll(); | ||
1321 | #else /* SUSPEND_USES_PMU */ | ||
1322 | if (gpio_irq >= 0) | ||
1323 | enable_irq(gpio_irq); | ||
1324 | out_8(&via[IER], CB1_INT | IER_SET); | ||
1325 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1326 | pmu_poll(); | ||
1327 | #endif /* SUSPEND_USES_PMU */ | ||
1328 | } | ||
1329 | |||
1330 | /* Interrupt data could be the result data from an ADB cmd */ | ||
1331 | static void __pmac | ||
1332 | pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) | ||
1333 | { | ||
1334 | unsigned char ints, pirq; | ||
1335 | int i = 0; | ||
1336 | |||
1337 | asleep = 0; | ||
1338 | if (drop_interrupts || len < 1) { | ||
1339 | adb_int_pending = 0; | ||
1340 | pmu_irq_stats[8]++; | ||
1341 | return; | ||
1342 | } | ||
1343 | |||
1344 | /* Get PMU interrupt mask */ | ||
1345 | ints = data[0]; | ||
1346 | |||
1347 | /* Record zero interrupts for stats */ | ||
1348 | if (ints == 0) | ||
1349 | pmu_irq_stats[9]++; | ||
1350 | |||
1351 | /* Hack to deal with ADB autopoll flag */ | ||
1352 | if (ints & PMU_INT_ADB) | ||
1353 | ints &= ~(PMU_INT_ADB_AUTO | PMU_INT_AUTO_SRQ_POLL); | ||
1354 | |||
1355 | next: | ||
1356 | |||
1357 | if (ints == 0) { | ||
1358 | if (i > pmu_irq_stats[10]) | ||
1359 | pmu_irq_stats[10] = i; | ||
1360 | return; | ||
1361 | } | ||
1362 | |||
1363 | for (pirq = 0; pirq < 8; pirq++) | ||
1364 | if (ints & (1 << pirq)) | ||
1365 | break; | ||
1366 | pmu_irq_stats[pirq]++; | ||
1367 | i++; | ||
1368 | ints &= ~(1 << pirq); | ||
1369 | |||
1370 | /* Note: for some reason, we get an interrupt with len=1, | ||
1371 | * data[0]==0 after each normal ADB interrupt, at least | ||
1372 | * on the Pismo. Still investigating... --BenH | ||
1373 | */ | ||
1374 | if ((1 << pirq) & PMU_INT_ADB) { | ||
1375 | if ((data[0] & PMU_INT_ADB_AUTO) == 0) { | ||
1376 | struct adb_request *req = req_awaiting_reply; | ||
1377 | if (req == 0) { | ||
1378 | printk(KERN_ERR "PMU: extra ADB reply\n"); | ||
1379 | return; | ||
1380 | } | ||
1381 | req_awaiting_reply = NULL; | ||
1382 | if (len <= 2) | ||
1383 | req->reply_len = 0; | ||
1384 | else { | ||
1385 | memcpy(req->reply, data + 1, len - 1); | ||
1386 | req->reply_len = len - 1; | ||
1387 | } | ||
1388 | pmu_done(req); | ||
1389 | } else { | ||
1390 | #if defined(CONFIG_XMON) && !defined(CONFIG_PPC64) | ||
1391 | if (len == 4 && data[1] == 0x2c) { | ||
1392 | extern int xmon_wants_key, xmon_adb_keycode; | ||
1393 | if (xmon_wants_key) { | ||
1394 | xmon_adb_keycode = data[2]; | ||
1395 | return; | ||
1396 | } | ||
1397 | } | ||
1398 | #endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */ | ||
1399 | #ifdef CONFIG_ADB | ||
1400 | /* | ||
1401 | * XXX On the [23]400 the PMU gives us an up | ||
1402 | * event for keycodes 0x74 or 0x75 when the PC | ||
1403 | * card eject buttons are released, so we | ||
1404 | * ignore those events. | ||
1405 | */ | ||
1406 | if (!(pmu_kind == PMU_OHARE_BASED && len == 4 | ||
1407 | && data[1] == 0x2c && data[3] == 0xff | ||
1408 | && (data[2] & ~1) == 0xf4)) | ||
1409 | adb_input(data+1, len-1, regs, 1); | ||
1410 | #endif /* CONFIG_ADB */ | ||
1411 | } | ||
1412 | } | ||
1413 | /* Sound/brightness button pressed */ | ||
1414 | else if ((1 << pirq) & PMU_INT_SNDBRT) { | ||
1415 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
1416 | if (len == 3) | ||
1417 | #ifdef CONFIG_INPUT_ADBHID | ||
1418 | if (!disable_kernel_backlight) | ||
1419 | #endif /* CONFIG_INPUT_ADBHID */ | ||
1420 | set_backlight_level(data[1] >> 4); | ||
1421 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
1422 | } | ||
1423 | /* Tick interrupt */ | ||
1424 | else if ((1 << pirq) & PMU_INT_TICK) { | ||
1425 | #ifdef CONFIG_PMAC_PBOOK | ||
1426 | /* Environement or tick interrupt, query batteries */ | ||
1427 | if (pmu_battery_count) { | ||
1428 | if ((--query_batt_timer) == 0) { | ||
1429 | query_battery_state(); | ||
1430 | query_batt_timer = BATTERY_POLLING_COUNT; | ||
1431 | } | ||
1432 | } | ||
1433 | } | ||
1434 | else if ((1 << pirq) & PMU_INT_ENVIRONMENT) { | ||
1435 | if (pmu_battery_count) | ||
1436 | query_battery_state(); | ||
1437 | pmu_pass_intr(data, len); | ||
1438 | } else { | ||
1439 | pmu_pass_intr(data, len); | ||
1440 | #endif /* CONFIG_PMAC_PBOOK */ | ||
1441 | } | ||
1442 | goto next; | ||
1443 | } | ||
1444 | |||
1445 | static struct adb_request* __pmac | ||
1446 | pmu_sr_intr(struct pt_regs *regs) | ||
1447 | { | ||
1448 | struct adb_request *req; | ||
1449 | int bite = 0; | ||
1450 | |||
1451 | if (via[B] & TREQ) { | ||
1452 | printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]); | ||
1453 | out_8(&via[IFR], SR_INT); | ||
1454 | return NULL; | ||
1455 | } | ||
1456 | /* The ack may not yet be low when we get the interrupt */ | ||
1457 | while ((in_8(&via[B]) & TACK) != 0) | ||
1458 | ; | ||
1459 | |||
1460 | /* if reading grab the byte, and reset the interrupt */ | ||
1461 | if (pmu_state == reading || pmu_state == reading_intr) | ||
1462 | bite = in_8(&via[SR]); | ||
1463 | |||
1464 | /* reset TREQ and wait for TACK to go high */ | ||
1465 | out_8(&via[B], in_8(&via[B]) | TREQ); | ||
1466 | wait_for_ack(); | ||
1467 | |||
1468 | switch (pmu_state) { | ||
1469 | case sending: | ||
1470 | req = current_req; | ||
1471 | if (data_len < 0) { | ||
1472 | data_len = req->nbytes - 1; | ||
1473 | send_byte(data_len); | ||
1474 | break; | ||
1475 | } | ||
1476 | if (data_index <= data_len) { | ||
1477 | send_byte(req->data[data_index++]); | ||
1478 | break; | ||
1479 | } | ||
1480 | req->sent = 1; | ||
1481 | data_len = pmu_data_len[req->data[0]][1]; | ||
1482 | if (data_len == 0) { | ||
1483 | pmu_state = idle; | ||
1484 | current_req = req->next; | ||
1485 | if (req->reply_expected) | ||
1486 | req_awaiting_reply = req; | ||
1487 | else | ||
1488 | return req; | ||
1489 | } else { | ||
1490 | pmu_state = reading; | ||
1491 | data_index = 0; | ||
1492 | reply_ptr = req->reply + req->reply_len; | ||
1493 | recv_byte(); | ||
1494 | } | ||
1495 | break; | ||
1496 | |||
1497 | case intack: | ||
1498 | data_index = 0; | ||
1499 | data_len = -1; | ||
1500 | pmu_state = reading_intr; | ||
1501 | reply_ptr = interrupt_data[int_data_last]; | ||
1502 | recv_byte(); | ||
1503 | if (gpio_irq >= 0 && !gpio_irq_enabled) { | ||
1504 | enable_irq(gpio_irq); | ||
1505 | gpio_irq_enabled = 1; | ||
1506 | } | ||
1507 | break; | ||
1508 | |||
1509 | case reading: | ||
1510 | case reading_intr: | ||
1511 | if (data_len == -1) { | ||
1512 | data_len = bite; | ||
1513 | if (bite > 32) | ||
1514 | printk(KERN_ERR "PMU: bad reply len %d\n", bite); | ||
1515 | } else if (data_index < 32) { | ||
1516 | reply_ptr[data_index++] = bite; | ||
1517 | } | ||
1518 | if (data_index < data_len) { | ||
1519 | recv_byte(); | ||
1520 | break; | ||
1521 | } | ||
1522 | |||
1523 | if (pmu_state == reading_intr) { | ||
1524 | pmu_state = idle; | ||
1525 | int_data_state[int_data_last] = int_data_ready; | ||
1526 | interrupt_data_len[int_data_last] = data_len; | ||
1527 | } else { | ||
1528 | req = current_req; | ||
1529 | /* | ||
1530 | * For PMU sleep and freq change requests, we lock the | ||
1531 | * PMU until it's explicitely unlocked. This avoids any | ||
1532 | * spurrious event polling getting in | ||
1533 | */ | ||
1534 | current_req = req->next; | ||
1535 | req->reply_len += data_index; | ||
1536 | if (req->data[0] == PMU_SLEEP || req->data[0] == PMU_CPU_SPEED) | ||
1537 | pmu_state = locked; | ||
1538 | else | ||
1539 | pmu_state = idle; | ||
1540 | return req; | ||
1541 | } | ||
1542 | break; | ||
1543 | |||
1544 | default: | ||
1545 | printk(KERN_ERR "via_pmu_interrupt: unknown state %d?\n", | ||
1546 | pmu_state); | ||
1547 | } | ||
1548 | return NULL; | ||
1549 | } | ||
1550 | |||
1551 | static irqreturn_t __pmac | ||
1552 | via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs) | ||
1553 | { | ||
1554 | unsigned long flags; | ||
1555 | int intr; | ||
1556 | int nloop = 0; | ||
1557 | int int_data = -1; | ||
1558 | struct adb_request *req = NULL; | ||
1559 | int handled = 0; | ||
1560 | |||
1561 | /* This is a bit brutal, we can probably do better */ | ||
1562 | spin_lock_irqsave(&pmu_lock, flags); | ||
1563 | ++disable_poll; | ||
1564 | |||
1565 | for (;;) { | ||
1566 | intr = in_8(&via[IFR]) & (SR_INT | CB1_INT); | ||
1567 | if (intr == 0) | ||
1568 | break; | ||
1569 | handled = 1; | ||
1570 | if (++nloop > 1000) { | ||
1571 | printk(KERN_DEBUG "PMU: stuck in intr loop, " | ||
1572 | "intr=%x, ier=%x pmu_state=%d\n", | ||
1573 | intr, in_8(&via[IER]), pmu_state); | ||
1574 | break; | ||
1575 | } | ||
1576 | out_8(&via[IFR], intr); | ||
1577 | if (intr & CB1_INT) { | ||
1578 | adb_int_pending = 1; | ||
1579 | pmu_irq_stats[0]++; | ||
1580 | } | ||
1581 | if (intr & SR_INT) { | ||
1582 | req = pmu_sr_intr(regs); | ||
1583 | if (req) | ||
1584 | break; | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | recheck: | ||
1589 | if (pmu_state == idle) { | ||
1590 | if (adb_int_pending) { | ||
1591 | if (int_data_state[0] == int_data_empty) | ||
1592 | int_data_last = 0; | ||
1593 | else if (int_data_state[1] == int_data_empty) | ||
1594 | int_data_last = 1; | ||
1595 | else | ||
1596 | goto no_free_slot; | ||
1597 | pmu_state = intack; | ||
1598 | int_data_state[int_data_last] = int_data_fill; | ||
1599 | /* Sounds safer to make sure ACK is high before writing. | ||
1600 | * This helped kill a problem with ADB and some iBooks | ||
1601 | */ | ||
1602 | wait_for_ack(); | ||
1603 | send_byte(PMU_INT_ACK); | ||
1604 | adb_int_pending = 0; | ||
1605 | } else if (current_req) | ||
1606 | pmu_start(); | ||
1607 | } | ||
1608 | no_free_slot: | ||
1609 | /* Mark the oldest buffer for flushing */ | ||
1610 | if (int_data_state[!int_data_last] == int_data_ready) { | ||
1611 | int_data_state[!int_data_last] = int_data_flush; | ||
1612 | int_data = !int_data_last; | ||
1613 | } else if (int_data_state[int_data_last] == int_data_ready) { | ||
1614 | int_data_state[int_data_last] = int_data_flush; | ||
1615 | int_data = int_data_last; | ||
1616 | } | ||
1617 | --disable_poll; | ||
1618 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1619 | |||
1620 | /* Deal with completed PMU requests outside of the lock */ | ||
1621 | if (req) { | ||
1622 | pmu_done(req); | ||
1623 | req = NULL; | ||
1624 | } | ||
1625 | |||
1626 | /* Deal with interrupt datas outside of the lock */ | ||
1627 | if (int_data >= 0) { | ||
1628 | pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data], regs); | ||
1629 | spin_lock_irqsave(&pmu_lock, flags); | ||
1630 | ++disable_poll; | ||
1631 | int_data_state[int_data] = int_data_empty; | ||
1632 | int_data = -1; | ||
1633 | goto recheck; | ||
1634 | } | ||
1635 | |||
1636 | return IRQ_RETVAL(handled); | ||
1637 | } | ||
1638 | |||
1639 | void __pmac | ||
1640 | pmu_unlock(void) | ||
1641 | { | ||
1642 | unsigned long flags; | ||
1643 | |||
1644 | spin_lock_irqsave(&pmu_lock, flags); | ||
1645 | if (pmu_state == locked) | ||
1646 | pmu_state = idle; | ||
1647 | adb_int_pending = 1; | ||
1648 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1649 | } | ||
1650 | |||
1651 | |||
1652 | static irqreturn_t __pmac | ||
1653 | gpio1_interrupt(int irq, void *arg, struct pt_regs *regs) | ||
1654 | { | ||
1655 | unsigned long flags; | ||
1656 | |||
1657 | if ((in_8(gpio_reg + 0x9) & 0x02) == 0) { | ||
1658 | spin_lock_irqsave(&pmu_lock, flags); | ||
1659 | if (gpio_irq_enabled > 0) { | ||
1660 | disable_irq_nosync(gpio_irq); | ||
1661 | gpio_irq_enabled = 0; | ||
1662 | } | ||
1663 | pmu_irq_stats[1]++; | ||
1664 | adb_int_pending = 1; | ||
1665 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1666 | via_pmu_interrupt(0, NULL, NULL); | ||
1667 | return IRQ_HANDLED; | ||
1668 | } | ||
1669 | return IRQ_NONE; | ||
1670 | } | ||
1671 | |||
1672 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
1673 | static int backlight_to_bright[] __pmacdata = { | ||
1674 | 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, | ||
1675 | 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e | ||
1676 | }; | ||
1677 | |||
1678 | static int __openfirmware | ||
1679 | pmu_set_backlight_enable(int on, int level, void* data) | ||
1680 | { | ||
1681 | struct adb_request req; | ||
1682 | |||
1683 | if (vias == NULL) | ||
1684 | return -ENODEV; | ||
1685 | |||
1686 | if (on) { | ||
1687 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, | ||
1688 | backlight_to_bright[level]); | ||
1689 | pmu_wait_complete(&req); | ||
1690 | } | ||
1691 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
1692 | PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); | ||
1693 | pmu_wait_complete(&req); | ||
1694 | |||
1695 | return 0; | ||
1696 | } | ||
1697 | |||
1698 | static void __openfirmware | ||
1699 | pmu_bright_complete(struct adb_request *req) | ||
1700 | { | ||
1701 | if (req == &bright_req_1) | ||
1702 | clear_bit(1, &async_req_locks); | ||
1703 | if (req == &bright_req_2) | ||
1704 | clear_bit(2, &async_req_locks); | ||
1705 | } | ||
1706 | |||
1707 | static int __openfirmware | ||
1708 | pmu_set_backlight_level(int level, void* data) | ||
1709 | { | ||
1710 | if (vias == NULL) | ||
1711 | return -ENODEV; | ||
1712 | |||
1713 | if (test_and_set_bit(1, &async_req_locks)) | ||
1714 | return -EAGAIN; | ||
1715 | pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT, | ||
1716 | backlight_to_bright[level]); | ||
1717 | if (test_and_set_bit(2, &async_req_locks)) | ||
1718 | return -EAGAIN; | ||
1719 | pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL, | ||
1720 | PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ? | ||
1721 | PMU_POW_ON : PMU_POW_OFF)); | ||
1722 | |||
1723 | return 0; | ||
1724 | } | ||
1725 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
1726 | |||
1727 | void __pmac | ||
1728 | pmu_enable_irled(int on) | ||
1729 | { | ||
1730 | struct adb_request req; | ||
1731 | |||
1732 | if (vias == NULL) | ||
1733 | return ; | ||
1734 | if (pmu_kind == PMU_KEYLARGO_BASED) | ||
1735 | return ; | ||
1736 | |||
1737 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED | | ||
1738 | (on ? PMU_POW_ON : PMU_POW_OFF)); | ||
1739 | pmu_wait_complete(&req); | ||
1740 | } | ||
1741 | |||
1742 | void __pmac | ||
1743 | pmu_restart(void) | ||
1744 | { | ||
1745 | struct adb_request req; | ||
1746 | |||
1747 | if (via == NULL) | ||
1748 | return; | ||
1749 | |||
1750 | local_irq_disable(); | ||
1751 | |||
1752 | drop_interrupts = 1; | ||
1753 | |||
1754 | if (pmu_kind != PMU_KEYLARGO_BASED) { | ||
1755 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | | ||
1756 | PMU_INT_TICK ); | ||
1757 | while(!req.complete) | ||
1758 | pmu_poll(); | ||
1759 | } | ||
1760 | |||
1761 | pmu_request(&req, NULL, 1, PMU_RESET); | ||
1762 | pmu_wait_complete(&req); | ||
1763 | for (;;) | ||
1764 | ; | ||
1765 | } | ||
1766 | |||
1767 | void __pmac | ||
1768 | pmu_shutdown(void) | ||
1769 | { | ||
1770 | struct adb_request req; | ||
1771 | |||
1772 | if (via == NULL) | ||
1773 | return; | ||
1774 | |||
1775 | local_irq_disable(); | ||
1776 | |||
1777 | drop_interrupts = 1; | ||
1778 | |||
1779 | if (pmu_kind != PMU_KEYLARGO_BASED) { | ||
1780 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | | ||
1781 | PMU_INT_TICK ); | ||
1782 | pmu_wait_complete(&req); | ||
1783 | } else { | ||
1784 | /* Disable server mode on shutdown or we'll just | ||
1785 | * wake up again | ||
1786 | */ | ||
1787 | pmu_set_server_mode(0); | ||
1788 | } | ||
1789 | |||
1790 | pmu_request(&req, NULL, 5, PMU_SHUTDOWN, | ||
1791 | 'M', 'A', 'T', 'T'); | ||
1792 | pmu_wait_complete(&req); | ||
1793 | for (;;) | ||
1794 | ; | ||
1795 | } | ||
1796 | |||
1797 | int | ||
1798 | pmu_present(void) | ||
1799 | { | ||
1800 | return via != 0; | ||
1801 | } | ||
1802 | |||
1803 | struct pmu_i2c_hdr { | ||
1804 | u8 bus; | ||
1805 | u8 mode; | ||
1806 | u8 bus2; | ||
1807 | u8 address; | ||
1808 | u8 sub_addr; | ||
1809 | u8 comb_addr; | ||
1810 | u8 count; | ||
1811 | }; | ||
1812 | |||
1813 | int | ||
1814 | pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len) | ||
1815 | { | ||
1816 | struct adb_request req; | ||
1817 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1818 | int retry; | ||
1819 | int rc; | ||
1820 | |||
1821 | for (retry=0; retry<16; retry++) { | ||
1822 | memset(&req, 0, sizeof(req)); | ||
1823 | |||
1824 | hdr->bus = bus; | ||
1825 | hdr->address = addr & 0xfe; | ||
1826 | hdr->mode = PMU_I2C_MODE_COMBINED; | ||
1827 | hdr->bus2 = 0; | ||
1828 | hdr->sub_addr = subaddr; | ||
1829 | hdr->comb_addr = addr | 1; | ||
1830 | hdr->count = len; | ||
1831 | |||
1832 | req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
1833 | req.reply_expected = 0; | ||
1834 | req.reply_len = 0; | ||
1835 | req.data[0] = PMU_I2C_CMD; | ||
1836 | req.reply[0] = 0xff; | ||
1837 | rc = pmu_queue_request(&req); | ||
1838 | if (rc) | ||
1839 | return rc; | ||
1840 | while(!req.complete) | ||
1841 | pmu_poll(); | ||
1842 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1843 | break; | ||
1844 | mdelay(15); | ||
1845 | } | ||
1846 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1847 | return -1; | ||
1848 | |||
1849 | for (retry=0; retry<16; retry++) { | ||
1850 | memset(&req, 0, sizeof(req)); | ||
1851 | |||
1852 | mdelay(15); | ||
1853 | |||
1854 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1855 | req.reply[0] = 0xff; | ||
1856 | |||
1857 | req.nbytes = 2; | ||
1858 | req.reply_expected = 0; | ||
1859 | req.reply_len = 0; | ||
1860 | req.data[0] = PMU_I2C_CMD; | ||
1861 | rc = pmu_queue_request(&req); | ||
1862 | if (rc) | ||
1863 | return rc; | ||
1864 | while(!req.complete) | ||
1865 | pmu_poll(); | ||
1866 | if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { | ||
1867 | memcpy(data, &req.reply[1], req.reply_len - 1); | ||
1868 | return req.reply_len - 1; | ||
1869 | } | ||
1870 | } | ||
1871 | return -1; | ||
1872 | } | ||
1873 | |||
1874 | int | ||
1875 | pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len) | ||
1876 | { | ||
1877 | struct adb_request req; | ||
1878 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1879 | int retry; | ||
1880 | int rc; | ||
1881 | |||
1882 | for (retry=0; retry<16; retry++) { | ||
1883 | memset(&req, 0, sizeof(req)); | ||
1884 | |||
1885 | hdr->bus = bus; | ||
1886 | hdr->address = addr & 0xfe; | ||
1887 | hdr->mode = PMU_I2C_MODE_STDSUB; | ||
1888 | hdr->bus2 = 0; | ||
1889 | hdr->sub_addr = subaddr; | ||
1890 | hdr->comb_addr = addr & 0xfe; | ||
1891 | hdr->count = len; | ||
1892 | |||
1893 | req.data[0] = PMU_I2C_CMD; | ||
1894 | memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); | ||
1895 | req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; | ||
1896 | req.reply_expected = 0; | ||
1897 | req.reply_len = 0; | ||
1898 | req.reply[0] = 0xff; | ||
1899 | rc = pmu_queue_request(&req); | ||
1900 | if (rc) | ||
1901 | return rc; | ||
1902 | while(!req.complete) | ||
1903 | pmu_poll(); | ||
1904 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1905 | break; | ||
1906 | mdelay(15); | ||
1907 | } | ||
1908 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1909 | return -1; | ||
1910 | |||
1911 | for (retry=0; retry<16; retry++) { | ||
1912 | memset(&req, 0, sizeof(req)); | ||
1913 | |||
1914 | mdelay(15); | ||
1915 | |||
1916 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1917 | req.reply[0] = 0xff; | ||
1918 | |||
1919 | req.nbytes = 2; | ||
1920 | req.reply_expected = 0; | ||
1921 | req.reply_len = 0; | ||
1922 | req.data[0] = PMU_I2C_CMD; | ||
1923 | rc = pmu_queue_request(&req); | ||
1924 | if (rc) | ||
1925 | return rc; | ||
1926 | while(!req.complete) | ||
1927 | pmu_poll(); | ||
1928 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1929 | return len; | ||
1930 | } | ||
1931 | return -1; | ||
1932 | } | ||
1933 | |||
1934 | int | ||
1935 | pmu_i2c_simple_read(int bus, int addr, u8* data, int len) | ||
1936 | { | ||
1937 | struct adb_request req; | ||
1938 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1939 | int retry; | ||
1940 | int rc; | ||
1941 | |||
1942 | for (retry=0; retry<16; retry++) { | ||
1943 | memset(&req, 0, sizeof(req)); | ||
1944 | |||
1945 | hdr->bus = bus; | ||
1946 | hdr->address = addr | 1; | ||
1947 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
1948 | hdr->bus2 = 0; | ||
1949 | hdr->sub_addr = 0; | ||
1950 | hdr->comb_addr = 0; | ||
1951 | hdr->count = len; | ||
1952 | |||
1953 | req.data[0] = PMU_I2C_CMD; | ||
1954 | req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
1955 | req.reply_expected = 0; | ||
1956 | req.reply_len = 0; | ||
1957 | req.reply[0] = 0xff; | ||
1958 | rc = pmu_queue_request(&req); | ||
1959 | if (rc) | ||
1960 | return rc; | ||
1961 | while(!req.complete) | ||
1962 | pmu_poll(); | ||
1963 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1964 | break; | ||
1965 | mdelay(15); | ||
1966 | } | ||
1967 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1968 | return -1; | ||
1969 | |||
1970 | for (retry=0; retry<16; retry++) { | ||
1971 | memset(&req, 0, sizeof(req)); | ||
1972 | |||
1973 | mdelay(15); | ||
1974 | |||
1975 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1976 | req.reply[0] = 0xff; | ||
1977 | |||
1978 | req.nbytes = 2; | ||
1979 | req.reply_expected = 0; | ||
1980 | req.reply_len = 0; | ||
1981 | req.data[0] = PMU_I2C_CMD; | ||
1982 | rc = pmu_queue_request(&req); | ||
1983 | if (rc) | ||
1984 | return rc; | ||
1985 | while(!req.complete) | ||
1986 | pmu_poll(); | ||
1987 | if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { | ||
1988 | memcpy(data, &req.reply[1], req.reply_len - 1); | ||
1989 | return req.reply_len - 1; | ||
1990 | } | ||
1991 | } | ||
1992 | return -1; | ||
1993 | } | ||
1994 | |||
1995 | int | ||
1996 | pmu_i2c_simple_write(int bus, int addr, u8* data, int len) | ||
1997 | { | ||
1998 | struct adb_request req; | ||
1999 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
2000 | int retry; | ||
2001 | int rc; | ||
2002 | |||
2003 | for (retry=0; retry<16; retry++) { | ||
2004 | memset(&req, 0, sizeof(req)); | ||
2005 | |||
2006 | hdr->bus = bus; | ||
2007 | hdr->address = addr & 0xfe; | ||
2008 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
2009 | hdr->bus2 = 0; | ||
2010 | hdr->sub_addr = 0; | ||
2011 | hdr->comb_addr = 0; | ||
2012 | hdr->count = len; | ||
2013 | |||
2014 | req.data[0] = PMU_I2C_CMD; | ||
2015 | memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); | ||
2016 | req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; | ||
2017 | req.reply_expected = 0; | ||
2018 | req.reply_len = 0; | ||
2019 | req.reply[0] = 0xff; | ||
2020 | rc = pmu_queue_request(&req); | ||
2021 | if (rc) | ||
2022 | return rc; | ||
2023 | while(!req.complete) | ||
2024 | pmu_poll(); | ||
2025 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
2026 | break; | ||
2027 | mdelay(15); | ||
2028 | } | ||
2029 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
2030 | return -1; | ||
2031 | |||
2032 | for (retry=0; retry<16; retry++) { | ||
2033 | memset(&req, 0, sizeof(req)); | ||
2034 | |||
2035 | mdelay(15); | ||
2036 | |||
2037 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
2038 | req.reply[0] = 0xff; | ||
2039 | |||
2040 | req.nbytes = 2; | ||
2041 | req.reply_expected = 0; | ||
2042 | req.reply_len = 0; | ||
2043 | req.data[0] = PMU_I2C_CMD; | ||
2044 | rc = pmu_queue_request(&req); | ||
2045 | if (rc) | ||
2046 | return rc; | ||
2047 | while(!req.complete) | ||
2048 | pmu_poll(); | ||
2049 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
2050 | return len; | ||
2051 | } | ||
2052 | return -1; | ||
2053 | } | ||
2054 | |||
2055 | #ifdef CONFIG_PMAC_PBOOK | ||
2056 | |||
2057 | static LIST_HEAD(sleep_notifiers); | ||
2058 | |||
2059 | int | ||
2060 | pmu_register_sleep_notifier(struct pmu_sleep_notifier *n) | ||
2061 | { | ||
2062 | struct list_head *list; | ||
2063 | struct pmu_sleep_notifier *notifier; | ||
2064 | |||
2065 | for (list = sleep_notifiers.next; list != &sleep_notifiers; | ||
2066 | list = list->next) { | ||
2067 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
2068 | if (n->priority > notifier->priority) | ||
2069 | break; | ||
2070 | } | ||
2071 | __list_add(&n->list, list->prev, list); | ||
2072 | return 0; | ||
2073 | } | ||
2074 | |||
2075 | int | ||
2076 | pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n) | ||
2077 | { | ||
2078 | if (n->list.next == 0) | ||
2079 | return -ENOENT; | ||
2080 | list_del(&n->list); | ||
2081 | n->list.next = NULL; | ||
2082 | return 0; | ||
2083 | } | ||
2084 | |||
2085 | /* Sleep is broadcast last-to-first */ | ||
2086 | static int __pmac | ||
2087 | broadcast_sleep(int when, int fallback) | ||
2088 | { | ||
2089 | int ret = PBOOK_SLEEP_OK; | ||
2090 | struct list_head *list; | ||
2091 | struct pmu_sleep_notifier *notifier; | ||
2092 | |||
2093 | for (list = sleep_notifiers.prev; list != &sleep_notifiers; | ||
2094 | list = list->prev) { | ||
2095 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
2096 | ret = notifier->notifier_call(notifier, when); | ||
2097 | if (ret != PBOOK_SLEEP_OK) { | ||
2098 | printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n", | ||
2099 | when, notifier, notifier->notifier_call); | ||
2100 | for (; list != &sleep_notifiers; list = list->next) { | ||
2101 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
2102 | notifier->notifier_call(notifier, fallback); | ||
2103 | } | ||
2104 | return ret; | ||
2105 | } | ||
2106 | } | ||
2107 | return ret; | ||
2108 | } | ||
2109 | |||
2110 | /* Wake is broadcast first-to-last */ | ||
2111 | static int __pmac | ||
2112 | broadcast_wake(void) | ||
2113 | { | ||
2114 | int ret = PBOOK_SLEEP_OK; | ||
2115 | struct list_head *list; | ||
2116 | struct pmu_sleep_notifier *notifier; | ||
2117 | |||
2118 | for (list = sleep_notifiers.next; list != &sleep_notifiers; | ||
2119 | list = list->next) { | ||
2120 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
2121 | notifier->notifier_call(notifier, PBOOK_WAKE); | ||
2122 | } | ||
2123 | return ret; | ||
2124 | } | ||
2125 | |||
2126 | /* | ||
2127 | * This struct is used to store config register values for | ||
2128 | * PCI devices which may get powered off when we sleep. | ||
2129 | */ | ||
2130 | static struct pci_save { | ||
2131 | #ifndef HACKED_PCI_SAVE | ||
2132 | u16 command; | ||
2133 | u16 cache_lat; | ||
2134 | u16 intr; | ||
2135 | u32 rom_address; | ||
2136 | #else | ||
2137 | u32 config[16]; | ||
2138 | #endif | ||
2139 | } *pbook_pci_saves; | ||
2140 | static int pbook_npci_saves; | ||
2141 | |||
2142 | static void __pmac | ||
2143 | pbook_alloc_pci_save(void) | ||
2144 | { | ||
2145 | int npci; | ||
2146 | struct pci_dev *pd = NULL; | ||
2147 | |||
2148 | npci = 0; | ||
2149 | while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
2150 | ++npci; | ||
2151 | } | ||
2152 | if (npci == 0) | ||
2153 | return; | ||
2154 | pbook_pci_saves = (struct pci_save *) | ||
2155 | kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL); | ||
2156 | pbook_npci_saves = npci; | ||
2157 | } | ||
2158 | |||
2159 | static void __pmac | ||
2160 | pbook_free_pci_save(void) | ||
2161 | { | ||
2162 | if (pbook_pci_saves == NULL) | ||
2163 | return; | ||
2164 | kfree(pbook_pci_saves); | ||
2165 | pbook_pci_saves = NULL; | ||
2166 | pbook_npci_saves = 0; | ||
2167 | } | ||
2168 | |||
2169 | static void __pmac | ||
2170 | pbook_pci_save(void) | ||
2171 | { | ||
2172 | struct pci_save *ps = pbook_pci_saves; | ||
2173 | struct pci_dev *pd = NULL; | ||
2174 | int npci = pbook_npci_saves; | ||
2175 | |||
2176 | if (ps == NULL) | ||
2177 | return; | ||
2178 | |||
2179 | while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
2180 | if (npci-- == 0) | ||
2181 | return; | ||
2182 | #ifndef HACKED_PCI_SAVE | ||
2183 | pci_read_config_word(pd, PCI_COMMAND, &ps->command); | ||
2184 | pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat); | ||
2185 | pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr); | ||
2186 | pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address); | ||
2187 | #else | ||
2188 | int i; | ||
2189 | for (i=1;i<16;i++) | ||
2190 | pci_read_config_dword(pd, i<<4, &ps->config[i]); | ||
2191 | #endif | ||
2192 | ++ps; | ||
2193 | } | ||
2194 | } | ||
2195 | |||
2196 | /* For this to work, we must take care of a few things: If gmac was enabled | ||
2197 | * during boot, it will be in the pci dev list. If it's disabled at this point | ||
2198 | * (and it will probably be), then you can't access it's config space. | ||
2199 | */ | ||
2200 | static void __pmac | ||
2201 | pbook_pci_restore(void) | ||
2202 | { | ||
2203 | u16 cmd; | ||
2204 | struct pci_save *ps = pbook_pci_saves - 1; | ||
2205 | struct pci_dev *pd = NULL; | ||
2206 | int npci = pbook_npci_saves; | ||
2207 | int j; | ||
2208 | |||
2209 | while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
2210 | #ifdef HACKED_PCI_SAVE | ||
2211 | int i; | ||
2212 | if (npci-- == 0) | ||
2213 | return; | ||
2214 | ps++; | ||
2215 | for (i=2;i<16;i++) | ||
2216 | pci_write_config_dword(pd, i<<4, ps->config[i]); | ||
2217 | pci_write_config_dword(pd, 4, ps->config[1]); | ||
2218 | #else | ||
2219 | if (npci-- == 0) | ||
2220 | return; | ||
2221 | ps++; | ||
2222 | if (ps->command == 0) | ||
2223 | continue; | ||
2224 | pci_read_config_word(pd, PCI_COMMAND, &cmd); | ||
2225 | if ((ps->command & ~cmd) == 0) | ||
2226 | continue; | ||
2227 | switch (pd->hdr_type) { | ||
2228 | case PCI_HEADER_TYPE_NORMAL: | ||
2229 | for (j = 0; j < 6; ++j) | ||
2230 | pci_write_config_dword(pd, | ||
2231 | PCI_BASE_ADDRESS_0 + j*4, | ||
2232 | pd->resource[j].start); | ||
2233 | pci_write_config_dword(pd, PCI_ROM_ADDRESS, | ||
2234 | ps->rom_address); | ||
2235 | pci_write_config_word(pd, PCI_CACHE_LINE_SIZE, | ||
2236 | ps->cache_lat); | ||
2237 | pci_write_config_word(pd, PCI_INTERRUPT_LINE, | ||
2238 | ps->intr); | ||
2239 | pci_write_config_word(pd, PCI_COMMAND, ps->command); | ||
2240 | break; | ||
2241 | } | ||
2242 | #endif | ||
2243 | } | ||
2244 | } | ||
2245 | |||
2246 | #ifdef DEBUG_SLEEP | ||
2247 | /* N.B. This doesn't work on the 3400 */ | ||
2248 | void __pmac | ||
2249 | pmu_blink(int n) | ||
2250 | { | ||
2251 | struct adb_request req; | ||
2252 | |||
2253 | memset(&req, 0, sizeof(req)); | ||
2254 | |||
2255 | for (; n > 0; --n) { | ||
2256 | req.nbytes = 4; | ||
2257 | req.done = NULL; | ||
2258 | req.data[0] = 0xee; | ||
2259 | req.data[1] = 4; | ||
2260 | req.data[2] = 0; | ||
2261 | req.data[3] = 1; | ||
2262 | req.reply[0] = ADB_RET_OK; | ||
2263 | req.reply_len = 1; | ||
2264 | req.reply_expected = 0; | ||
2265 | pmu_polled_request(&req); | ||
2266 | mdelay(50); | ||
2267 | req.nbytes = 4; | ||
2268 | req.done = NULL; | ||
2269 | req.data[0] = 0xee; | ||
2270 | req.data[1] = 4; | ||
2271 | req.data[2] = 0; | ||
2272 | req.data[3] = 0; | ||
2273 | req.reply[0] = ADB_RET_OK; | ||
2274 | req.reply_len = 1; | ||
2275 | req.reply_expected = 0; | ||
2276 | pmu_polled_request(&req); | ||
2277 | mdelay(50); | ||
2278 | } | ||
2279 | mdelay(50); | ||
2280 | } | ||
2281 | #endif | ||
2282 | |||
2283 | /* | ||
2284 | * Put the powerbook to sleep. | ||
2285 | */ | ||
2286 | |||
2287 | static u32 save_via[8] __pmacdata; | ||
2288 | |||
2289 | static void __pmac | ||
2290 | save_via_state(void) | ||
2291 | { | ||
2292 | save_via[0] = in_8(&via[ANH]); | ||
2293 | save_via[1] = in_8(&via[DIRA]); | ||
2294 | save_via[2] = in_8(&via[B]); | ||
2295 | save_via[3] = in_8(&via[DIRB]); | ||
2296 | save_via[4] = in_8(&via[PCR]); | ||
2297 | save_via[5] = in_8(&via[ACR]); | ||
2298 | save_via[6] = in_8(&via[T1CL]); | ||
2299 | save_via[7] = in_8(&via[T1CH]); | ||
2300 | } | ||
2301 | static void __pmac | ||
2302 | restore_via_state(void) | ||
2303 | { | ||
2304 | out_8(&via[ANH], save_via[0]); | ||
2305 | out_8(&via[DIRA], save_via[1]); | ||
2306 | out_8(&via[B], save_via[2]); | ||
2307 | out_8(&via[DIRB], save_via[3]); | ||
2308 | out_8(&via[PCR], save_via[4]); | ||
2309 | out_8(&via[ACR], save_via[5]); | ||
2310 | out_8(&via[T1CL], save_via[6]); | ||
2311 | out_8(&via[T1CH], save_via[7]); | ||
2312 | out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ | ||
2313 | out_8(&via[IFR], 0x7f); /* clear IFR */ | ||
2314 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); | ||
2315 | } | ||
2316 | |||
2317 | static int __pmac | ||
2318 | pmac_suspend_devices(void) | ||
2319 | { | ||
2320 | int ret; | ||
2321 | |||
2322 | pm_prepare_console(); | ||
2323 | |||
2324 | /* Notify old-style device drivers & userland */ | ||
2325 | ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); | ||
2326 | if (ret != PBOOK_SLEEP_OK) { | ||
2327 | printk(KERN_ERR "Sleep rejected by drivers\n"); | ||
2328 | return -EBUSY; | ||
2329 | } | ||
2330 | |||
2331 | /* Sync the disks. */ | ||
2332 | /* XXX It would be nice to have some way to ensure that | ||
2333 | * nobody is dirtying any new buffers while we wait. That | ||
2334 | * could be achieved using the refrigerator for processes | ||
2335 | * that swsusp uses | ||
2336 | */ | ||
2337 | sys_sync(); | ||
2338 | |||
2339 | /* Sleep can fail now. May not be very robust but useful for debugging */ | ||
2340 | ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE); | ||
2341 | if (ret != PBOOK_SLEEP_OK) { | ||
2342 | printk(KERN_ERR "Driver sleep failed\n"); | ||
2343 | return -EBUSY; | ||
2344 | } | ||
2345 | |||
2346 | /* Send suspend call to devices, hold the device core's dpm_sem */ | ||
2347 | ret = device_suspend(PMSG_SUSPEND); | ||
2348 | if (ret) { | ||
2349 | broadcast_wake(); | ||
2350 | printk(KERN_ERR "Driver sleep failed\n"); | ||
2351 | return -EBUSY; | ||
2352 | } | ||
2353 | |||
2354 | preempt_disable(); | ||
2355 | |||
2356 | /* Make sure the decrementer won't interrupt us */ | ||
2357 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
2358 | /* Make sure any pending DEC interrupt occurring while we did | ||
2359 | * the above didn't re-enable the DEC */ | ||
2360 | mb(); | ||
2361 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
2362 | |||
2363 | /* We can now disable MSR_EE. This code of course works properly only | ||
2364 | * on UP machines... For SMP, if we ever implement sleep, we'll have to | ||
2365 | * stop the "other" CPUs way before we do all that stuff. | ||
2366 | */ | ||
2367 | local_irq_disable(); | ||
2368 | |||
2369 | /* Broadcast power down irq | ||
2370 | * This isn't that useful in most cases (only directly wired devices can | ||
2371 | * use this but still... This will take care of sysdev's as well, so | ||
2372 | * we exit from here with local irqs disabled and PIC off. | ||
2373 | */ | ||
2374 | ret = device_power_down(PM_SUSPEND_MEM); | ||
2375 | if (ret) { | ||
2376 | wakeup_decrementer(); | ||
2377 | local_irq_enable(); | ||
2378 | preempt_enable(); | ||
2379 | device_resume(); | ||
2380 | broadcast_wake(); | ||
2381 | printk(KERN_ERR "Driver powerdown failed\n"); | ||
2382 | return -EBUSY; | ||
2383 | } | ||
2384 | |||
2385 | /* Wait for completion of async backlight requests */ | ||
2386 | while (!bright_req_1.complete || !bright_req_2.complete || | ||
2387 | !batt_req.complete) | ||
2388 | pmu_poll(); | ||
2389 | |||
2390 | /* Giveup the lazy FPU & vec so we don't have to back them | ||
2391 | * up from the low level code | ||
2392 | */ | ||
2393 | enable_kernel_fp(); | ||
2394 | |||
2395 | #ifdef CONFIG_ALTIVEC | ||
2396 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
2397 | enable_kernel_altivec(); | ||
2398 | #endif /* CONFIG_ALTIVEC */ | ||
2399 | |||
2400 | return 0; | ||
2401 | } | ||
2402 | |||
2403 | static int __pmac | ||
2404 | pmac_wakeup_devices(void) | ||
2405 | { | ||
2406 | mdelay(100); | ||
2407 | |||
2408 | /* Power back up system devices (including the PIC) */ | ||
2409 | device_power_up(); | ||
2410 | |||
2411 | /* Force a poll of ADB interrupts */ | ||
2412 | adb_int_pending = 1; | ||
2413 | via_pmu_interrupt(0, NULL, NULL); | ||
2414 | |||
2415 | /* Restart jiffies & scheduling */ | ||
2416 | wakeup_decrementer(); | ||
2417 | |||
2418 | /* Re-enable local CPU interrupts */ | ||
2419 | local_irq_enable(); | ||
2420 | |||
2421 | mdelay(100); | ||
2422 | |||
2423 | preempt_enable(); | ||
2424 | |||
2425 | /* Resume devices */ | ||
2426 | device_resume(); | ||
2427 | |||
2428 | /* Notify old style drivers */ | ||
2429 | broadcast_wake(); | ||
2430 | |||
2431 | pm_restore_console(); | ||
2432 | |||
2433 | return 0; | ||
2434 | } | ||
2435 | |||
2436 | #define GRACKLE_PM (1<<7) | ||
2437 | #define GRACKLE_DOZE (1<<5) | ||
2438 | #define GRACKLE_NAP (1<<4) | ||
2439 | #define GRACKLE_SLEEP (1<<3) | ||
2440 | |||
2441 | int __pmac | ||
2442 | powerbook_sleep_grackle(void) | ||
2443 | { | ||
2444 | unsigned long save_l2cr; | ||
2445 | unsigned short pmcr1; | ||
2446 | struct adb_request req; | ||
2447 | int ret; | ||
2448 | struct pci_dev *grackle; | ||
2449 | |||
2450 | grackle = pci_find_slot(0, 0); | ||
2451 | if (!grackle) | ||
2452 | return -ENODEV; | ||
2453 | |||
2454 | ret = pmac_suspend_devices(); | ||
2455 | if (ret) { | ||
2456 | printk(KERN_ERR "Sleep rejected by devices\n"); | ||
2457 | return ret; | ||
2458 | } | ||
2459 | |||
2460 | /* Turn off various things. Darwin does some retry tests here... */ | ||
2461 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE); | ||
2462 | pmu_wait_complete(&req); | ||
2463 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
2464 | PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY); | ||
2465 | pmu_wait_complete(&req); | ||
2466 | |||
2467 | /* For 750, save backside cache setting and disable it */ | ||
2468 | save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ | ||
2469 | |||
2470 | if (!__fake_sleep) { | ||
2471 | /* Ask the PMU to put us to sleep */ | ||
2472 | pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); | ||
2473 | pmu_wait_complete(&req); | ||
2474 | } | ||
2475 | |||
2476 | /* The VIA is supposed not to be restored correctly*/ | ||
2477 | save_via_state(); | ||
2478 | /* We shut down some HW */ | ||
2479 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1); | ||
2480 | |||
2481 | pci_read_config_word(grackle, 0x70, &pmcr1); | ||
2482 | /* Apparently, MacOS uses NAP mode for Grackle ??? */ | ||
2483 | pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); | ||
2484 | pmcr1 |= GRACKLE_PM|GRACKLE_NAP; | ||
2485 | pci_write_config_word(grackle, 0x70, pmcr1); | ||
2486 | |||
2487 | /* Call low-level ASM sleep handler */ | ||
2488 | if (__fake_sleep) | ||
2489 | mdelay(5000); | ||
2490 | else | ||
2491 | low_sleep_handler(); | ||
2492 | |||
2493 | /* We're awake again, stop grackle PM */ | ||
2494 | pci_read_config_word(grackle, 0x70, &pmcr1); | ||
2495 | pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); | ||
2496 | pci_write_config_word(grackle, 0x70, pmcr1); | ||
2497 | |||
2498 | /* Make sure the PMU is idle */ | ||
2499 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0); | ||
2500 | restore_via_state(); | ||
2501 | |||
2502 | /* Restore L2 cache */ | ||
2503 | if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) | ||
2504 | _set_L2CR(save_l2cr); | ||
2505 | |||
2506 | /* Restore userland MMU context */ | ||
2507 | set_context(current->active_mm->context, current->active_mm->pgd); | ||
2508 | |||
2509 | /* Power things up */ | ||
2510 | pmu_unlock(); | ||
2511 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); | ||
2512 | pmu_wait_complete(&req); | ||
2513 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, | ||
2514 | PMU_POW0_ON|PMU_POW0_HARD_DRIVE); | ||
2515 | pmu_wait_complete(&req); | ||
2516 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
2517 | PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY); | ||
2518 | pmu_wait_complete(&req); | ||
2519 | |||
2520 | pmac_wakeup_devices(); | ||
2521 | |||
2522 | return 0; | ||
2523 | } | ||
2524 | |||
2525 | static int __pmac | ||
2526 | powerbook_sleep_Core99(void) | ||
2527 | { | ||
2528 | unsigned long save_l2cr; | ||
2529 | unsigned long save_l3cr; | ||
2530 | struct adb_request req; | ||
2531 | int ret; | ||
2532 | |||
2533 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) { | ||
2534 | printk(KERN_ERR "Sleep mode not supported on this machine\n"); | ||
2535 | return -ENOSYS; | ||
2536 | } | ||
2537 | |||
2538 | if (num_online_cpus() > 1 || cpu_is_offline(0)) | ||
2539 | return -EAGAIN; | ||
2540 | |||
2541 | ret = pmac_suspend_devices(); | ||
2542 | if (ret) { | ||
2543 | printk(KERN_ERR "Sleep rejected by devices\n"); | ||
2544 | return ret; | ||
2545 | } | ||
2546 | |||
2547 | printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); | ||
2548 | |||
2549 | /* Tell PMU what events will wake us up */ | ||
2550 | pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS, | ||
2551 | 0xff, 0xff); | ||
2552 | pmu_wait_complete(&req); | ||
2553 | pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS, | ||
2554 | 0, PMU_PWR_WAKEUP_KEY | | ||
2555 | (option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0)); | ||
2556 | pmu_wait_complete(&req); | ||
2557 | |||
2558 | /* Save the state of the L2 and L3 caches */ | ||
2559 | save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ | ||
2560 | save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ | ||
2561 | |||
2562 | if (!__fake_sleep) { | ||
2563 | /* Ask the PMU to put us to sleep */ | ||
2564 | pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); | ||
2565 | pmu_wait_complete(&req); | ||
2566 | } | ||
2567 | |||
2568 | /* The VIA is supposed not to be restored correctly*/ | ||
2569 | save_via_state(); | ||
2570 | |||
2571 | /* Shut down various ASICs. There's a chance that we can no longer | ||
2572 | * talk to the PMU after this, so I moved it to _after_ sending the | ||
2573 | * sleep command to it. Still need to be checked. | ||
2574 | */ | ||
2575 | pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1); | ||
2576 | |||
2577 | /* Call low-level ASM sleep handler */ | ||
2578 | if (__fake_sleep) | ||
2579 | mdelay(5000); | ||
2580 | else | ||
2581 | low_sleep_handler(); | ||
2582 | |||
2583 | /* Restore Apple core ASICs state */ | ||
2584 | pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0); | ||
2585 | |||
2586 | /* Restore VIA */ | ||
2587 | restore_via_state(); | ||
2588 | |||
2589 | /* Restore video */ | ||
2590 | pmac_call_early_video_resume(); | ||
2591 | |||
2592 | /* Restore L2 cache */ | ||
2593 | if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) | ||
2594 | _set_L2CR(save_l2cr); | ||
2595 | /* Restore L3 cache */ | ||
2596 | if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) | ||
2597 | _set_L3CR(save_l3cr); | ||
2598 | |||
2599 | /* Restore userland MMU context */ | ||
2600 | set_context(current->active_mm->context, current->active_mm->pgd); | ||
2601 | |||
2602 | /* Tell PMU we are ready */ | ||
2603 | pmu_unlock(); | ||
2604 | pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); | ||
2605 | pmu_wait_complete(&req); | ||
2606 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); | ||
2607 | pmu_wait_complete(&req); | ||
2608 | |||
2609 | printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); | ||
2610 | |||
2611 | pmac_wakeup_devices(); | ||
2612 | |||
2613 | return 0; | ||
2614 | } | ||
2615 | |||
2616 | #define PB3400_MEM_CTRL 0xf8000000 | ||
2617 | #define PB3400_MEM_CTRL_SLEEP 0x70 | ||
2618 | |||
2619 | static int __pmac | ||
2620 | powerbook_sleep_3400(void) | ||
2621 | { | ||
2622 | int ret, i, x; | ||
2623 | unsigned int hid0; | ||
2624 | unsigned long p; | ||
2625 | struct adb_request sleep_req; | ||
2626 | void __iomem *mem_ctrl; | ||
2627 | unsigned int __iomem *mem_ctrl_sleep; | ||
2628 | |||
2629 | /* first map in the memory controller registers */ | ||
2630 | mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100); | ||
2631 | if (mem_ctrl == NULL) { | ||
2632 | printk("powerbook_sleep_3400: ioremap failed\n"); | ||
2633 | return -ENOMEM; | ||
2634 | } | ||
2635 | mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP; | ||
2636 | |||
2637 | /* Allocate room for PCI save */ | ||
2638 | pbook_alloc_pci_save(); | ||
2639 | |||
2640 | ret = pmac_suspend_devices(); | ||
2641 | if (ret) { | ||
2642 | pbook_free_pci_save(); | ||
2643 | printk(KERN_ERR "Sleep rejected by devices\n"); | ||
2644 | return ret; | ||
2645 | } | ||
2646 | |||
2647 | /* Save the state of PCI config space for some slots */ | ||
2648 | pbook_pci_save(); | ||
2649 | |||
2650 | /* Set the memory controller to keep the memory refreshed | ||
2651 | while we're asleep */ | ||
2652 | for (i = 0x403f; i >= 0x4000; --i) { | ||
2653 | out_be32(mem_ctrl_sleep, i); | ||
2654 | do { | ||
2655 | x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff; | ||
2656 | } while (x == 0); | ||
2657 | if (x >= 0x100) | ||
2658 | break; | ||
2659 | } | ||
2660 | |||
2661 | /* Ask the PMU to put us to sleep */ | ||
2662 | pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); | ||
2663 | while (!sleep_req.complete) | ||
2664 | mb(); | ||
2665 | |||
2666 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1); | ||
2667 | |||
2668 | /* displacement-flush the L2 cache - necessary? */ | ||
2669 | for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000) | ||
2670 | i = *(volatile int *)p; | ||
2671 | asleep = 1; | ||
2672 | |||
2673 | /* Put the CPU into sleep mode */ | ||
2674 | asm volatile("mfspr %0,1008" : "=r" (hid0) :); | ||
2675 | hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; | ||
2676 | asm volatile("mtspr 1008,%0" : : "r" (hid0)); | ||
2677 | _nmask_and_or_msr(0, MSR_POW | MSR_EE); | ||
2678 | udelay(10); | ||
2679 | |||
2680 | /* OK, we're awake again, start restoring things */ | ||
2681 | out_be32(mem_ctrl_sleep, 0x3f); | ||
2682 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0); | ||
2683 | pbook_pci_restore(); | ||
2684 | pmu_unlock(); | ||
2685 | |||
2686 | /* wait for the PMU interrupt sequence to complete */ | ||
2687 | while (asleep) | ||
2688 | mb(); | ||
2689 | |||
2690 | pmac_wakeup_devices(); | ||
2691 | pbook_free_pci_save(); | ||
2692 | iounmap(mem_ctrl); | ||
2693 | |||
2694 | return 0; | ||
2695 | } | ||
2696 | |||
2697 | /* | ||
2698 | * Support for /dev/pmu device | ||
2699 | */ | ||
2700 | #define RB_SIZE 0x10 | ||
2701 | struct pmu_private { | ||
2702 | struct list_head list; | ||
2703 | int rb_get; | ||
2704 | int rb_put; | ||
2705 | struct rb_entry { | ||
2706 | unsigned short len; | ||
2707 | unsigned char data[16]; | ||
2708 | } rb_buf[RB_SIZE]; | ||
2709 | wait_queue_head_t wait; | ||
2710 | spinlock_t lock; | ||
2711 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | ||
2712 | int backlight_locker; | ||
2713 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | ||
2714 | }; | ||
2715 | |||
2716 | static LIST_HEAD(all_pmu_pvt); | ||
2717 | static DEFINE_SPINLOCK(all_pvt_lock __pmacdata); | ||
2718 | |||
2719 | static void __pmac | ||
2720 | pmu_pass_intr(unsigned char *data, int len) | ||
2721 | { | ||
2722 | struct pmu_private *pp; | ||
2723 | struct list_head *list; | ||
2724 | int i; | ||
2725 | unsigned long flags; | ||
2726 | |||
2727 | if (len > sizeof(pp->rb_buf[0].data)) | ||
2728 | len = sizeof(pp->rb_buf[0].data); | ||
2729 | spin_lock_irqsave(&all_pvt_lock, flags); | ||
2730 | for (list = &all_pmu_pvt; (list = list->next) != &all_pmu_pvt; ) { | ||
2731 | pp = list_entry(list, struct pmu_private, list); | ||
2732 | spin_lock(&pp->lock); | ||
2733 | i = pp->rb_put + 1; | ||
2734 | if (i >= RB_SIZE) | ||
2735 | i = 0; | ||
2736 | if (i != pp->rb_get) { | ||
2737 | struct rb_entry *rp = &pp->rb_buf[pp->rb_put]; | ||
2738 | rp->len = len; | ||
2739 | memcpy(rp->data, data, len); | ||
2740 | pp->rb_put = i; | ||
2741 | wake_up_interruptible(&pp->wait); | ||
2742 | } | ||
2743 | spin_unlock(&pp->lock); | ||
2744 | } | ||
2745 | spin_unlock_irqrestore(&all_pvt_lock, flags); | ||
2746 | } | ||
2747 | |||
2748 | static int __pmac | ||
2749 | pmu_open(struct inode *inode, struct file *file) | ||
2750 | { | ||
2751 | struct pmu_private *pp; | ||
2752 | unsigned long flags; | ||
2753 | |||
2754 | pp = kmalloc(sizeof(struct pmu_private), GFP_KERNEL); | ||
2755 | if (pp == 0) | ||
2756 | return -ENOMEM; | ||
2757 | pp->rb_get = pp->rb_put = 0; | ||
2758 | spin_lock_init(&pp->lock); | ||
2759 | init_waitqueue_head(&pp->wait); | ||
2760 | spin_lock_irqsave(&all_pvt_lock, flags); | ||
2761 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | ||
2762 | pp->backlight_locker = 0; | ||
2763 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | ||
2764 | list_add(&pp->list, &all_pmu_pvt); | ||
2765 | spin_unlock_irqrestore(&all_pvt_lock, flags); | ||
2766 | file->private_data = pp; | ||
2767 | return 0; | ||
2768 | } | ||
2769 | |||
2770 | static ssize_t __pmac | ||
2771 | pmu_read(struct file *file, char __user *buf, | ||
2772 | size_t count, loff_t *ppos) | ||
2773 | { | ||
2774 | struct pmu_private *pp = file->private_data; | ||
2775 | DECLARE_WAITQUEUE(wait, current); | ||
2776 | unsigned long flags; | ||
2777 | int ret = 0; | ||
2778 | |||
2779 | if (count < 1 || pp == 0) | ||
2780 | return -EINVAL; | ||
2781 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
2782 | return -EFAULT; | ||
2783 | |||
2784 | spin_lock_irqsave(&pp->lock, flags); | ||
2785 | add_wait_queue(&pp->wait, &wait); | ||
2786 | current->state = TASK_INTERRUPTIBLE; | ||
2787 | |||
2788 | for (;;) { | ||
2789 | ret = -EAGAIN; | ||
2790 | if (pp->rb_get != pp->rb_put) { | ||
2791 | int i = pp->rb_get; | ||
2792 | struct rb_entry *rp = &pp->rb_buf[i]; | ||
2793 | ret = rp->len; | ||
2794 | spin_unlock_irqrestore(&pp->lock, flags); | ||
2795 | if (ret > count) | ||
2796 | ret = count; | ||
2797 | if (ret > 0 && copy_to_user(buf, rp->data, ret)) | ||
2798 | ret = -EFAULT; | ||
2799 | if (++i >= RB_SIZE) | ||
2800 | i = 0; | ||
2801 | spin_lock_irqsave(&pp->lock, flags); | ||
2802 | pp->rb_get = i; | ||
2803 | } | ||
2804 | if (ret >= 0) | ||
2805 | break; | ||
2806 | if (file->f_flags & O_NONBLOCK) | ||
2807 | break; | ||
2808 | ret = -ERESTARTSYS; | ||
2809 | if (signal_pending(current)) | ||
2810 | break; | ||
2811 | spin_unlock_irqrestore(&pp->lock, flags); | ||
2812 | schedule(); | ||
2813 | spin_lock_irqsave(&pp->lock, flags); | ||
2814 | } | ||
2815 | current->state = TASK_RUNNING; | ||
2816 | remove_wait_queue(&pp->wait, &wait); | ||
2817 | spin_unlock_irqrestore(&pp->lock, flags); | ||
2818 | |||
2819 | return ret; | ||
2820 | } | ||
2821 | |||
2822 | static ssize_t __pmac | ||
2823 | pmu_write(struct file *file, const char __user *buf, | ||
2824 | size_t count, loff_t *ppos) | ||
2825 | { | ||
2826 | return 0; | ||
2827 | } | ||
2828 | |||
2829 | static unsigned int __pmac | ||
2830 | pmu_fpoll(struct file *filp, poll_table *wait) | ||
2831 | { | ||
2832 | struct pmu_private *pp = filp->private_data; | ||
2833 | unsigned int mask = 0; | ||
2834 | unsigned long flags; | ||
2835 | |||
2836 | if (pp == 0) | ||
2837 | return 0; | ||
2838 | poll_wait(filp, &pp->wait, wait); | ||
2839 | spin_lock_irqsave(&pp->lock, flags); | ||
2840 | if (pp->rb_get != pp->rb_put) | ||
2841 | mask |= POLLIN; | ||
2842 | spin_unlock_irqrestore(&pp->lock, flags); | ||
2843 | return mask; | ||
2844 | } | ||
2845 | |||
2846 | static int __pmac | ||
2847 | pmu_release(struct inode *inode, struct file *file) | ||
2848 | { | ||
2849 | struct pmu_private *pp = file->private_data; | ||
2850 | unsigned long flags; | ||
2851 | |||
2852 | lock_kernel(); | ||
2853 | if (pp != 0) { | ||
2854 | file->private_data = NULL; | ||
2855 | spin_lock_irqsave(&all_pvt_lock, flags); | ||
2856 | list_del(&pp->list); | ||
2857 | spin_unlock_irqrestore(&all_pvt_lock, flags); | ||
2858 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | ||
2859 | if (pp->backlight_locker) { | ||
2860 | spin_lock_irqsave(&pmu_lock, flags); | ||
2861 | disable_kernel_backlight--; | ||
2862 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
2863 | } | ||
2864 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | ||
2865 | kfree(pp); | ||
2866 | } | ||
2867 | unlock_kernel(); | ||
2868 | return 0; | ||
2869 | } | ||
2870 | |||
2871 | /* Note: removed __openfirmware here since it causes link errors */ | ||
2872 | static int __pmac | ||
2873 | pmu_ioctl(struct inode * inode, struct file *filp, | ||
2874 | u_int cmd, u_long arg) | ||
2875 | { | ||
2876 | struct pmu_private *pp = filp->private_data; | ||
2877 | __u32 __user *argp = (__u32 __user *)arg; | ||
2878 | int error; | ||
2879 | |||
2880 | switch (cmd) { | ||
2881 | case PMU_IOC_SLEEP: | ||
2882 | if (!capable(CAP_SYS_ADMIN)) | ||
2883 | return -EACCES; | ||
2884 | if (sleep_in_progress) | ||
2885 | return -EBUSY; | ||
2886 | sleep_in_progress = 1; | ||
2887 | switch (pmu_kind) { | ||
2888 | case PMU_OHARE_BASED: | ||
2889 | error = powerbook_sleep_3400(); | ||
2890 | break; | ||
2891 | case PMU_HEATHROW_BASED: | ||
2892 | case PMU_PADDINGTON_BASED: | ||
2893 | error = powerbook_sleep_grackle(); | ||
2894 | break; | ||
2895 | case PMU_KEYLARGO_BASED: | ||
2896 | error = powerbook_sleep_Core99(); | ||
2897 | break; | ||
2898 | default: | ||
2899 | error = -ENOSYS; | ||
2900 | } | ||
2901 | sleep_in_progress = 0; | ||
2902 | return error; | ||
2903 | case PMU_IOC_CAN_SLEEP: | ||
2904 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) | ||
2905 | return put_user(0, argp); | ||
2906 | else | ||
2907 | return put_user(1, argp); | ||
2908 | |||
2909 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2910 | /* Backlight should have its own device or go via | ||
2911 | * the fbdev | ||
2912 | */ | ||
2913 | case PMU_IOC_GET_BACKLIGHT: | ||
2914 | if (sleep_in_progress) | ||
2915 | return -EBUSY; | ||
2916 | error = get_backlight_level(); | ||
2917 | if (error < 0) | ||
2918 | return error; | ||
2919 | return put_user(error, argp); | ||
2920 | case PMU_IOC_SET_BACKLIGHT: | ||
2921 | { | ||
2922 | __u32 value; | ||
2923 | if (sleep_in_progress) | ||
2924 | return -EBUSY; | ||
2925 | error = get_user(value, argp); | ||
2926 | if (!error) | ||
2927 | error = set_backlight_level(value); | ||
2928 | return error; | ||
2929 | } | ||
2930 | #ifdef CONFIG_INPUT_ADBHID | ||
2931 | case PMU_IOC_GRAB_BACKLIGHT: { | ||
2932 | unsigned long flags; | ||
2933 | if (pp->backlight_locker) | ||
2934 | return 0; | ||
2935 | pp->backlight_locker = 1; | ||
2936 | spin_lock_irqsave(&pmu_lock, flags); | ||
2937 | disable_kernel_backlight++; | ||
2938 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
2939 | return 0; | ||
2940 | } | ||
2941 | #endif /* CONFIG_INPUT_ADBHID */ | ||
2942 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
2943 | case PMU_IOC_GET_MODEL: | ||
2944 | return put_user(pmu_kind, argp); | ||
2945 | case PMU_IOC_HAS_ADB: | ||
2946 | return put_user(pmu_has_adb, argp); | ||
2947 | } | ||
2948 | return -EINVAL; | ||
2949 | } | ||
2950 | |||
2951 | static struct file_operations pmu_device_fops __pmacdata = { | ||
2952 | .read = pmu_read, | ||
2953 | .write = pmu_write, | ||
2954 | .poll = pmu_fpoll, | ||
2955 | .ioctl = pmu_ioctl, | ||
2956 | .open = pmu_open, | ||
2957 | .release = pmu_release, | ||
2958 | }; | ||
2959 | |||
2960 | static struct miscdevice pmu_device __pmacdata = { | ||
2961 | PMU_MINOR, "pmu", &pmu_device_fops | ||
2962 | }; | ||
2963 | |||
2964 | void pmu_device_init(void) | ||
2965 | { | ||
2966 | if (!via) | ||
2967 | return; | ||
2968 | if (misc_register(&pmu_device) < 0) | ||
2969 | printk(KERN_ERR "via-pmu: cannot register misc device.\n"); | ||
2970 | } | ||
2971 | #endif /* CONFIG_PMAC_PBOOK */ | ||
2972 | |||
2973 | #ifdef DEBUG_SLEEP | ||
2974 | static inline void __pmac | ||
2975 | polled_handshake(volatile unsigned char __iomem *via) | ||
2976 | { | ||
2977 | via[B] &= ~TREQ; eieio(); | ||
2978 | while ((via[B] & TACK) != 0) | ||
2979 | ; | ||
2980 | via[B] |= TREQ; eieio(); | ||
2981 | while ((via[B] & TACK) == 0) | ||
2982 | ; | ||
2983 | } | ||
2984 | |||
2985 | static inline void __pmac | ||
2986 | polled_send_byte(volatile unsigned char __iomem *via, int x) | ||
2987 | { | ||
2988 | via[ACR] |= SR_OUT | SR_EXT; eieio(); | ||
2989 | via[SR] = x; eieio(); | ||
2990 | polled_handshake(via); | ||
2991 | } | ||
2992 | |||
2993 | static inline int __pmac | ||
2994 | polled_recv_byte(volatile unsigned char __iomem *via) | ||
2995 | { | ||
2996 | int x; | ||
2997 | |||
2998 | via[ACR] = (via[ACR] & ~SR_OUT) | SR_EXT; eieio(); | ||
2999 | x = via[SR]; eieio(); | ||
3000 | polled_handshake(via); | ||
3001 | x = via[SR]; eieio(); | ||
3002 | return x; | ||
3003 | } | ||
3004 | |||
3005 | int __pmac | ||
3006 | pmu_polled_request(struct adb_request *req) | ||
3007 | { | ||
3008 | unsigned long flags; | ||
3009 | int i, l, c; | ||
3010 | volatile unsigned char __iomem *v = via; | ||
3011 | |||
3012 | req->complete = 1; | ||
3013 | c = req->data[0]; | ||
3014 | l = pmu_data_len[c][0]; | ||
3015 | if (l >= 0 && req->nbytes != l + 1) | ||
3016 | return -EINVAL; | ||
3017 | |||
3018 | local_irq_save(flags); | ||
3019 | while (pmu_state != idle) | ||
3020 | pmu_poll(); | ||
3021 | |||
3022 | while ((via[B] & TACK) == 0) | ||
3023 | ; | ||
3024 | polled_send_byte(v, c); | ||
3025 | if (l < 0) { | ||
3026 | l = req->nbytes - 1; | ||
3027 | polled_send_byte(v, l); | ||
3028 | } | ||
3029 | for (i = 1; i <= l; ++i) | ||
3030 | polled_send_byte(v, req->data[i]); | ||
3031 | |||
3032 | l = pmu_data_len[c][1]; | ||
3033 | if (l < 0) | ||
3034 | l = polled_recv_byte(v); | ||
3035 | for (i = 0; i < l; ++i) | ||
3036 | req->reply[i + req->reply_len] = polled_recv_byte(v); | ||
3037 | |||
3038 | if (req->done) | ||
3039 | (*req->done)(req); | ||
3040 | |||
3041 | local_irq_restore(flags); | ||
3042 | return 0; | ||
3043 | } | ||
3044 | #endif /* DEBUG_SLEEP */ | ||
3045 | |||
3046 | |||
3047 | /* FIXME: This is a temporary set of callbacks to enable us | ||
3048 | * to do suspend-to-disk. | ||
3049 | */ | ||
3050 | |||
3051 | #ifdef CONFIG_PM | ||
3052 | |||
3053 | static int pmu_sys_suspended = 0; | ||
3054 | |||
3055 | static int pmu_sys_suspend(struct sys_device *sysdev, u32 state) | ||
3056 | { | ||
3057 | if (state != PM_SUSPEND_DISK || pmu_sys_suspended) | ||
3058 | return 0; | ||
3059 | |||
3060 | /* Suspend PMU event interrupts */ | ||
3061 | pmu_suspend(); | ||
3062 | |||
3063 | pmu_sys_suspended = 1; | ||
3064 | return 0; | ||
3065 | } | ||
3066 | |||
3067 | static int pmu_sys_resume(struct sys_device *sysdev) | ||
3068 | { | ||
3069 | struct adb_request req; | ||
3070 | |||
3071 | if (!pmu_sys_suspended) | ||
3072 | return 0; | ||
3073 | |||
3074 | /* Tell PMU we are ready */ | ||
3075 | pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); | ||
3076 | pmu_wait_complete(&req); | ||
3077 | |||
3078 | /* Resume PMU event interrupts */ | ||
3079 | pmu_resume(); | ||
3080 | |||
3081 | pmu_sys_suspended = 0; | ||
3082 | |||
3083 | return 0; | ||
3084 | } | ||
3085 | |||
3086 | #endif /* CONFIG_PM */ | ||
3087 | |||
3088 | static struct sysdev_class pmu_sysclass = { | ||
3089 | set_kset_name("pmu"), | ||
3090 | }; | ||
3091 | |||
3092 | static struct sys_device device_pmu = { | ||
3093 | .id = 0, | ||
3094 | .cls = &pmu_sysclass, | ||
3095 | }; | ||
3096 | |||
3097 | static struct sysdev_driver driver_pmu = { | ||
3098 | #ifdef CONFIG_PM | ||
3099 | .suspend = &pmu_sys_suspend, | ||
3100 | .resume = &pmu_sys_resume, | ||
3101 | #endif /* CONFIG_PM */ | ||
3102 | }; | ||
3103 | |||
3104 | static int __init init_pmu_sysfs(void) | ||
3105 | { | ||
3106 | int rc; | ||
3107 | |||
3108 | rc = sysdev_class_register(&pmu_sysclass); | ||
3109 | if (rc) { | ||
3110 | printk(KERN_ERR "Failed registering PMU sys class\n"); | ||
3111 | return -ENODEV; | ||
3112 | } | ||
3113 | rc = sysdev_register(&device_pmu); | ||
3114 | if (rc) { | ||
3115 | printk(KERN_ERR "Failed registering PMU sys device\n"); | ||
3116 | return -ENODEV; | ||
3117 | } | ||
3118 | rc = sysdev_driver_register(&pmu_sysclass, &driver_pmu); | ||
3119 | if (rc) { | ||
3120 | printk(KERN_ERR "Failed registering PMU sys driver\n"); | ||
3121 | return -ENODEV; | ||
3122 | } | ||
3123 | return 0; | ||
3124 | } | ||
3125 | |||
3126 | subsys_initcall(init_pmu_sysfs); | ||
3127 | |||
3128 | EXPORT_SYMBOL(pmu_request); | ||
3129 | EXPORT_SYMBOL(pmu_poll); | ||
3130 | EXPORT_SYMBOL(pmu_poll_adb); | ||
3131 | EXPORT_SYMBOL(pmu_wait_complete); | ||
3132 | EXPORT_SYMBOL(pmu_suspend); | ||
3133 | EXPORT_SYMBOL(pmu_resume); | ||
3134 | EXPORT_SYMBOL(pmu_unlock); | ||
3135 | EXPORT_SYMBOL(pmu_i2c_combined_read); | ||
3136 | EXPORT_SYMBOL(pmu_i2c_stdsub_write); | ||
3137 | EXPORT_SYMBOL(pmu_i2c_simple_read); | ||
3138 | EXPORT_SYMBOL(pmu_i2c_simple_write); | ||
3139 | #ifdef CONFIG_PMAC_PBOOK | ||
3140 | EXPORT_SYMBOL(pmu_register_sleep_notifier); | ||
3141 | EXPORT_SYMBOL(pmu_unregister_sleep_notifier); | ||
3142 | EXPORT_SYMBOL(pmu_enable_irled); | ||
3143 | EXPORT_SYMBOL(pmu_battery_count); | ||
3144 | EXPORT_SYMBOL(pmu_batteries); | ||
3145 | EXPORT_SYMBOL(pmu_power_flags); | ||
3146 | #endif /* CONFIG_PMAC_PBOOK */ | ||
3147 | |||
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c new file mode 100644 index 000000000000..820dc52e30bc --- /dev/null +++ b/drivers/macintosh/via-pmu68k.c | |||
@@ -0,0 +1,1063 @@ | |||
1 | /* | ||
2 | * Device driver for the PMU on 68K-based Apple PowerBooks | ||
3 | * | ||
4 | * The VIA (versatile interface adapter) interfaces to the PMU, | ||
5 | * a 6805 microprocessor core whose primary function is to control | ||
6 | * battery charging and system power on the PowerBooks. | ||
7 | * The PMU also controls the ADB (Apple Desktop Bus) which connects | ||
8 | * to the keyboard and mouse, as well as the non-volatile RAM | ||
9 | * and the RTC (real time clock) chip. | ||
10 | * | ||
11 | * Adapted for 68K PMU by Joshua M. Thompson | ||
12 | * | ||
13 | * Based largely on the PowerMac PMU code by Paul Mackerras and | ||
14 | * Fabio Riccardi. | ||
15 | * | ||
16 | * Also based on the PMU driver from MkLinux by Apple Computer, Inc. | ||
17 | * and the Open Software Foundation, Inc. | ||
18 | */ | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/blkdev.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | |||
33 | #include <linux/adb.h> | ||
34 | #include <linux/pmu.h> | ||
35 | #include <linux/cuda.h> | ||
36 | |||
37 | #include <asm/macintosh.h> | ||
38 | #include <asm/macints.h> | ||
39 | #include <asm/machw.h> | ||
40 | #include <asm/mac_via.h> | ||
41 | |||
42 | #include <asm/pgtable.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/irq.h> | ||
45 | #include <asm/uaccess.h> | ||
46 | |||
47 | /* Misc minor number allocated for /dev/pmu */ | ||
48 | #define PMU_MINOR 154 | ||
49 | |||
50 | /* VIA registers - spaced 0x200 bytes apart */ | ||
51 | #define RS 0x200 /* skip between registers */ | ||
52 | #define B 0 /* B-side data */ | ||
53 | #define A RS /* A-side data */ | ||
54 | #define DIRB (2*RS) /* B-side direction (1=output) */ | ||
55 | #define DIRA (3*RS) /* A-side direction (1=output) */ | ||
56 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
57 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
58 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
59 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
60 | #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ | ||
61 | #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ | ||
62 | #define SR (10*RS) /* Shift register */ | ||
63 | #define ACR (11*RS) /* Auxiliary control register */ | ||
64 | #define PCR (12*RS) /* Peripheral control register */ | ||
65 | #define IFR (13*RS) /* Interrupt flag register */ | ||
66 | #define IER (14*RS) /* Interrupt enable register */ | ||
67 | #define ANH (15*RS) /* A-side data, no handshake */ | ||
68 | |||
69 | /* Bits in B data register: both active low */ | ||
70 | #define TACK 0x02 /* Transfer acknowledge (input) */ | ||
71 | #define TREQ 0x04 /* Transfer request (output) */ | ||
72 | |||
73 | /* Bits in ACR */ | ||
74 | #define SR_CTRL 0x1c /* Shift register control bits */ | ||
75 | #define SR_EXT 0x0c /* Shift on external clock */ | ||
76 | #define SR_OUT 0x10 /* Shift out if 1 */ | ||
77 | |||
78 | /* Bits in IFR and IER */ | ||
79 | #define SR_INT 0x04 /* Shift register full/empty */ | ||
80 | #define CB1_INT 0x10 /* transition on CB1 input */ | ||
81 | |||
82 | static enum pmu_state { | ||
83 | idle, | ||
84 | sending, | ||
85 | intack, | ||
86 | reading, | ||
87 | reading_intr, | ||
88 | } pmu_state; | ||
89 | |||
90 | static struct adb_request *current_req; | ||
91 | static struct adb_request *last_req; | ||
92 | static struct adb_request *req_awaiting_reply; | ||
93 | static unsigned char interrupt_data[32]; | ||
94 | static unsigned char *reply_ptr; | ||
95 | static int data_index; | ||
96 | static int data_len; | ||
97 | static int adb_int_pending; | ||
98 | static int pmu_adb_flags; | ||
99 | static int adb_dev_map = 0; | ||
100 | static struct adb_request bright_req_1, bright_req_2, bright_req_3; | ||
101 | static int pmu_kind = PMU_UNKNOWN; | ||
102 | static int pmu_fully_inited = 0; | ||
103 | |||
104 | int asleep; | ||
105 | struct notifier_block *sleep_notifier_list; | ||
106 | |||
107 | static int pmu_probe(void); | ||
108 | static int pmu_init(void); | ||
109 | static void pmu_start(void); | ||
110 | static irqreturn_t pmu_interrupt(int irq, void *arg, struct pt_regs *regs); | ||
111 | static int pmu_send_request(struct adb_request *req, int sync); | ||
112 | static int pmu_autopoll(int devs); | ||
113 | void pmu_poll(void); | ||
114 | static int pmu_reset_bus(void); | ||
115 | static int pmu_queue_request(struct adb_request *req); | ||
116 | |||
117 | static void pmu_start(void); | ||
118 | static void send_byte(int x); | ||
119 | static void recv_byte(void); | ||
120 | static void pmu_done(struct adb_request *req); | ||
121 | static void pmu_handle_data(unsigned char *data, int len, | ||
122 | struct pt_regs *regs); | ||
123 | static void set_volume(int level); | ||
124 | static void pmu_enable_backlight(int on); | ||
125 | static void pmu_set_brightness(int level); | ||
126 | |||
127 | struct adb_driver via_pmu_driver = { | ||
128 | "68K PMU", | ||
129 | pmu_probe, | ||
130 | pmu_init, | ||
131 | pmu_send_request, | ||
132 | pmu_autopoll, | ||
133 | pmu_poll, | ||
134 | pmu_reset_bus | ||
135 | }; | ||
136 | |||
137 | /* | ||
138 | * This table indicates for each PMU opcode: | ||
139 | * - the number of data bytes to be sent with the command, or -1 | ||
140 | * if a length byte should be sent, | ||
141 | * - the number of response bytes which the PMU will return, or | ||
142 | * -1 if it will send a length byte. | ||
143 | */ | ||
144 | static s8 pmu_data_len[256][2] = { | ||
145 | /* 0 1 2 3 4 5 6 7 */ | ||
146 | /*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
147 | /*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
148 | /*10*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
149 | /*18*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0, 0}, | ||
150 | /*20*/ {-1, 0},{ 0, 0},{ 2, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
151 | /*28*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0,-1}, | ||
152 | /*30*/ { 4, 0},{20, 0},{-1, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
153 | /*38*/ { 0, 4},{ 0,20},{ 2,-1},{ 2, 1},{ 3,-1},{-1,-1},{-1,-1},{ 4, 0}, | ||
154 | /*40*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
155 | /*48*/ { 0, 1},{ 0, 1},{-1,-1},{ 1, 0},{ 1, 0},{-1,-1},{-1,-1},{-1,-1}, | ||
156 | /*50*/ { 1, 0},{ 0, 0},{ 2, 0},{ 2, 0},{-1, 0},{ 1, 0},{ 3, 0},{ 1, 0}, | ||
157 | /*58*/ { 0, 1},{ 1, 0},{ 0, 2},{ 0, 2},{ 0,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
158 | /*60*/ { 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
159 | /*68*/ { 0, 3},{ 0, 3},{ 0, 2},{ 0, 8},{ 0,-1},{ 0,-1},{-1,-1},{-1,-1}, | ||
160 | /*70*/ { 1, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
161 | /*78*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{ 5, 1},{ 4, 1},{ 4, 1}, | ||
162 | /*80*/ { 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
163 | /*88*/ { 0, 5},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
164 | /*90*/ { 1, 0},{ 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
165 | /*98*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
166 | /*a0*/ { 2, 0},{ 2, 0},{ 2, 0},{ 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0}, | ||
167 | /*a8*/ { 1, 1},{ 1, 0},{ 3, 0},{ 2, 0},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
168 | /*b0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
169 | /*b8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
170 | /*c0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
171 | /*c8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
172 | /*d0*/ { 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
173 | /*d8*/ { 1, 1},{ 1, 1},{-1,-1},{-1,-1},{ 0, 1},{ 0,-1},{-1,-1},{-1,-1}, | ||
174 | /*e0*/ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{ 4, 0},{-1, 0},{-1, 0}, | ||
175 | /*e8*/ { 3,-1},{-1,-1},{ 0, 1},{-1,-1},{ 0,-1},{-1,-1},{-1,-1},{ 0, 0}, | ||
176 | /*f0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, | ||
177 | /*f8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, | ||
178 | }; | ||
179 | |||
180 | int pmu_probe(void) | ||
181 | { | ||
182 | if (macintosh_config->adb_type == MAC_ADB_PB1) { | ||
183 | pmu_kind = PMU_68K_V1; | ||
184 | } else if (macintosh_config->adb_type == MAC_ADB_PB2) { | ||
185 | pmu_kind = PMU_68K_V2; | ||
186 | } else { | ||
187 | return -ENODEV; | ||
188 | } | ||
189 | |||
190 | pmu_state = idle; | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | pmu_init(void) | ||
197 | { | ||
198 | int timeout; | ||
199 | volatile struct adb_request req; | ||
200 | |||
201 | via2[B] |= TREQ; /* negate TREQ */ | ||
202 | via2[DIRB] = (via2[DIRB] | TREQ) & ~TACK; /* TACK in, TREQ out */ | ||
203 | |||
204 | pmu_request((struct adb_request *) &req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB); | ||
205 | timeout = 100000; | ||
206 | while (!req.complete) { | ||
207 | if (--timeout < 0) { | ||
208 | printk(KERN_ERR "pmu_init: no response from PMU\n"); | ||
209 | return -EAGAIN; | ||
210 | } | ||
211 | udelay(10); | ||
212 | pmu_poll(); | ||
213 | } | ||
214 | |||
215 | /* ack all pending interrupts */ | ||
216 | timeout = 100000; | ||
217 | interrupt_data[0] = 1; | ||
218 | while (interrupt_data[0] || pmu_state != idle) { | ||
219 | if (--timeout < 0) { | ||
220 | printk(KERN_ERR "pmu_init: timed out acking intrs\n"); | ||
221 | return -EAGAIN; | ||
222 | } | ||
223 | if (pmu_state == idle) { | ||
224 | adb_int_pending = 1; | ||
225 | pmu_interrupt(0, NULL, NULL); | ||
226 | } | ||
227 | pmu_poll(); | ||
228 | udelay(10); | ||
229 | } | ||
230 | |||
231 | pmu_request((struct adb_request *) &req, NULL, 2, PMU_SET_INTR_MASK, | ||
232 | PMU_INT_ADB_AUTO|PMU_INT_SNDBRT|PMU_INT_ADB); | ||
233 | timeout = 100000; | ||
234 | while (!req.complete) { | ||
235 | if (--timeout < 0) { | ||
236 | printk(KERN_ERR "pmu_init: no response from PMU\n"); | ||
237 | return -EAGAIN; | ||
238 | } | ||
239 | udelay(10); | ||
240 | pmu_poll(); | ||
241 | } | ||
242 | |||
243 | bright_req_1.complete = 1; | ||
244 | bright_req_2.complete = 1; | ||
245 | bright_req_3.complete = 1; | ||
246 | |||
247 | if (request_irq(IRQ_MAC_ADB_SR, pmu_interrupt, 0, "pmu-shift", | ||
248 | pmu_interrupt)) { | ||
249 | printk(KERN_ERR "pmu_init: can't get irq %d\n", | ||
250 | IRQ_MAC_ADB_SR); | ||
251 | return -EAGAIN; | ||
252 | } | ||
253 | if (request_irq(IRQ_MAC_ADB_CL, pmu_interrupt, 0, "pmu-clock", | ||
254 | pmu_interrupt)) { | ||
255 | printk(KERN_ERR "pmu_init: can't get irq %d\n", | ||
256 | IRQ_MAC_ADB_CL); | ||
257 | free_irq(IRQ_MAC_ADB_SR, pmu_interrupt); | ||
258 | return -EAGAIN; | ||
259 | } | ||
260 | |||
261 | pmu_fully_inited = 1; | ||
262 | |||
263 | /* Enable backlight */ | ||
264 | pmu_enable_backlight(1); | ||
265 | |||
266 | printk("adb: PMU 68K driver v0.5 for Unified ADB.\n"); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | int | ||
272 | pmu_get_model(void) | ||
273 | { | ||
274 | return pmu_kind; | ||
275 | } | ||
276 | |||
277 | /* Send an ADB command */ | ||
278 | static int | ||
279 | pmu_send_request(struct adb_request *req, int sync) | ||
280 | { | ||
281 | int i, ret; | ||
282 | |||
283 | if (!pmu_fully_inited) | ||
284 | { | ||
285 | req->complete = 1; | ||
286 | return -ENXIO; | ||
287 | } | ||
288 | |||
289 | ret = -EINVAL; | ||
290 | |||
291 | switch (req->data[0]) { | ||
292 | case PMU_PACKET: | ||
293 | for (i = 0; i < req->nbytes - 1; ++i) | ||
294 | req->data[i] = req->data[i+1]; | ||
295 | --req->nbytes; | ||
296 | if (pmu_data_len[req->data[0]][1] != 0) { | ||
297 | req->reply[0] = ADB_RET_OK; | ||
298 | req->reply_len = 1; | ||
299 | } else | ||
300 | req->reply_len = 0; | ||
301 | ret = pmu_queue_request(req); | ||
302 | break; | ||
303 | case CUDA_PACKET: | ||
304 | switch (req->data[1]) { | ||
305 | case CUDA_GET_TIME: | ||
306 | if (req->nbytes != 2) | ||
307 | break; | ||
308 | req->data[0] = PMU_READ_RTC; | ||
309 | req->nbytes = 1; | ||
310 | req->reply_len = 3; | ||
311 | req->reply[0] = CUDA_PACKET; | ||
312 | req->reply[1] = 0; | ||
313 | req->reply[2] = CUDA_GET_TIME; | ||
314 | ret = pmu_queue_request(req); | ||
315 | break; | ||
316 | case CUDA_SET_TIME: | ||
317 | if (req->nbytes != 6) | ||
318 | break; | ||
319 | req->data[0] = PMU_SET_RTC; | ||
320 | req->nbytes = 5; | ||
321 | for (i = 1; i <= 4; ++i) | ||
322 | req->data[i] = req->data[i+1]; | ||
323 | req->reply_len = 3; | ||
324 | req->reply[0] = CUDA_PACKET; | ||
325 | req->reply[1] = 0; | ||
326 | req->reply[2] = CUDA_SET_TIME; | ||
327 | ret = pmu_queue_request(req); | ||
328 | break; | ||
329 | case CUDA_GET_PRAM: | ||
330 | if (req->nbytes != 4) | ||
331 | break; | ||
332 | req->data[0] = PMU_READ_NVRAM; | ||
333 | req->data[1] = req->data[2]; | ||
334 | req->data[2] = req->data[3]; | ||
335 | req->nbytes = 3; | ||
336 | req->reply_len = 3; | ||
337 | req->reply[0] = CUDA_PACKET; | ||
338 | req->reply[1] = 0; | ||
339 | req->reply[2] = CUDA_GET_PRAM; | ||
340 | ret = pmu_queue_request(req); | ||
341 | break; | ||
342 | case CUDA_SET_PRAM: | ||
343 | if (req->nbytes != 5) | ||
344 | break; | ||
345 | req->data[0] = PMU_WRITE_NVRAM; | ||
346 | req->data[1] = req->data[2]; | ||
347 | req->data[2] = req->data[3]; | ||
348 | req->data[3] = req->data[4]; | ||
349 | req->nbytes = 4; | ||
350 | req->reply_len = 3; | ||
351 | req->reply[0] = CUDA_PACKET; | ||
352 | req->reply[1] = 0; | ||
353 | req->reply[2] = CUDA_SET_PRAM; | ||
354 | ret = pmu_queue_request(req); | ||
355 | break; | ||
356 | } | ||
357 | break; | ||
358 | case ADB_PACKET: | ||
359 | for (i = req->nbytes - 1; i > 1; --i) | ||
360 | req->data[i+2] = req->data[i]; | ||
361 | req->data[3] = req->nbytes - 2; | ||
362 | req->data[2] = pmu_adb_flags; | ||
363 | /*req->data[1] = req->data[1];*/ | ||
364 | req->data[0] = PMU_ADB_CMD; | ||
365 | req->nbytes += 2; | ||
366 | req->reply_expected = 1; | ||
367 | req->reply_len = 0; | ||
368 | ret = pmu_queue_request(req); | ||
369 | break; | ||
370 | } | ||
371 | if (ret) | ||
372 | { | ||
373 | req->complete = 1; | ||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | if (sync) { | ||
378 | while (!req->complete) | ||
379 | pmu_poll(); | ||
380 | } | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | /* Enable/disable autopolling */ | ||
386 | static int | ||
387 | pmu_autopoll(int devs) | ||
388 | { | ||
389 | struct adb_request req; | ||
390 | |||
391 | if (!pmu_fully_inited) return -ENXIO; | ||
392 | |||
393 | if (devs) { | ||
394 | adb_dev_map = devs; | ||
395 | pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86, | ||
396 | adb_dev_map >> 8, adb_dev_map); | ||
397 | pmu_adb_flags = 2; | ||
398 | } else { | ||
399 | pmu_request(&req, NULL, 1, PMU_ADB_POLL_OFF); | ||
400 | pmu_adb_flags = 0; | ||
401 | } | ||
402 | while (!req.complete) | ||
403 | pmu_poll(); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | /* Reset the ADB bus */ | ||
408 | static int | ||
409 | pmu_reset_bus(void) | ||
410 | { | ||
411 | struct adb_request req; | ||
412 | long timeout; | ||
413 | int save_autopoll = adb_dev_map; | ||
414 | |||
415 | if (!pmu_fully_inited) return -ENXIO; | ||
416 | |||
417 | /* anyone got a better idea?? */ | ||
418 | pmu_autopoll(0); | ||
419 | |||
420 | req.nbytes = 5; | ||
421 | req.done = NULL; | ||
422 | req.data[0] = PMU_ADB_CMD; | ||
423 | req.data[1] = 0; | ||
424 | req.data[2] = 3; /* ADB_BUSRESET ??? */ | ||
425 | req.data[3] = 0; | ||
426 | req.data[4] = 0; | ||
427 | req.reply_len = 0; | ||
428 | req.reply_expected = 1; | ||
429 | if (pmu_queue_request(&req) != 0) | ||
430 | { | ||
431 | printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n"); | ||
432 | return -EIO; | ||
433 | } | ||
434 | while (!req.complete) | ||
435 | pmu_poll(); | ||
436 | timeout = 100000; | ||
437 | while (!req.complete) { | ||
438 | if (--timeout < 0) { | ||
439 | printk(KERN_ERR "pmu_adb_reset_bus (reset): no response from PMU\n"); | ||
440 | return -EIO; | ||
441 | } | ||
442 | udelay(10); | ||
443 | pmu_poll(); | ||
444 | } | ||
445 | |||
446 | if (save_autopoll != 0) | ||
447 | pmu_autopoll(save_autopoll); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | /* Construct and send a pmu request */ | ||
453 | int | ||
454 | pmu_request(struct adb_request *req, void (*done)(struct adb_request *), | ||
455 | int nbytes, ...) | ||
456 | { | ||
457 | va_list list; | ||
458 | int i; | ||
459 | |||
460 | if (nbytes < 0 || nbytes > 32) { | ||
461 | printk(KERN_ERR "pmu_request: bad nbytes (%d)\n", nbytes); | ||
462 | req->complete = 1; | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | req->nbytes = nbytes; | ||
466 | req->done = done; | ||
467 | va_start(list, nbytes); | ||
468 | for (i = 0; i < nbytes; ++i) | ||
469 | req->data[i] = va_arg(list, int); | ||
470 | va_end(list); | ||
471 | if (pmu_data_len[req->data[0]][1] != 0) { | ||
472 | req->reply[0] = ADB_RET_OK; | ||
473 | req->reply_len = 1; | ||
474 | } else | ||
475 | req->reply_len = 0; | ||
476 | req->reply_expected = 0; | ||
477 | return pmu_queue_request(req); | ||
478 | } | ||
479 | |||
480 | static int | ||
481 | pmu_queue_request(struct adb_request *req) | ||
482 | { | ||
483 | unsigned long flags; | ||
484 | int nsend; | ||
485 | |||
486 | if (req->nbytes <= 0) { | ||
487 | req->complete = 1; | ||
488 | return 0; | ||
489 | } | ||
490 | nsend = pmu_data_len[req->data[0]][0]; | ||
491 | if (nsend >= 0 && req->nbytes != nsend + 1) { | ||
492 | req->complete = 1; | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | |||
496 | req->next = 0; | ||
497 | req->sent = 0; | ||
498 | req->complete = 0; | ||
499 | local_irq_save(flags); | ||
500 | |||
501 | if (current_req != 0) { | ||
502 | last_req->next = req; | ||
503 | last_req = req; | ||
504 | } else { | ||
505 | current_req = req; | ||
506 | last_req = req; | ||
507 | if (pmu_state == idle) | ||
508 | pmu_start(); | ||
509 | } | ||
510 | |||
511 | local_irq_restore(flags); | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static void | ||
516 | send_byte(int x) | ||
517 | { | ||
518 | via1[ACR] |= SR_CTRL; | ||
519 | via1[SR] = x; | ||
520 | via2[B] &= ~TREQ; /* assert TREQ */ | ||
521 | } | ||
522 | |||
523 | static void | ||
524 | recv_byte(void) | ||
525 | { | ||
526 | char c; | ||
527 | |||
528 | via1[ACR] = (via1[ACR] | SR_EXT) & ~SR_OUT; | ||
529 | c = via1[SR]; /* resets SR */ | ||
530 | via2[B] &= ~TREQ; | ||
531 | } | ||
532 | |||
533 | static void | ||
534 | pmu_start(void) | ||
535 | { | ||
536 | unsigned long flags; | ||
537 | struct adb_request *req; | ||
538 | |||
539 | /* assert pmu_state == idle */ | ||
540 | /* get the packet to send */ | ||
541 | local_irq_save(flags); | ||
542 | req = current_req; | ||
543 | if (req == 0 || pmu_state != idle | ||
544 | || (req->reply_expected && req_awaiting_reply)) | ||
545 | goto out; | ||
546 | |||
547 | pmu_state = sending; | ||
548 | data_index = 1; | ||
549 | data_len = pmu_data_len[req->data[0]][0]; | ||
550 | |||
551 | /* set the shift register to shift out and send a byte */ | ||
552 | send_byte(req->data[0]); | ||
553 | |||
554 | out: | ||
555 | local_irq_restore(flags); | ||
556 | } | ||
557 | |||
558 | void | ||
559 | pmu_poll(void) | ||
560 | { | ||
561 | unsigned long flags; | ||
562 | |||
563 | local_irq_save(flags); | ||
564 | if (via1[IFR] & SR_INT) { | ||
565 | via1[IFR] = SR_INT; | ||
566 | pmu_interrupt(IRQ_MAC_ADB_SR, NULL, NULL); | ||
567 | } | ||
568 | if (via1[IFR] & CB1_INT) { | ||
569 | via1[IFR] = CB1_INT; | ||
570 | pmu_interrupt(IRQ_MAC_ADB_CL, NULL, NULL); | ||
571 | } | ||
572 | local_irq_restore(flags); | ||
573 | } | ||
574 | |||
575 | static irqreturn_t | ||
576 | pmu_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
577 | { | ||
578 | struct adb_request *req; | ||
579 | int timeout, bite = 0; /* to prevent compiler warning */ | ||
580 | |||
581 | #if 0 | ||
582 | printk("pmu_interrupt: irq %d state %d acr %02X, b %02X data_index %d/%d adb_int_pending %d\n", | ||
583 | irq, pmu_state, (uint) via1[ACR], (uint) via2[B], data_index, data_len, adb_int_pending); | ||
584 | #endif | ||
585 | |||
586 | if (irq == IRQ_MAC_ADB_CL) { /* CB1 interrupt */ | ||
587 | adb_int_pending = 1; | ||
588 | } else if (irq == IRQ_MAC_ADB_SR) { /* SR interrupt */ | ||
589 | if (via2[B] & TACK) { | ||
590 | printk(KERN_DEBUG "PMU: SR_INT but ack still high! (%x)\n", via2[B]); | ||
591 | } | ||
592 | |||
593 | /* if reading grab the byte */ | ||
594 | if ((via1[ACR] & SR_OUT) == 0) bite = via1[SR]; | ||
595 | |||
596 | /* reset TREQ and wait for TACK to go high */ | ||
597 | via2[B] |= TREQ; | ||
598 | timeout = 3200; | ||
599 | while (!(via2[B] & TACK)) { | ||
600 | if (--timeout < 0) { | ||
601 | printk(KERN_ERR "PMU not responding (!ack)\n"); | ||
602 | goto finish; | ||
603 | } | ||
604 | udelay(10); | ||
605 | } | ||
606 | |||
607 | switch (pmu_state) { | ||
608 | case sending: | ||
609 | req = current_req; | ||
610 | if (data_len < 0) { | ||
611 | data_len = req->nbytes - 1; | ||
612 | send_byte(data_len); | ||
613 | break; | ||
614 | } | ||
615 | if (data_index <= data_len) { | ||
616 | send_byte(req->data[data_index++]); | ||
617 | break; | ||
618 | } | ||
619 | req->sent = 1; | ||
620 | data_len = pmu_data_len[req->data[0]][1]; | ||
621 | if (data_len == 0) { | ||
622 | pmu_state = idle; | ||
623 | current_req = req->next; | ||
624 | if (req->reply_expected) | ||
625 | req_awaiting_reply = req; | ||
626 | else | ||
627 | pmu_done(req); | ||
628 | } else { | ||
629 | pmu_state = reading; | ||
630 | data_index = 0; | ||
631 | reply_ptr = req->reply + req->reply_len; | ||
632 | recv_byte(); | ||
633 | } | ||
634 | break; | ||
635 | |||
636 | case intack: | ||
637 | data_index = 0; | ||
638 | data_len = -1; | ||
639 | pmu_state = reading_intr; | ||
640 | reply_ptr = interrupt_data; | ||
641 | recv_byte(); | ||
642 | break; | ||
643 | |||
644 | case reading: | ||
645 | case reading_intr: | ||
646 | if (data_len == -1) { | ||
647 | data_len = bite; | ||
648 | if (bite > 32) | ||
649 | printk(KERN_ERR "PMU: bad reply len %d\n", | ||
650 | bite); | ||
651 | } else { | ||
652 | reply_ptr[data_index++] = bite; | ||
653 | } | ||
654 | if (data_index < data_len) { | ||
655 | recv_byte(); | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | if (pmu_state == reading_intr) { | ||
660 | pmu_handle_data(interrupt_data, data_index, regs); | ||
661 | } else { | ||
662 | req = current_req; | ||
663 | current_req = req->next; | ||
664 | req->reply_len += data_index; | ||
665 | pmu_done(req); | ||
666 | } | ||
667 | pmu_state = idle; | ||
668 | |||
669 | break; | ||
670 | |||
671 | default: | ||
672 | printk(KERN_ERR "pmu_interrupt: unknown state %d?\n", | ||
673 | pmu_state); | ||
674 | } | ||
675 | } | ||
676 | finish: | ||
677 | if (pmu_state == idle) { | ||
678 | if (adb_int_pending) { | ||
679 | pmu_state = intack; | ||
680 | send_byte(PMU_INT_ACK); | ||
681 | adb_int_pending = 0; | ||
682 | } else if (current_req) { | ||
683 | pmu_start(); | ||
684 | } | ||
685 | } | ||
686 | |||
687 | #if 0 | ||
688 | printk("pmu_interrupt: exit state %d acr %02X, b %02X data_index %d/%d adb_int_pending %d\n", | ||
689 | pmu_state, (uint) via1[ACR], (uint) via2[B], data_index, data_len, adb_int_pending); | ||
690 | #endif | ||
691 | return IRQ_HANDLED; | ||
692 | } | ||
693 | |||
694 | static void | ||
695 | pmu_done(struct adb_request *req) | ||
696 | { | ||
697 | req->complete = 1; | ||
698 | if (req->done) | ||
699 | (*req->done)(req); | ||
700 | } | ||
701 | |||
702 | /* Interrupt data could be the result data from an ADB cmd */ | ||
703 | static void | ||
704 | pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) | ||
705 | { | ||
706 | static int show_pmu_ints = 1; | ||
707 | |||
708 | asleep = 0; | ||
709 | if (len < 1) { | ||
710 | adb_int_pending = 0; | ||
711 | return; | ||
712 | } | ||
713 | if (data[0] & PMU_INT_ADB) { | ||
714 | if ((data[0] & PMU_INT_ADB_AUTO) == 0) { | ||
715 | struct adb_request *req = req_awaiting_reply; | ||
716 | if (req == 0) { | ||
717 | printk(KERN_ERR "PMU: extra ADB reply\n"); | ||
718 | return; | ||
719 | } | ||
720 | req_awaiting_reply = 0; | ||
721 | if (len <= 2) | ||
722 | req->reply_len = 0; | ||
723 | else { | ||
724 | memcpy(req->reply, data + 1, len - 1); | ||
725 | req->reply_len = len - 1; | ||
726 | } | ||
727 | pmu_done(req); | ||
728 | } else { | ||
729 | adb_input(data+1, len-1, regs, 1); | ||
730 | } | ||
731 | } else { | ||
732 | if (data[0] == 0x08 && len == 3) { | ||
733 | /* sound/brightness buttons pressed */ | ||
734 | pmu_set_brightness(data[1] >> 3); | ||
735 | set_volume(data[2]); | ||
736 | } else if (show_pmu_ints | ||
737 | && !(data[0] == PMU_INT_TICK && len == 1)) { | ||
738 | int i; | ||
739 | printk(KERN_DEBUG "pmu intr"); | ||
740 | for (i = 0; i < len; ++i) | ||
741 | printk(" %.2x", data[i]); | ||
742 | printk("\n"); | ||
743 | } | ||
744 | } | ||
745 | } | ||
746 | |||
747 | int backlight_level = -1; | ||
748 | int backlight_enabled = 0; | ||
749 | |||
750 | #define LEVEL_TO_BRIGHT(lev) ((lev) < 1? 0x7f: 0x4a - ((lev) << 1)) | ||
751 | |||
752 | static void | ||
753 | pmu_enable_backlight(int on) | ||
754 | { | ||
755 | struct adb_request req; | ||
756 | |||
757 | if (on) { | ||
758 | /* first call: get current backlight value */ | ||
759 | if (backlight_level < 0) { | ||
760 | switch(pmu_kind) { | ||
761 | case PMU_68K_V1: | ||
762 | case PMU_68K_V2: | ||
763 | pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 0x14, 0xe); | ||
764 | while (!req.complete) | ||
765 | pmu_poll(); | ||
766 | printk(KERN_DEBUG "pmu: nvram returned bright: %d\n", (int)req.reply[1]); | ||
767 | backlight_level = req.reply[1]; | ||
768 | break; | ||
769 | default: | ||
770 | backlight_enabled = 0; | ||
771 | return; | ||
772 | } | ||
773 | } | ||
774 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, | ||
775 | LEVEL_TO_BRIGHT(backlight_level)); | ||
776 | while (!req.complete) | ||
777 | pmu_poll(); | ||
778 | } | ||
779 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
780 | PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); | ||
781 | while (!req.complete) | ||
782 | pmu_poll(); | ||
783 | backlight_enabled = on; | ||
784 | } | ||
785 | |||
786 | static void | ||
787 | pmu_set_brightness(int level) | ||
788 | { | ||
789 | int bright; | ||
790 | |||
791 | backlight_level = level; | ||
792 | bright = LEVEL_TO_BRIGHT(level); | ||
793 | if (!backlight_enabled) | ||
794 | return; | ||
795 | if (bright_req_1.complete) | ||
796 | pmu_request(&bright_req_1, NULL, 2, PMU_BACKLIGHT_BRIGHT, | ||
797 | bright); | ||
798 | if (bright_req_2.complete) | ||
799 | pmu_request(&bright_req_2, NULL, 2, PMU_POWER_CTRL, | ||
800 | PMU_POW_BACKLIGHT | (bright < 0x7f ? PMU_POW_ON : PMU_POW_OFF)); | ||
801 | } | ||
802 | |||
803 | void | ||
804 | pmu_enable_irled(int on) | ||
805 | { | ||
806 | struct adb_request req; | ||
807 | |||
808 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED | | ||
809 | (on ? PMU_POW_ON : PMU_POW_OFF)); | ||
810 | while (!req.complete) | ||
811 | pmu_poll(); | ||
812 | } | ||
813 | |||
814 | static void | ||
815 | set_volume(int level) | ||
816 | { | ||
817 | } | ||
818 | |||
819 | int | ||
820 | pmu_present(void) | ||
821 | { | ||
822 | return (pmu_kind != PMU_UNKNOWN); | ||
823 | } | ||
824 | |||
825 | #if 0 /* needs some work for 68K */ | ||
826 | |||
827 | /* | ||
828 | * This struct is used to store config register values for | ||
829 | * PCI devices which may get powered off when we sleep. | ||
830 | */ | ||
831 | static struct pci_save { | ||
832 | u16 command; | ||
833 | u16 cache_lat; | ||
834 | u16 intr; | ||
835 | } *pbook_pci_saves; | ||
836 | static int n_pbook_pci_saves; | ||
837 | |||
838 | static inline void __openfirmware | ||
839 | pbook_pci_save(void) | ||
840 | { | ||
841 | int npci; | ||
842 | struct pci_dev *pd = NULL; | ||
843 | struct pci_save *ps; | ||
844 | |||
845 | npci = 0; | ||
846 | while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) | ||
847 | ++npci; | ||
848 | n_pbook_pci_saves = npci; | ||
849 | if (npci == 0) | ||
850 | return; | ||
851 | ps = (struct pci_save *) kmalloc(npci * sizeof(*ps), GFP_KERNEL); | ||
852 | pbook_pci_saves = ps; | ||
853 | if (ps == NULL) | ||
854 | return; | ||
855 | |||
856 | pd = NULL; | ||
857 | while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
858 | pci_read_config_word(pd, PCI_COMMAND, &ps->command); | ||
859 | pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat); | ||
860 | pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr); | ||
861 | ++ps; | ||
862 | --npci; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | static inline void __openfirmware | ||
867 | pbook_pci_restore(void) | ||
868 | { | ||
869 | u16 cmd; | ||
870 | struct pci_save *ps = pbook_pci_saves; | ||
871 | struct pci_dev *pd = NULL; | ||
872 | int j; | ||
873 | |||
874 | while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
875 | if (ps->command == 0) | ||
876 | continue; | ||
877 | pci_read_config_word(pd, PCI_COMMAND, &cmd); | ||
878 | if ((ps->command & ~cmd) == 0) | ||
879 | continue; | ||
880 | switch (pd->hdr_type) { | ||
881 | case PCI_HEADER_TYPE_NORMAL: | ||
882 | for (j = 0; j < 6; ++j) | ||
883 | pci_write_config_dword(pd, | ||
884 | PCI_BASE_ADDRESS_0 + j*4, | ||
885 | pd->resource[j].start); | ||
886 | pci_write_config_dword(pd, PCI_ROM_ADDRESS, | ||
887 | pd->resource[PCI_ROM_RESOURCE].start); | ||
888 | pci_write_config_word(pd, PCI_CACHE_LINE_SIZE, | ||
889 | ps->cache_lat); | ||
890 | pci_write_config_word(pd, PCI_INTERRUPT_LINE, | ||
891 | ps->intr); | ||
892 | pci_write_config_word(pd, PCI_COMMAND, ps->command); | ||
893 | break; | ||
894 | /* other header types not restored at present */ | ||
895 | } | ||
896 | } | ||
897 | } | ||
898 | |||
899 | /* | ||
900 | * Put the powerbook to sleep. | ||
901 | */ | ||
902 | #define IRQ_ENABLE ((unsigned int *)0xf3000024) | ||
903 | #define MEM_CTRL ((unsigned int *)0xf8000070) | ||
904 | |||
905 | int __openfirmware powerbook_sleep(void) | ||
906 | { | ||
907 | int ret, i, x; | ||
908 | static int save_backlight; | ||
909 | static unsigned int save_irqen; | ||
910 | unsigned long msr; | ||
911 | unsigned int hid0; | ||
912 | unsigned long p, wait; | ||
913 | struct adb_request sleep_req; | ||
914 | |||
915 | /* Notify device drivers */ | ||
916 | ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL); | ||
917 | if (ret & NOTIFY_STOP_MASK) | ||
918 | return -EBUSY; | ||
919 | |||
920 | /* Sync the disks. */ | ||
921 | /* XXX It would be nice to have some way to ensure that | ||
922 | * nobody is dirtying any new buffers while we wait. */ | ||
923 | sys_sync(); | ||
924 | |||
925 | /* Turn off the display backlight */ | ||
926 | save_backlight = backlight_enabled; | ||
927 | if (save_backlight) | ||
928 | pmu_enable_backlight(0); | ||
929 | |||
930 | /* Give the disks a little time to actually finish writing */ | ||
931 | for (wait = jiffies + (HZ/4); time_before(jiffies, wait); ) | ||
932 | mb(); | ||
933 | |||
934 | /* Disable all interrupts except pmu */ | ||
935 | save_irqen = in_le32(IRQ_ENABLE); | ||
936 | for (i = 0; i < 32; ++i) | ||
937 | if (i != vias->intrs[0].line && (save_irqen & (1 << i))) | ||
938 | disable_irq(i); | ||
939 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
940 | |||
941 | /* Save the state of PCI config space for some slots */ | ||
942 | pbook_pci_save(); | ||
943 | |||
944 | /* Set the memory controller to keep the memory refreshed | ||
945 | while we're asleep */ | ||
946 | for (i = 0x403f; i >= 0x4000; --i) { | ||
947 | out_be32(MEM_CTRL, i); | ||
948 | do { | ||
949 | x = (in_be32(MEM_CTRL) >> 16) & 0x3ff; | ||
950 | } while (x == 0); | ||
951 | if (x >= 0x100) | ||
952 | break; | ||
953 | } | ||
954 | |||
955 | /* Ask the PMU to put us to sleep */ | ||
956 | pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); | ||
957 | while (!sleep_req.complete) | ||
958 | mb(); | ||
959 | /* displacement-flush the L2 cache - necessary? */ | ||
960 | for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000) | ||
961 | i = *(volatile int *)p; | ||
962 | asleep = 1; | ||
963 | |||
964 | /* Put the CPU into sleep mode */ | ||
965 | asm volatile("mfspr %0,1008" : "=r" (hid0) :); | ||
966 | hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; | ||
967 | asm volatile("mtspr 1008,%0" : : "r" (hid0)); | ||
968 | local_save_flags(msr); | ||
969 | msr |= MSR_POW | MSR_EE; | ||
970 | local_irq_restore(msr); | ||
971 | udelay(10); | ||
972 | |||
973 | /* OK, we're awake again, start restoring things */ | ||
974 | out_be32(MEM_CTRL, 0x3f); | ||
975 | pbook_pci_restore(); | ||
976 | |||
977 | /* wait for the PMU interrupt sequence to complete */ | ||
978 | while (asleep) | ||
979 | mb(); | ||
980 | |||
981 | /* reenable interrupts */ | ||
982 | for (i = 0; i < 32; ++i) | ||
983 | if (i != vias->intrs[0].line && (save_irqen & (1 << i))) | ||
984 | enable_irq(i); | ||
985 | |||
986 | /* Notify drivers */ | ||
987 | notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL); | ||
988 | |||
989 | /* reenable ADB autopoll */ | ||
990 | pmu_adb_autopoll(adb_dev_map); | ||
991 | |||
992 | /* Turn on the screen backlight, if it was on before */ | ||
993 | if (save_backlight) | ||
994 | pmu_enable_backlight(1); | ||
995 | |||
996 | /* Wait for the hard disk to spin up */ | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | /* | ||
1002 | * Support for /dev/pmu device | ||
1003 | */ | ||
1004 | static int __openfirmware pmu_open(struct inode *inode, struct file *file) | ||
1005 | { | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static ssize_t __openfirmware pmu_read(struct file *file, char *buf, | ||
1010 | size_t count, loff_t *ppos) | ||
1011 | { | ||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static ssize_t __openfirmware pmu_write(struct file *file, const char *buf, | ||
1016 | size_t count, loff_t *ppos) | ||
1017 | { | ||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | /* Note: removed __openfirmware here since it causes link errors */ | ||
1022 | static int /*__openfirmware*/ pmu_ioctl(struct inode * inode, struct file *filp, | ||
1023 | u_int cmd, u_long arg) | ||
1024 | { | ||
1025 | int error; | ||
1026 | __u32 value; | ||
1027 | |||
1028 | switch (cmd) { | ||
1029 | case PMU_IOC_SLEEP: | ||
1030 | return -ENOSYS; | ||
1031 | case PMU_IOC_GET_BACKLIGHT: | ||
1032 | return put_user(backlight_level, (__u32 *)arg); | ||
1033 | case PMU_IOC_SET_BACKLIGHT: | ||
1034 | error = get_user(value, (__u32 *)arg); | ||
1035 | if (!error) | ||
1036 | pmu_set_brightness(value); | ||
1037 | return error; | ||
1038 | case PMU_IOC_GET_MODEL: | ||
1039 | return put_user(pmu_kind, (__u32 *)arg); | ||
1040 | } | ||
1041 | return -EINVAL; | ||
1042 | } | ||
1043 | |||
1044 | static struct file_operations pmu_device_fops = { | ||
1045 | .read = pmu_read, | ||
1046 | .write = pmu_write, | ||
1047 | .ioctl = pmu_ioctl, | ||
1048 | .open = pmu_open, | ||
1049 | }; | ||
1050 | |||
1051 | static struct miscdevice pmu_device = { | ||
1052 | PMU_MINOR, "pmu", &pmu_device_fops | ||
1053 | }; | ||
1054 | |||
1055 | void pmu_device_init(void) | ||
1056 | { | ||
1057 | if (!via) | ||
1058 | return; | ||
1059 | if (misc_register(&pmu_device) < 0) | ||
1060 | printk(KERN_ERR "via-pmu68k: cannot register misc device.\n"); | ||
1061 | } | ||
1062 | #endif /* CONFIG_PMAC_PBOOK */ | ||
1063 | |||