Commit 70c3967d4f8029f3d53323a9f0490df61d8cb77d

Authored by Johannes Berg
Committed by Paul Mackerras
1 parent 266bee8869

[POWERPC] Convert powermac ide blink to new led infrastructure

This patch removes the old pmac ide led blink code and
adds generic LED subsystem support for the LED.

It maintains backward compatibility with the old
BLK_DEV_IDE_PMAC_BLINK Kconfig option which now
simply selects the new code and influences the
default trigger.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>

Showing 5 changed files with 164 additions and 126 deletions Side-by-side Diff

... ... @@ -774,11 +774,18 @@
774 774 performance.
775 775  
776 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 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 782 help
780 783 This option enables the use of the sleep LED as a hard drive
781 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 790 config BLK_DEV_IDE_SWARM
784 791 tristate "IDE for Sibyte evaluation boards"
drivers/ide/ppc/pmac.c
... ... @@ -421,107 +421,6 @@
421 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 424 * N.B. this can't be an initfunc, because the media-bay task can
526 425 * call ide_[un]register at any time.
527 426 */
... ... @@ -1192,23 +1091,6 @@
1192 1091 pmif->timings[0] = 0;
1193 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 1094 disable_irq(pmif->irq);
1213 1095  
1214 1096 /* The media bay will handle itself just fine */
... ... @@ -1375,13 +1257,6 @@
1375 1257 else
1376 1258 hwif->selectproc = pmac_ide_selectproc;
1377 1259 hwif->speedproc = pmac_ide_tune_chipset;
1378   -
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 1260  
1386 1261 printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
1387 1262 hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
drivers/macintosh/Kconfig
... ... @@ -78,6 +78,17 @@
78 78 this device; you should do so if your machine is one of those
79 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 92 config PMAC_SMU
82 93 bool "Support for SMU based PowerMacs"
83 94 depends on PPC_PMAC64
drivers/macintosh/Makefile
... ... @@ -12,6 +12,7 @@
12 12 obj-$(CONFIG_ANSLCD) += ans-lcd.o
13 13  
14 14 obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o
  15 +obj-$(CONFIG_ADB_PMU_LED) += via-pmu-led.o
15 16 obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o
16 17 obj-$(CONFIG_ADB_CUDA) += via-cuda.o
17 18 obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o
drivers/macintosh/via-pmu-led.c
  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);