diff options
-rw-r--r-- | drivers/ide/Kconfig | 9 | ||||
-rw-r--r-- | drivers/ide/ppc/pmac.c | 125 | ||||
-rw-r--r-- | drivers/macintosh/Kconfig | 11 | ||||
-rw-r--r-- | drivers/macintosh/Makefile | 1 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu-led.c | 144 |
5 files changed, 164 insertions, 126 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index d633081fa4c5..d1266fe2d1ab 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -774,11 +774,18 @@ config BLK_DEV_IDEDMA_PMAC | |||
774 | performance. | 774 | performance. |
775 | 775 | ||
776 | config BLK_DEV_IDE_PMAC_BLINK | 776 | config BLK_DEV_IDE_PMAC_BLINK |
777 | bool "Blink laptop LED on drive activity" | 777 | bool "Blink laptop LED on drive activity (DEPRECATED)" |
778 | depends on BLK_DEV_IDE_PMAC && ADB_PMU | 778 | depends on BLK_DEV_IDE_PMAC && ADB_PMU |
779 | select ADB_PMU_LED | ||
780 | select LEDS_TRIGGERS | ||
781 | select LEDS_TRIGGER_IDE_DISK | ||
779 | help | 782 | help |
780 | This option enables the use of the sleep LED as a hard drive | 783 | This option enables the use of the sleep LED as a hard drive |
781 | activity LED. | 784 | activity LED. |
785 | This option is deprecated, it only selects ADB_PMU_LED and | ||
786 | LEDS_TRIGGER_IDE_DISK and changes the code in the new led class | ||
787 | device to default to the ide-disk trigger (which should be set | ||
788 | from userspace via sysfs). | ||
782 | 789 | ||
783 | config BLK_DEV_IDE_SWARM | 790 | config BLK_DEV_IDE_SWARM |
784 | tristate "IDE for Sibyte evaluation boards" | 791 | tristate "IDE for Sibyte evaluation boards" |
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index ffca8b63ee79..e8ef3455ec35 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
@@ -421,107 +421,6 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive); | |||
421 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ | 421 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ |
422 | 422 | ||
423 | /* | 423 | /* |
424 | * Below is the code for blinking the laptop LED along with hard | ||
425 | * disk activity. | ||
426 | */ | ||
427 | |||
428 | #ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK | ||
429 | |||
430 | /* Set to 50ms minimum led-on time (also used to limit frequency | ||
431 | * of requests sent to the PMU | ||
432 | */ | ||
433 | #define PMU_HD_BLINK_TIME (HZ/50) | ||
434 | |||
435 | static struct adb_request pmu_blink_on, pmu_blink_off; | ||
436 | static spinlock_t pmu_blink_lock; | ||
437 | static unsigned long pmu_blink_stoptime; | ||
438 | static int pmu_blink_ledstate; | ||
439 | static struct timer_list pmu_blink_timer; | ||
440 | static int pmu_ide_blink_enabled; | ||
441 | |||
442 | |||
443 | static void | ||
444 | pmu_hd_blink_timeout(unsigned long data) | ||
445 | { | ||
446 | unsigned long flags; | ||
447 | |||
448 | spin_lock_irqsave(&pmu_blink_lock, flags); | ||
449 | |||
450 | /* We may have been triggered again in a racy way, check | ||
451 | * that we really want to switch it off | ||
452 | */ | ||
453 | if (time_after(pmu_blink_stoptime, jiffies)) | ||
454 | goto done; | ||
455 | |||
456 | /* Previous req. not complete, try 100ms more */ | ||
457 | if (pmu_blink_off.complete == 0) | ||
458 | mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME); | ||
459 | else if (pmu_blink_ledstate) { | ||
460 | pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0); | ||
461 | pmu_blink_ledstate = 0; | ||
462 | } | ||
463 | done: | ||
464 | spin_unlock_irqrestore(&pmu_blink_lock, flags); | ||
465 | } | ||
466 | |||
467 | static void | ||
468 | pmu_hd_kick_blink(void *data, int rw) | ||
469 | { | ||
470 | unsigned long flags; | ||
471 | |||
472 | pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME; | ||
473 | wmb(); | ||
474 | mod_timer(&pmu_blink_timer, pmu_blink_stoptime); | ||
475 | /* Fast path when LED is already ON */ | ||
476 | if (pmu_blink_ledstate == 1) | ||
477 | return; | ||
478 | spin_lock_irqsave(&pmu_blink_lock, flags); | ||
479 | if (pmu_blink_on.complete && !pmu_blink_ledstate) { | ||
480 | pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1); | ||
481 | pmu_blink_ledstate = 1; | ||
482 | } | ||
483 | spin_unlock_irqrestore(&pmu_blink_lock, flags); | ||
484 | } | ||
485 | |||
486 | static int | ||
487 | pmu_hd_blink_init(void) | ||
488 | { | ||
489 | struct device_node *dt; | ||
490 | const char *model; | ||
491 | |||
492 | /* Currently, I only enable this feature on KeyLargo based laptops, | ||
493 | * older laptops may support it (at least heathrow/paddington) but | ||
494 | * I don't feel like loading those venerable old machines with so | ||
495 | * much additional interrupt & PMU activity... | ||
496 | */ | ||
497 | if (pmu_get_model() != PMU_KEYLARGO_BASED) | ||
498 | return 0; | ||
499 | |||
500 | dt = of_find_node_by_path("/"); | ||
501 | if (dt == NULL) | ||
502 | return 0; | ||
503 | model = (const char *)get_property(dt, "model", NULL); | ||
504 | if (model == NULL) | ||
505 | return 0; | ||
506 | if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && | ||
507 | strncmp(model, "iBook", strlen("iBook")) != 0) { | ||
508 | of_node_put(dt); | ||
509 | return 0; | ||
510 | } | ||
511 | of_node_put(dt); | ||
512 | |||
513 | pmu_blink_on.complete = 1; | ||
514 | pmu_blink_off.complete = 1; | ||
515 | spin_lock_init(&pmu_blink_lock); | ||
516 | init_timer(&pmu_blink_timer); | ||
517 | pmu_blink_timer.function = pmu_hd_blink_timeout; | ||
518 | |||
519 | return 1; | ||
520 | } | ||
521 | |||
522 | #endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ | ||
523 | |||
524 | /* | ||
525 | * N.B. this can't be an initfunc, because the media-bay task can | 424 | * N.B. this can't be an initfunc, because the media-bay task can |
526 | * call ide_[un]register at any time. | 425 | * call ide_[un]register at any time. |
527 | */ | 426 | */ |
@@ -1192,23 +1091,6 @@ pmac_ide_do_suspend(ide_hwif_t *hwif) | |||
1192 | pmif->timings[0] = 0; | 1091 | pmif->timings[0] = 0; |
1193 | pmif->timings[1] = 0; | 1092 | pmif->timings[1] = 0; |
1194 | 1093 | ||
1195 | #ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK | ||
1196 | /* Note: This code will be called for every hwif, thus we'll | ||
1197 | * try several time to stop the LED blinker timer, but that | ||
1198 | * should be harmless | ||
1199 | */ | ||
1200 | if (pmu_ide_blink_enabled) { | ||
1201 | unsigned long flags; | ||
1202 | |||
1203 | /* Make sure we don't hit the PMU blink */ | ||
1204 | spin_lock_irqsave(&pmu_blink_lock, flags); | ||
1205 | if (pmu_blink_ledstate) | ||
1206 | del_timer(&pmu_blink_timer); | ||
1207 | pmu_blink_ledstate = 0; | ||
1208 | spin_unlock_irqrestore(&pmu_blink_lock, flags); | ||
1209 | } | ||
1210 | #endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ | ||
1211 | |||
1212 | disable_irq(pmif->irq); | 1094 | disable_irq(pmif->irq); |
1213 | 1095 | ||
1214 | /* The media bay will handle itself just fine */ | 1096 | /* The media bay will handle itself just fine */ |
@@ -1376,13 +1258,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) | |||
1376 | hwif->selectproc = pmac_ide_selectproc; | 1258 | hwif->selectproc = pmac_ide_selectproc; |
1377 | hwif->speedproc = pmac_ide_tune_chipset; | 1259 | hwif->speedproc = pmac_ide_tune_chipset; |
1378 | 1260 | ||
1379 | #ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK | ||
1380 | pmu_ide_blink_enabled = pmu_hd_blink_init(); | ||
1381 | |||
1382 | if (pmu_ide_blink_enabled) | ||
1383 | hwif->led_act = pmu_hd_kick_blink; | ||
1384 | #endif | ||
1385 | |||
1386 | printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", | 1261 | printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", |
1387 | hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, | 1262 | hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, |
1388 | pmif->mediabay ? " (mediabay)" : "", hwif->irq); | 1263 | pmif->mediabay ? " (mediabay)" : "", hwif->irq); |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 37cd6ee4586b..062dac26f2ae 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -78,6 +78,17 @@ config ADB_PMU | |||
78 | this device; you should do so if your machine is one of those | 78 | this device; you should do so if your machine is one of those |
79 | mentioned above. | 79 | mentioned above. |
80 | 80 | ||
81 | config ADB_PMU_LED | ||
82 | bool "Support for the Power/iBook front LED" | ||
83 | depends on ADB_PMU | ||
84 | select LEDS_CLASS | ||
85 | help | ||
86 | Support the front LED on Power/iBooks as a generic LED that can | ||
87 | be triggered by any of the supported triggers. To get the | ||
88 | behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this | ||
89 | and the ide-disk LED trigger and configure appropriately through | ||
90 | sysfs. | ||
91 | |||
81 | config PMAC_SMU | 92 | config PMAC_SMU |
82 | bool "Support for SMU based PowerMacs" | 93 | bool "Support for SMU based PowerMacs" |
83 | depends on PPC_PMAC64 | 94 | depends on PPC_PMAC64 |
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 45a268f8047e..b53d45f87b0b 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o | |||
12 | obj-$(CONFIG_ANSLCD) += ans-lcd.o | 12 | obj-$(CONFIG_ANSLCD) += ans-lcd.o |
13 | 13 | ||
14 | obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o | 14 | obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o |
15 | obj-$(CONFIG_ADB_PMU_LED) += via-pmu-led.o | ||
15 | obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o | 16 | obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o |
16 | obj-$(CONFIG_ADB_CUDA) += via-cuda.o | 17 | obj-$(CONFIG_ADB_CUDA) += via-cuda.o |
17 | obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o | 18 | obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o |
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c new file mode 100644 index 000000000000..af8375ed0f5e --- /dev/null +++ b/drivers/macintosh/via-pmu-led.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * via-pmu LED class device | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
14 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
15 | * details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/leds.h> | ||
26 | #include <linux/adb.h> | ||
27 | #include <linux/pmu.h> | ||
28 | #include <asm/prom.h> | ||
29 | |||
30 | static spinlock_t pmu_blink_lock; | ||
31 | static struct adb_request pmu_blink_req; | ||
32 | /* -1: no change, 0: request off, 1: request on */ | ||
33 | static int requested_change; | ||
34 | static int sleeping; | ||
35 | |||
36 | static void pmu_req_done(struct adb_request * req) | ||
37 | { | ||
38 | unsigned long flags; | ||
39 | |||
40 | spin_lock_irqsave(&pmu_blink_lock, flags); | ||
41 | /* if someone requested a change in the meantime | ||
42 | * (we only see the last one which is fine) | ||
43 | * then apply it now */ | ||
44 | if (requested_change != -1 && !sleeping) | ||
45 | pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); | ||
46 | /* reset requested change */ | ||
47 | requested_change = -1; | ||
48 | spin_unlock_irqrestore(&pmu_blink_lock, flags); | ||
49 | } | ||
50 | |||
51 | static void pmu_led_set(struct led_classdev *led_cdev, | ||
52 | enum led_brightness brightness) | ||
53 | { | ||
54 | unsigned long flags; | ||
55 | |||
56 | spin_lock_irqsave(&pmu_blink_lock, flags); | ||
57 | switch (brightness) { | ||
58 | case LED_OFF: | ||
59 | requested_change = 0; | ||
60 | break; | ||
61 | case LED_FULL: | ||
62 | requested_change = 1; | ||
63 | break; | ||
64 | default: | ||
65 | goto out; | ||
66 | break; | ||
67 | } | ||
68 | /* if request isn't done, then don't do anything */ | ||
69 | if (pmu_blink_req.complete && !sleeping) | ||
70 | pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); | ||
71 | out: | ||
72 | spin_unlock_irqrestore(&pmu_blink_lock, flags); | ||
73 | } | ||
74 | |||
75 | static struct led_classdev pmu_led = { | ||
76 | .name = "pmu-front-led", | ||
77 | #ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK | ||
78 | .default_trigger = "ide-disk", | ||
79 | #endif | ||
80 | .brightness_set = pmu_led_set, | ||
81 | }; | ||
82 | |||
83 | #ifdef CONFIG_PM | ||
84 | static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) | ||
85 | { | ||
86 | unsigned long flags; | ||
87 | |||
88 | spin_lock_irqsave(&pmu_blink_lock, flags); | ||
89 | |||
90 | switch (when) { | ||
91 | case PBOOK_SLEEP_REQUEST: | ||
92 | sleeping = 1; | ||
93 | break; | ||
94 | case PBOOK_WAKE: | ||
95 | sleeping = 0; | ||
96 | break; | ||
97 | default: | ||
98 | /* do nothing */ | ||
99 | break; | ||
100 | } | ||
101 | spin_unlock_irqrestore(&pmu_blink_lock, flags); | ||
102 | |||
103 | return PBOOK_SLEEP_OK; | ||
104 | } | ||
105 | |||
106 | static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { | ||
107 | .notifier_call = pmu_led_sleep_call, | ||
108 | }; | ||
109 | #endif | ||
110 | |||
111 | static int __init via_pmu_led_init(void) | ||
112 | { | ||
113 | struct device_node *dt; | ||
114 | const char *model; | ||
115 | |||
116 | /* only do this on keylargo based models */ | ||
117 | if (pmu_get_model() != PMU_KEYLARGO_BASED) | ||
118 | return -ENODEV; | ||
119 | |||
120 | dt = of_find_node_by_path("/"); | ||
121 | if (dt == NULL) | ||
122 | return -ENODEV; | ||
123 | model = (const char *)get_property(dt, "model", NULL); | ||
124 | if (model == NULL) | ||
125 | return -ENODEV; | ||
126 | if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && | ||
127 | strncmp(model, "iBook", strlen("iBook")) != 0) { | ||
128 | of_node_put(dt); | ||
129 | /* ignore */ | ||
130 | return -ENODEV; | ||
131 | } | ||
132 | of_node_put(dt); | ||
133 | |||
134 | spin_lock_init(&pmu_blink_lock); | ||
135 | /* no outstanding req */ | ||
136 | pmu_blink_req.complete = 1; | ||
137 | pmu_blink_req.done = pmu_req_done; | ||
138 | #ifdef CONFIG_PM | ||
139 | pmu_register_sleep_notifier(&via_pmu_led_sleep_notif); | ||
140 | #endif | ||
141 | return led_classdev_register(NULL, &pmu_led); | ||
142 | } | ||
143 | |||
144 | late_initcall(via_pmu_led_init); | ||