diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/ide/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/ide/ppc/pmac.c | 125 | ||||
| -rw-r--r-- | drivers/macintosh/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/macintosh/Makefile | 1 | ||||
| -rw-r--r-- | drivers/macintosh/via-pmu-led.c | 144 |
5 files changed, 165 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..54f3f6b94efc 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
| @@ -78,6 +78,18 @@ 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 NEW_LEDS | ||
| 85 | select LEDS_CLASS | ||
| 86 | help | ||
| 87 | Support the front LED on Power/iBooks as a generic LED that can | ||
| 88 | be triggered by any of the supported triggers. To get the | ||
| 89 | behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this | ||
| 90 | and the ide-disk LED trigger and configure appropriately through | ||
| 91 | sysfs. | ||
| 92 | |||
| 81 | config PMAC_SMU | 93 | config PMAC_SMU |
| 82 | bool "Support for SMU based PowerMacs" | 94 | bool "Support for SMU based PowerMacs" |
| 83 | depends on PPC_PMAC64 | 95 | 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); | ||
