diff options
Diffstat (limited to 'drivers/macintosh')
27 files changed, 998 insertions, 363 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index ccf5df44cde..d5d649f5ccd 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -78,6 +78,27 @@ config ADB_PMU this device; you should do so if your machine is one of those mentioned above. +config ADB_PMU_LED + bool "Support for the Power/iBook front LED" + depends on ADB_PMU + select NEW_LEDS + select LEDS_CLASS + help + Support the front LED on Power/iBooks as a generic LED that can + be triggered by any of the supported triggers. To get the + behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this + and the ide-disk LED trigger and configure appropriately through + sysfs. + +config ADB_PMU_LED_IDE + bool "Use front LED as IDE LED by default" + depends on ADB_PMU_LED + select LEDS_TRIGGERS + select LEDS_TRIGGER_IDE_DISK + help + This option makes the front LED default to the IDE trigger + so that it blinks on IDE activity. + config PMAC_SMU bool "Support for SMU based PowerMacs" depends on PPC_PMAC64 @@ -88,7 +109,7 @@ config PMAC_SMU config PMAC_APM_EMU tristate "APM emulation" - depends on PPC_PMAC && PPC32 && PM + depends on PPC_PMAC && PPC32 && PM && ADB_PMU config PMAC_MEDIABAY bool "Support PowerBook hotswap media bay" @@ -99,17 +120,23 @@ config PMAC_MEDIABAY devices are not fully supported in the bay as I never had one to try with -# made a separate option since backlight may end up beeing used -# on non-powerbook machines (but only on PMU based ones AFAIK) config PMAC_BACKLIGHT bool "Backlight control for LCD screens" - depends on ADB_PMU && (BROKEN || !PPC64) + depends on ADB_PMU && FB = y && (BROKEN || !PPC64) + select FB_BACKLIGHT + help + Say Y here to enable Macintosh specific extensions of the generic + backlight code. With this enabled, the brightness keys on older + PowerBooks will be enabled so you can change the screen brightness. + Newer models should use an userspace daemon like pbbuttonsd. + +config PMAC_BACKLIGHT_LEGACY + bool "Provide legacy ioctl's on /dev/pmu for the backlight" + depends on PMAC_BACKLIGHT && (BROKEN || !PPC64) help - Say Y here to build in code to manage the LCD backlight on a - Macintosh PowerBook. With this code, the backlight will be turned - on and off appropriately on power-management and lid-open/lid-closed - events; also, the PowerBook button device will be enabled so you can - change the screen brightness. + Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for + programs which use this old interface. New and updated programs + should use the backlight classes in sysfs. config ADB_MACIO bool "Include MacIO (CHRP) ADB driver" diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 6081acdea40..b53d45f87b0 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -11,7 +11,9 @@ obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_ANSLCD) += ans-lcd.o -obj-$(CONFIG_ADB_PMU) += via-pmu.o +obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o +obj-$(CONFIG_ADB_PMU_LED) += via-pmu-led.o +obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o obj-$(CONFIG_ADB_CUDA) += via-cuda.o obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o obj-$(CONFIG_PMAC_SMU) += smu.o diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 259fd8973ce..360f93f6fcd 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -16,7 +16,6 @@ * - move bus probe to a kernel thread */ -#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> @@ -36,7 +35,6 @@ #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/device.h> -#include <linux/devfs_fs_kernel.h> #include <asm/uaccess.h> #include <asm/semaphore.h> @@ -904,8 +902,6 @@ adbdev_init(void) return; } - devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR, "adb"); - adb_dev_class = class_create(THIS_MODULE, "adb"); if (IS_ERR(adb_dev_class)) return; diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 394334ec576..efd51e01c06 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -34,7 +34,6 @@ * Move to syfs */ -#include <linux/config.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> @@ -47,11 +46,8 @@ #include <asm/machdep.h> #ifdef CONFIG_PPC_PMAC -#include <asm/pmac_feature.h> -#endif - -#ifdef CONFIG_PMAC_BACKLIGHT #include <asm/backlight.h> +#include <asm/pmac_feature.h> #endif MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); @@ -179,7 +175,7 @@ u8 adb_to_linux_keycodes[128] = { /* 0x65 */ KEY_F9, /* 67 */ /* 0x66 */ KEY_HANJA, /* 123 */ /* 0x67 */ KEY_F11, /* 87 */ - /* 0x68 */ KEY_HANGUEL, /* 122 */ + /* 0x68 */ KEY_HANGEUL, /* 122 */ /* 0x69 */ KEY_SYSRQ, /* 99 */ /* 0x6a */ 0, /* 0x6b */ KEY_SCROLLLOCK, /* 70 */ @@ -238,11 +234,6 @@ static struct adb_ids keyboard_ids; static struct adb_ids mouse_ids; static struct adb_ids buttons_ids; -#ifdef CONFIG_PMAC_BACKLIGHT -/* Exported to via-pmu.c */ -int disable_kernel_backlight = 0; -#endif /* CONFIG_PMAC_BACKLIGHT */ - /* Kind of keyboard, see Apple technote 1152 */ #define ADB_KEYBOARD_UNKNOWN 0 #define ADB_KEYBOARD_ANSI 0x0100 @@ -503,9 +494,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto case 0x1f: /* Powerbook button device */ { int down = (data[1] == (data[1] & 0xf)); -#ifdef CONFIG_PMAC_BACKLIGHT - int backlight = get_backlight_level(); -#endif + /* * XXX: Where is the contrast control for the passive? * -- Cort @@ -530,29 +519,17 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto case 0xa: /* brightness decrease */ #ifdef CONFIG_PMAC_BACKLIGHT - if (!disable_kernel_backlight) { - if (down && backlight >= 0) { - if (backlight > BACKLIGHT_OFF) - set_backlight_level(backlight-1); - else - set_backlight_level(BACKLIGHT_OFF); - } - } -#endif /* CONFIG_PMAC_BACKLIGHT */ + if (down) + pmac_backlight_key_down(); +#endif input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); break; case 0x9: /* brightness increase */ #ifdef CONFIG_PMAC_BACKLIGHT - if (!disable_kernel_backlight) { - if (down && backlight >= 0) { - if (backlight < BACKLIGHT_MAX) - set_backlight_level(backlight+1); - else - set_backlight_level(BACKLIGHT_MAX); - } - } -#endif /* CONFIG_PMAC_BACKLIGHT */ + if (down) + pmac_backlight_key_up(); +#endif input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); break; diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c index e5a2bbf9939..1293876a2eb 100644 --- a/drivers/macintosh/apm_emu.c +++ b/drivers/macintosh/apm_emu.c @@ -18,7 +18,6 @@ * */ -#include <linux/config.h> #include <linux/module.h> #include <linux/poll.h> diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c index a66636116f0..6b129eef798 100644 --- a/drivers/macintosh/mac_hid.c +++ b/drivers/macintosh/mac_hid.c @@ -8,7 +8,6 @@ * This file will soon be removed in favor of an uinput userspace tool. */ -#include <linux/config.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/sysctl.h> diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index 314fc0830d9..4b08852c35e 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -90,22 +90,12 @@ int macio_init(void) { struct device_node *adbs; struct resource r; + unsigned int irq; adbs = find_compatible_devices("adb", "chrp,adb0"); if (adbs == 0) return -ENXIO; -#if 0 - { int i = 0; - - printk("macio_adb_init: node = %p, addrs =", adbs->node); - while(!of_address_to_resource(adbs, i, &r)) - printk(" %x(%x)", r.start, r.end - r.start); - printk(", intrs ="); - for (i = 0; i < adbs->n_intrs; ++i) - printk(" %x", adbs->intrs[i].line); - printk("\n"); } -#endif if (of_address_to_resource(adbs, 0, &r)) return -ENXIO; adb = ioremap(r.start, sizeof(struct adb_regs)); @@ -117,10 +107,9 @@ int macio_init(void) out_8(&adb->active_lo.r, 0xff); out_8(&adb->autopoll.r, APE); - if (request_irq(adbs->intrs[0].line, macio_adb_interrupt, - 0, "ADB", (void *)0)) { - printk(KERN_ERR "ADB: can't get irq %d\n", - adbs->intrs[0].line); + irq = irq_of_parse_and_map(adbs, 0); + if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) { + printk(KERN_ERR "ADB: can't get irq %d\n", irq); return -EAGAIN; } out_8(&adb->intr_enb.r, DFB | TAG); diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 431bd37225a..d5621606754 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -17,7 +17,6 @@ * sub-devices. */ -#include <linux/config.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/pci.h> @@ -140,7 +139,9 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, { struct macio_dev * macio_dev; struct of_device * of; - char *scratch, *compat, *compat2; + char *scratch; + const char *compat, *compat2; + int i = 0; int length, cplen, cplen2, seen = 0; @@ -174,7 +175,7 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, * it's not really legal to split it out with commas. We split it * up using a number of environment variables instead. */ - compat = (char *) get_property(of->node, "compatible", &cplen); + compat = get_property(of->node, "compatible", &cplen); compat2 = compat; cplen2= cplen; while (compat && cplen > 0) { @@ -281,75 +282,128 @@ static void macio_release_dev(struct device *dev) static int macio_resource_quirks(struct device_node *np, struct resource *res, int index) { - if (res->flags & IORESOURCE_MEM) { - /* Grand Central has too large resource 0 on some machines */ - if (index == 0 && !strcmp(np->name, "gc")) - res->end = res->start + 0x1ffff; + /* Only quirks for memory resources for now */ + if ((res->flags & IORESOURCE_MEM) == 0) + return 0; - /* Airport has bogus resource 2 */ - if (index >= 2 && !strcmp(np->name, "radio")) - return 1; + /* Grand Central has too large resource 0 on some machines */ + if (index == 0 && !strcmp(np->name, "gc")) + res->end = res->start + 0x1ffff; + + /* Airport has bogus resource 2 */ + if (index >= 2 && !strcmp(np->name, "radio")) + return 1; #ifndef CONFIG_PPC64 - /* DBDMAs may have bogus sizes */ - if ((res->start & 0x0001f000) == 0x00008000) - res->end = res->start + 0xff; + /* DBDMAs may have bogus sizes */ + if ((res->start & 0x0001f000) == 0x00008000) + res->end = res->start + 0xff; #endif /* CONFIG_PPC64 */ - /* ESCC parent eats child resources. We could have added a - * level of hierarchy, but I don't really feel the need - * for it - */ - if (!strcmp(np->name, "escc")) - return 1; - - /* ESCC has bogus resources >= 3 */ - if (index >= 3 && !(strcmp(np->name, "ch-a") && - strcmp(np->name, "ch-b"))) - return 1; - - /* Media bay has too many resources, keep only first one */ - if (index > 0 && !strcmp(np->name, "media-bay")) - return 1; - - /* Some older IDE resources have bogus sizes */ - if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && - strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { - if (index == 0 && (res->end - res->start) > 0xfff) - res->end = res->start + 0xfff; - if (index == 1 && (res->end - res->start) > 0xff) - res->end = res->start + 0xff; - } + /* ESCC parent eats child resources. We could have added a + * level of hierarchy, but I don't really feel the need + * for it + */ + if (!strcmp(np->name, "escc")) + return 1; + + /* ESCC has bogus resources >= 3 */ + if (index >= 3 && !(strcmp(np->name, "ch-a") && + strcmp(np->name, "ch-b"))) + return 1; + + /* Media bay has too many resources, keep only first one */ + if (index > 0 && !strcmp(np->name, "media-bay")) + return 1; + + /* Some older IDE resources have bogus sizes */ + if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && + strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { + if (index == 0 && (res->end - res->start) > 0xfff) + res->end = res->start + 0xfff; + if (index == 1 && (res->end - res->start) > 0xff) + res->end = res->start + 0xff; } return 0; } +static void macio_create_fixup_irq(struct macio_dev *dev, int index, + unsigned int line) +{ + unsigned int irq; -static void macio_setup_interrupts(struct macio_dev *dev) + irq = irq_create_mapping(NULL, line); + if (irq != NO_IRQ) { + dev->interrupt[index].start = irq; + dev->interrupt[index].flags = IORESOURCE_IRQ; + dev->interrupt[index].name = dev->ofdev.dev.bus_id; + } + if (dev->n_interrupts <= index) + dev->n_interrupts = index + 1; +} + +static void macio_add_missing_resources(struct macio_dev *dev) { struct device_node *np = dev->ofdev.node; - int i,j; + unsigned int irq_base; + + /* Gatwick has some missing interrupts on child nodes */ + if (dev->bus->chip->type != macio_gatwick) + return; - /* For now, we use pre-parsed entries in the device-tree for - * interrupt routing and addresses, but we should change that - * to dynamically parsed entries and so get rid of most of the - * clutter in struct device_node + /* irq_base is always 64 on gatwick. I have no cleaner way to get + * that value from here at this point */ - for (i = j = 0; i < np->n_intrs; i++) { + irq_base = 64; + + /* Fix SCC */ + if (strcmp(np->name, "ch-a") == 0) { + macio_create_fixup_irq(dev, 0, 15 + irq_base); + macio_create_fixup_irq(dev, 1, 4 + irq_base); + macio_create_fixup_irq(dev, 2, 5 + irq_base); + printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n"); + } + + /* Fix media-bay */ + if (strcmp(np->name, "media-bay") == 0) { + macio_create_fixup_irq(dev, 0, 29 + irq_base); + printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n"); + } + + /* Fix left media bay childs */ + if (dev->media_bay != NULL && strcmp(np->name, "floppy") == 0) { + macio_create_fixup_irq(dev, 0, 19 + irq_base); + macio_create_fixup_irq(dev, 1, 1 + irq_base); + printk(KERN_INFO "macio: fixed left floppy irqs\n"); + } + if (dev->media_bay != NULL && strcasecmp(np->name, "ata4") == 0) { + macio_create_fixup_irq(dev, 0, 14 + irq_base); + macio_create_fixup_irq(dev, 0, 3 + irq_base); + printk(KERN_INFO "macio: fixed left ide irqs\n"); + } +} + +static void macio_setup_interrupts(struct macio_dev *dev) +{ + struct device_node *np = dev->ofdev.node; + unsigned int irq; + int i = 0, j = 0; + + for (;;) { struct resource *res = &dev->interrupt[j]; if (j >= MACIO_DEV_COUNT_IRQS) break; - res->start = np->intrs[i].line; - res->flags = IORESOURCE_IO; - if (np->intrs[j].sense) - res->flags |= IORESOURCE_IRQ_LOWLEVEL; - else - res->flags |= IORESOURCE_IRQ_HIGHEDGE; + irq = irq_of_parse_and_map(np, i++); + if (irq == NO_IRQ) + break; + res->start = irq; + res->flags = IORESOURCE_IRQ; res->name = dev->ofdev.dev.bus_id; - if (macio_resource_quirks(np, res, i)) + if (macio_resource_quirks(np, res, i - 1)) { memset(res, 0, sizeof(struct resource)); - else + continue; + } else j++; } dev->n_interrupts = j; @@ -402,7 +456,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct resource *parent_res) { struct macio_dev *dev; - u32 *reg; + const u32 *reg; if (np == NULL) return NULL; @@ -428,16 +482,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, /* MacIO itself has a different reg, we use it's PCI base */ if (np == chip->of_node) { - sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", + sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, #ifdef CONFIG_PCI - pci_resource_start(chip->lbus.pdev, 0), + (unsigned int)pci_resource_start(chip->lbus.pdev, 0), #else 0, /* NuBus may want to do something better here */ #endif MAX_NODE_NAME_SIZE, np->name); } else { - reg = (u32 *)get_property(np, "reg", NULL); + reg = get_property(np, "reg", NULL); sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); @@ -446,6 +500,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, /* Setup interrupts & resources */ macio_setup_interrupts(dev); macio_setup_resources(dev, parent_res); + macio_add_missing_resources(dev); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) { diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 7f7d4eaca87..8566bdfdd4b 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/stat.h> #include <asm/macio.h> @@ -17,12 +16,12 @@ static ssize_t compatible_show (struct device *dev, struct device_attribute *attr, char *buf) { struct of_device *of; - char *compat; + const char *compat; int cplen; int length = 0; of = &to_macio_device (dev)->ofdev; - compat = (char *) get_property(of->node, "compatible", &cplen); + compat = get_property(of->node, "compatible", &cplen); if (!compat) { *buf = '\0'; return 0; @@ -43,12 +42,12 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, char *buf) { struct of_device *of; - char *compat; + const char *compat; int cplen; int length; of = &to_macio_device (dev)->ofdev; - compat = (char *) get_property (of->node, "compatible", &cplen); + compat = get_property(of->node, "compatible", &cplen); if (!compat) compat = "", cplen = 1; length = sprintf (buf, "of:N%sT%s", of->node->name, of->node->type); buf += length; diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 53c1c790941..0acf2f7fd9d 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -10,7 +10,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index f4516ca7aa3..090e40fc501 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -19,7 +19,6 @@ * the userland interface */ -#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/device.h> @@ -76,9 +75,11 @@ struct smu_device { struct of_device *of_dev; int doorbell; /* doorbell gpio */ u32 __iomem *db_buf; /* doorbell buffer */ - int db_irq; + struct device_node *db_node; + unsigned int db_irq; int msg; - int msg_irq; + struct device_node *msg_node; + unsigned int msg_irq; struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ u32 cmd_buf_abs; /* command buffer absolute */ struct list_head cmd_list; @@ -94,6 +95,7 @@ struct smu_device { */ static struct smu_device *smu; static DEFINE_MUTEX(smu_part_access); +static int smu_irq_inited; static void smu_i2c_retry(unsigned long data); @@ -258,6 +260,10 @@ int smu_queue_cmd(struct smu_cmd *cmd) smu_start_cmd(); spin_unlock_irqrestore(&smu->lock, flags); + /* Workaround for early calls when irq isn't available */ + if (!smu_irq_inited || smu->db_irq == NO_IRQ) + smu_spinwait_cmd(cmd); + return 0; } EXPORT_SYMBOL(smu_queue_cmd); @@ -448,7 +454,7 @@ EXPORT_SYMBOL(smu_present); int __init smu_init (void) { struct device_node *np; - u32 *data; + const u32 *data; np = of_find_node_by_type(NULL, "smu"); if (np == NULL) @@ -479,14 +485,15 @@ int __init smu_init (void) smu->cmd_buf_abs = (u32)smu_cmdbuf_abs; smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs); - np = of_find_node_by_name(NULL, "smu-doorbell"); - if (np == NULL) { + smu->db_node = of_find_node_by_name(NULL, "smu-doorbell"); + if (smu->db_node == NULL) { printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); goto fail; } - data = (u32 *)get_property(np, "reg", NULL); + data = get_property(smu->db_node, "reg", NULL); if (data == NULL) { - of_node_put(np); + of_node_put(smu->db_node); + smu->db_node = NULL; printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); goto fail; } @@ -498,27 +505,21 @@ int __init smu_init (void) smu->doorbell = *data; if (smu->doorbell < 0x50) smu->doorbell += 0x50; - if (np->n_intrs > 0) - smu->db_irq = np->intrs[0].line; - - of_node_put(np); /* Now look for the smu-interrupt GPIO */ do { - np = of_find_node_by_name(NULL, "smu-interrupt"); - if (np == NULL) + smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt"); + if (smu->msg_node == NULL) break; - data = (u32 *)get_property(np, "reg", NULL); + data = get_property(smu->msg_node, "reg", NULL); if (data == NULL) { - of_node_put(np); + of_node_put(smu->msg_node); + smu->msg_node = NULL; break; } smu->msg = *data; if (smu->msg < 0x50) smu->msg += 0x50; - if (np->n_intrs > 0) - smu->msg_irq = np->intrs[0].line; - of_node_put(np); } while(0); /* Doorbell buffer is currently hard-coded, I didn't find a proper @@ -550,13 +551,26 @@ static int smu_late_init(void) smu->i2c_timer.function = smu_i2c_retry; smu->i2c_timer.data = (unsigned long)smu; + if (smu->db_node) { + smu->db_irq = irq_of_parse_and_map(smu->db_node, 0); + if (smu->db_irq == NO_IRQ) + printk(KERN_ERR "smu: failed to map irq for node %s\n", + smu->db_node->full_name); + } + if (smu->msg_node) { + smu->msg_irq = irq_of_parse_and_map(smu->msg_node, 0); + if (smu->msg_irq == NO_IRQ) + printk(KERN_ERR "smu: failed to map irq for node %s\n", + smu->msg_node->full_name); + } + /* * Try to request the interrupts */ if (smu->db_irq != NO_IRQ) { if (request_irq(smu->db_irq, smu_db_intr, - SA_SHIRQ, "SMU doorbell", smu) < 0) { + IRQF_SHARED, "SMU doorbell", smu) < 0) { printk(KERN_WARNING "SMU: can't " "request interrupt %d\n", smu->db_irq); @@ -566,7 +580,7 @@ static int smu_late_init(void) if (smu->msg_irq != NO_IRQ) { if (request_irq(smu->msg_irq, smu_msg_intr, - SA_SHIRQ, "SMU message", smu) < 0) { + IRQF_SHARED, "SMU message", smu) < 0) { printk(KERN_WARNING "SMU: can't " "request interrupt %d\n", smu->msg_irq); @@ -574,6 +588,7 @@ static int smu_late_init(void) } } + smu_irq_inited = 1; return 0; } /* This has to be before arch_initcall as the low i2c stuff relies on the @@ -745,6 +760,11 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) if (fail && --cmd->retries > 0) { DPRINTK("SMU: i2c failure, starting timer...\n"); BUG_ON(cmd != smu->cmd_i2c_cur); + if (!smu_irq_inited) { + mdelay(5); + smu_i2c_retry(0); + return; + } mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); return; } @@ -962,11 +982,11 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) /* Note: Only allowed to return error code in pointers (using ERR_PTR) * when interruptible is 1 */ -struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, - int interruptible) +const struct smu_sdbp_header *__smu_get_sdb_partition(int id, + unsigned int *size, int interruptible) { char pname[32]; - struct smu_sdbp_header *part; + const struct smu_sdbp_header *part; if (!smu) return NULL; @@ -983,8 +1003,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, } else mutex_lock(&smu_part_access); - part = (struct smu_sdbp_header *)get_property(smu->of_node, - pname, size); + part = get_property(smu->of_node, pname, size); if (part == NULL) { DPRINTK("trying to extract from SMU ...\n"); part = smu_create_sdb_partition(id); @@ -995,7 +1014,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, return part; } -struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +const struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) { return __smu_get_sdb_partition(id, size, 0); } @@ -1074,7 +1093,7 @@ static ssize_t smu_write(struct file *file, const char __user *buf, pp->mode = smu_file_events; return 0; } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { - struct smu_sdbp_header *part; + const struct smu_sdbp_header *part; part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); if (part == NULL) return -EINVAL; diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 5282fec1707..a0f30d0853e 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -9,7 +9,6 @@ * */ -#include <linux/config.h> #include <linux/types.h> #include <linux/module.h> #include <linux/errno.h> @@ -48,7 +47,7 @@ static u8 FAN_SPD_SET[2] = {0x30, 0x31}; static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */ static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */ -static char *sensor_location[3] = {NULL, NULL, NULL}; +static const char *sensor_location[3] = {NULL, NULL, NULL}; static int limit_adjust = 0; static int fan_speed = -1; @@ -554,7 +553,7 @@ static int __init thermostat_init(void) { struct device_node* np; - u32 *prop; + const u32 *prop; int i = 0, offset = 0; np = of_find_node_by_name(NULL, "fan"); @@ -567,13 +566,13 @@ thermostat_init(void) else return -ENODEV; - prop = (u32 *)get_property(np, "hwsensor-params-version", NULL); + prop = get_property(np, "hwsensor-params-version", NULL); printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop, (*prop == 1)?"":"un"); if (*prop != 1) return -ENODEV; - prop = (u32 *)get_property(np, "reg", NULL); + prop = get_property(np, "reg", NULL); if (!prop) return -ENODEV; diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 231146f439d..d00c0c37a12 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -95,9 +95,19 @@ * - Use min/max macros here or there * - Latest darwin updated U3H min fan speed to 20% PWM * + * July. 06, 2006 : 1.3 + * - Fix setting of RPM fans on Xserve G5 (they were going too fast) + * - Add missing slots fan control loop for Xserve G5 + * - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We + * still can't properly implement the control loop for these, so let's + * reduce the noise a little bit, it appears that 40% still gives us + * a pretty good air flow + * - Add code to "tickle" the FCU regulary so it doesn't think that + * we are gone while in fact, the machine just didn't need any fan + * speed change lately + * */ -#include <linux/config.h> #include <linux/types.h> #include <linux/module.h> #include <linux/errno.h> @@ -122,7 +132,7 @@ #include "therm_pm72.h" -#define VERSION "1.2b2" +#define VERSION "1.3" #undef DEBUG @@ -147,6 +157,7 @@ static struct basckside_pid_params backside_params; static struct backside_pid_state backside_state; static struct drives_pid_state drives_state; static struct dimm_pid_state dimms_state; +static struct slots_pid_state slots_state; static int state; static int cpu_count; static int cpu_pid_type; @@ -155,7 +166,8 @@ static struct completion ctrl_complete; static int critical_state; static int rackmac; static s32 dimm_output_clamp; - +static int fcu_rpm_shift; +static int fcu_tickle_ticks; static DECLARE_MUTEX(driver_lock); /* @@ -496,13 +508,20 @@ static int start_fcu(void) rc = fan_write_reg(0x2e, &buf, 1); if (rc < 0) return -EIO; + rc = fan_read_reg(0, &buf, 1); + if (rc < 0) + return -EIO; + fcu_rpm_shift = (buf == 1) ? 2 : 3; + printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n", + fcu_rpm_shift); + return 0; } static int set_rpm_fan(int fan_index, int rpm) { unsigned char buf[2]; - int rc, id; + int rc, id, min, max; if (fcu_fans[fan_index].type != FCU_FAN_RPM) return -EINVAL; @@ -510,12 +529,15 @@ static int set_rpm_fan(int fan_index, int rpm) if (id == FCU_FAN_ABSENT_ID) return -EINVAL; - if (rpm < 300) - rpm = 300; - else if (rpm > 8191) - rpm = 8191; - buf[0] = rpm >> 5; - buf[1] = rpm << 3; + min = 2400 >> fcu_rpm_shift; + max = 56000 >> fcu_rpm_shift; + + if (rpm < min) + rpm = min; + else if (rpm > max) + rpm = max; + buf[0] = rpm >> (8 - fcu_rpm_shift); + buf[1] = rpm << fcu_rpm_shift; rc = fan_write_reg(0x10 + (id * 2), buf, 2); if (rc < 0) return -EIO; @@ -552,7 +574,7 @@ static int get_rpm_fan(int fan_index, int programmed) if (rc != 2) return -EIO; - return (buf[0] << 5) | buf[1] >> 3; + return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift; } static int set_pwm_fan(int fan_index, int pwm) @@ -610,6 +632,26 @@ static int get_pwm_fan(int fan_index) return (buf[0] * 1000) / 2559; } +static void tickle_fcu(void) +{ + int pwm; + + pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX); + + DBG("FCU Tickle, slots fan is: %d\n", pwm); + if (pwm < 0) + pwm = 100; + + if (!rackmac) { + pwm = SLOTS_FAN_DEFAULT_PWM; + } else if (pwm < SLOTS_PID_OUTPUT_MIN) + pwm = SLOTS_PID_OUTPUT_MIN; + + /* That is hopefully enough to make the FCU happy */ + set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm); +} + + /* * Utility routine to read the CPU calibration EEPROM data * from the device-tree @@ -618,7 +660,7 @@ static int read_eeprom(int cpu, struct mpu_data *out) { struct device_node *np; char nodename[64]; - u8 *data; + const u8 *data; int len; /* prom.c routine for finding a node by path is a bit brain dead @@ -631,7 +673,7 @@ static int read_eeprom(int cpu, struct mpu_data *out) printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n"); return -ENODEV; } - data = (u8 *)get_property(np, "cpuid", &len); + data = get_property(np, "cpuid", &len); if (data == NULL) { printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n"); of_node_put(np); @@ -716,6 +758,9 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm) BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp) BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm) +BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp) +BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm) + BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp) static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL); @@ -736,6 +781,9 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL); static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL); static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL); +static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL); +static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL); + static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL); /* @@ -1077,6 +1125,9 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state) fan_min = dimm_output_clamp; fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan); + DBG(" CPU min mpu = %d, min dimm = %d\n", + state->mpu.rminn_intake_fan, dimm_output_clamp); + state->rpm = max(state->rpm, (int)fan_min); state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan); state->intake_rpm = state->rpm; @@ -1285,7 +1336,7 @@ static int init_backside_state(struct backside_pid_state *state) */ u3 = of_find_node_by_path("/u3@0,f8000000"); if (u3 != NULL) { - u32 *vers = (u32 *)get_property(u3, "device-rev", NULL); + const u32 *vers = get_property(u3, "device-rev", NULL); if (vers) if (((*vers) & 0x3f) < 0x34) u3h = 0; @@ -1375,7 +1426,8 @@ static void do_monitor_drives(struct drives_pid_state *state) DBG(" current rpm: %d\n", state->rpm); /* Get some sensor readings */ - temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8; + temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, + DS1775_TEMP)) << 8; state->last_temp = temp; DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), FIX32TOPRINT(DRIVES_PID_INPUT_TARGET)); @@ -1576,7 +1628,7 @@ static int init_dimms_state(struct dimm_pid_state *state) } /* - * Dispose of the state data for the drives control loop + * Dispose of the state data for the DIMM control loop */ static void dispose_dimms_state(struct dimm_pid_state *state) { @@ -1589,6 +1641,127 @@ static void dispose_dimms_state(struct dimm_pid_state *state) state->monitor = NULL; } +/* + * Slots fan control loop + */ +static void do_monitor_slots(struct slots_pid_state *state) +{ + s32 temp, integral, derivative; + s64 integ_p, deriv_p, prop_p, sum; + int i, rc; + + if (--state->ticks != 0) + return; + state->ticks = SLOTS_PID_INTERVAL; + + DBG("slots:\n"); + + /* Check fan status */ + rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX); + if (rc < 0) { + printk(KERN_WARNING "Error %d reading slots fan !\n", rc); + /* XXX What do we do now ? */ + } else + state->pwm = rc; + DBG(" current pwm: %d\n", state->pwm); + + /* Get some sensor readings */ + temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, + DS1775_TEMP)) << 8; + state->last_temp = temp; + DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), + FIX32TOPRINT(SLOTS_PID_INPUT_TARGET)); + + /* Store temperature and error in history array */ + state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE; + state->sample_history[state->cur_sample] = temp; + state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET; + + /* If first loop, fill the history table */ + if (state->first) { + for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) { + state->cur_sample = (state->cur_sample + 1) % + SLOTS_PID_HISTORY_SIZE; + state->sample_history[state->cur_sample] = temp; + state->error_history[state->cur_sample] = + temp - SLOTS_PID_INPUT_TARGET; + } + state->first = 0; + } + + /* Calculate the integral term */ + sum = 0; + integral = 0; + for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++) + integral += state->error_history[i]; + integral *= SLOTS_PID_INTERVAL; + DBG(" integral: %08x\n", integral); + integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral; + DBG(" integ_p: %d\n", (int)(integ_p >> 36)); + sum += integ_p; + + /* Calculate the derivative term */ + derivative = state->error_history[state->cur_sample] - + state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1) + % SLOTS_PID_HISTORY_SIZE]; + derivative /= SLOTS_PID_INTERVAL; + deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative; + DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); + sum += deriv_p; + + /* Calculate the proportional term */ + prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]); + DBG(" prop_p: %d\n", (int)(prop_p >> 36)); + sum += prop_p; + + /* Scale sum */ + sum >>= 36; + + DBG(" sum: %d\n", (int)sum); + state->pwm = (s32)sum; + + state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN); + state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX); + + DBG("** DRIVES PWM: %d\n", (int)state->pwm); + set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm); +} + +/* + * Initialize the state structure for the slots bay fan control loop + */ +static int init_slots_state(struct slots_pid_state *state) +{ + state->ticks = 1; + state->first = 1; + state->pwm = 50; + + state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp"); + if (state->monitor == NULL) + return -ENODEV; + + device_create_file(&of_dev->dev, &dev_attr_slots_temperature); + device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm); + + return 0; +} + +/* + * Dispose of the state data for the slots control loop + */ +static void dispose_slots_state(struct slots_pid_state *state) +{ + if (state->monitor == NULL) + return; + + device_remove_file(&of_dev->dev, &dev_attr_slots_temperature); + device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm); + + detach_i2c_chip(state->monitor); + state->monitor = NULL; +} + + static int call_critical_overtemp(void) { char *argv[] = { critical_overtemp_path, NULL }; @@ -1618,14 +1791,17 @@ static int main_control_loop(void *x) goto out; } - /* Set the PCI fan once for now */ - set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); + /* Set the PCI fan once for now on non-RackMac */ + if (!rackmac) + set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); /* Initialize ADCs */ initialize_adc(&cpu_state[0]); if (cpu_state[1].monitor != NULL) initialize_adc(&cpu_state[1]); + fcu_tickle_ticks = FCU_TICKLE_TICKS; + up(&driver_lock); while (state == state_attached) { @@ -1635,6 +1811,12 @@ static int main_control_loop(void *x) down(&driver_lock); + /* Tickle the FCU just in case */ + if (--fcu_tickle_ticks < 0) { + fcu_tickle_ticks = FCU_TICKLE_TICKS; + tickle_fcu(); + } + /* First, we always calculate the new DIMMs state on an Xserve */ if (rackmac) do_monitor_dimms(&dimms_state); @@ -1655,7 +1837,9 @@ static int main_control_loop(void *x) } /* Then, the rest */ do_monitor_backside(&backside_state); - if (!rackmac) + if (rackmac) + do_monitor_slots(&slots_state); + else do_monitor_drives(&drives_state); up(&driver_lock); @@ -1697,6 +1881,7 @@ static void dispose_control_loops(void) dispose_cpu_state(&cpu_state[1]); dispose_backside_state(&backside_state); dispose_drives_state(&drives_state); + dispose_slots_state(&slots_state); dispose_dimms_state(&dimms_state); } @@ -1746,6 +1931,8 @@ static int create_control_loops(void) goto fail; if (rackmac && init_dimms_state(&dimms_state)) goto fail; + if (rackmac && init_slots_state(&slots_state)) + goto fail; if (!rackmac && init_drives_state(&drives_state)) goto fail; @@ -1924,8 +2111,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node) while ((np = of_get_next_child(fcu_node, np)) != NULL) { int type = -1; - char *loc; - u32 *reg; + const char *loc; + const u32 *reg; DBG(" control: %s, type: %s\n", np->name, np->type); @@ -1941,8 +2128,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node) continue; /* Lookup for a matching location */ - loc = (char *)get_property(np, "location", NULL); - reg = (u32 *)get_property(np, "reg", NULL); + loc = get_property(np, "location", NULL); + reg = get_property(np, "reg", NULL); if (loc == NULL || reg == NULL) continue; DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h index c17e61f9c41..393cc9df94e 100644 --- a/drivers/macintosh/therm_pm72.h +++ b/drivers/macintosh/therm_pm72.h @@ -93,7 +93,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp"; * 0. This appear to be safe enough for this first version * of the driver, though I would accept any clean patch * doing a better use of the device-tree without turning the - * while i2c registration mecanism into a racy mess + * while i2c registration mechanism into a racy mess * * Note: Xserve changed this. We have some bits on the K2 bus, * which I arbitrarily set to 0x200. Ultimately, we really want @@ -105,6 +105,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp"; #define DRIVES_DALLAS_ID 0x94 #define BACKSIDE_MAX_ID 0x98 #define XSERVE_DIMMS_LM87 0x25a +#define XSERVE_SLOTS_LM75 0x290 /* * Some MAX6690, DS1775, LM87 register definitions @@ -198,7 +199,7 @@ struct drives_pid_state #define SLOTS_FAN_PWM_DEFAULT_ID 2 #define SLOTS_FAN_PWM_INDEX 2 -#define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */ +#define SLOTS_FAN_DEFAULT_PWM 40 /* Do better here ! */ /* @@ -206,7 +207,7 @@ struct drives_pid_state */ #define DIMM_PID_G_d 0 #define DIMM_PID_G_p 0 -#define DIMM_PID_G_r 0x6553600 +#define DIMM_PID_G_r 0x06553600 #define DIMM_PID_INPUT_TARGET 3276800 #define DIMM_PID_INTERVAL 1 #define DIMM_PID_OUTPUT_MAX 14000 @@ -226,6 +227,31 @@ struct dimm_pid_state }; +/* + * PID factors for the Xserve Slots control loop + */ +#define SLOTS_PID_G_d 0 +#define SLOTS_PID_G_p 0 +#define SLOTS_PID_G_r 0x00100000 +#define SLOTS_PID_INPUT_TARGET 3200000 +#define SLOTS_PID_INTERVAL 1 +#define SLOTS_PID_OUTPUT_MAX 100 +#define SLOTS_PID_OUTPUT_MIN 20 +#define SLOTS_PID_HISTORY_SIZE 20 + +struct slots_pid_state +{ + int ticks; + struct i2c_client * monitor; + s32 sample_history[SLOTS_PID_HISTORY_SIZE]; + s32 error_history[SLOTS_PID_HISTORY_SIZE]; + int cur_sample; + s32 last_temp; + int first; + int pwm; +}; + + /* Desktops */ @@ -283,6 +309,9 @@ struct cpu_pid_state s32 pump_max; }; +/* Tickle FCU every 10 seconds */ +#define FCU_TICKLE_TICKS 10 + /* * Driver state */ diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 3d9dd2e166a..738faab1b22 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -27,7 +27,6 @@ * */ -#include <linux/config.h> #include <linux/types.h> #include <linux/module.h> #include <linux/errno.h> @@ -485,14 +484,14 @@ struct apple_thermal_info { static int __init g4fan_init( void ) { - struct apple_thermal_info *info; + const struct apple_thermal_info *info; struct device_node *np; init_MUTEX( &x.lock ); if( !(np=of_find_node_by_name(NULL, "power-mgt")) ) return -ENODEV; - info = (struct apple_thermal_info*)get_property(np, "thermal-info", NULL); + info = get_property(np, "thermal-info", NULL); of_node_put(np); if( !info || !machine_is_compatible("PowerMac3,6") ) diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 2d9d7915040..7512d1c1520 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -9,7 +9,6 @@ * Copyright (C) 1996 Paul Mackerras. */ #include <stdarg.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> @@ -35,13 +34,6 @@ static volatile unsigned char __iomem *via; static DEFINE_SPINLOCK(cuda_lock); -#ifdef CONFIG_MAC -#define CUDA_IRQ IRQ_MAC_ADB -#define eieio() -#else -#define CUDA_IRQ vias->intrs[0].line -#endif - /* VIA registers - spaced 0x200 bytes apart */ #define RS 0x200 /* skip between registers */ #define B 0 /* B-side data */ @@ -131,7 +123,7 @@ int __init find_via_cuda(void) { struct adb_request req; phys_addr_t taddr; - u32 *reg; + const u32 *reg; int err; if (vias != 0) @@ -140,7 +132,7 @@ int __init find_via_cuda(void) if (vias == 0) return 0; - reg = (u32 *)get_property(vias, "reg", NULL); + reg = get_property(vias, "reg", NULL); if (reg == NULL) { printk(KERN_ERR "via-cuda: No \"reg\" property !\n"); goto fail; @@ -190,11 +182,24 @@ int __init find_via_cuda(void) static int __init via_cuda_start(void) { + unsigned int irq; + if (via == NULL) return -ENODEV; - if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { - printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); +#ifdef CONFIG_MAC + irq = IRQ_MAC_ADB; +#else /* CONFIG_MAC */ + irq = irq_of_parse_and_map(vias, 0); + if (irq == NO_IRQ) { + printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", + vias->full_name); + return -ENODEV; + } +#endif /* CONFIG_MAP */ + + if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { + printk(KERN_ERR "via-cuda: can't request irq %d\n", irq); return -EAGAIN; } diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c new file mode 100644 index 00000000000..6c29fe727c0 --- /dev/null +++ b/drivers/macintosh/via-pmu-backlight.c @@ -0,0 +1,187 @@ +/* + * Backlight code for via-pmu + * + * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi. + * Copyright (C) 2001-2002 Benjamin Herrenschmidt + * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> + * + */ + +#include <asm/ptrace.h> +#include <linux/adb.h> +#include <linux/pmu.h> +#include <asm/backlight.h> +#include <asm/prom.h> + +#define MAX_PMU_LEVEL 0xFF + +static struct backlight_properties pmu_backlight_data; +static DEFINE_SPINLOCK(pmu_backlight_lock); +static int sleeping; +static u8 bl_curve[FB_BACKLIGHT_LEVELS]; + +static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) +{ + unsigned int i, flat, count, range = (max - min); + + bl_curve[0] = off; + + for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) + bl_curve[flat] = min; + + count = FB_BACKLIGHT_LEVELS * 15 / 16; + for (i = 0; i < count; ++i) + bl_curve[flat + i] = min + (range * (i + 1) / count); +} + +static int pmu_backlight_curve_lookup(int value) +{ + int level = (FB_BACKLIGHT_LEVELS - 1); + int i, max = 0; + + /* Look for biggest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) + max = max((int)bl_curve[i], max); + + /* Look for nearest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { + int diff = abs(bl_curve[i] - value); + if (diff < max) { + max = diff; + level = i; + } + } + return level; +} + +static int pmu_backlight_get_level_brightness(int level) +{ + int pmulevel; + + /* Get and convert the value */ + pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; + if (pmulevel < 0) + pmulevel = 0; + else if (pmulevel > MAX_PMU_LEVEL) + pmulevel = MAX_PMU_LEVEL; + + return pmulevel; +} + +static int pmu_backlight_update_status(struct backlight_device *bd) +{ + struct adb_request req; + unsigned long flags; + int level = bd->props->brightness; + + spin_lock_irqsave(&pmu_backlight_lock, flags); + + /* Don't update brightness when sleeping */ + if (sleeping) + goto out; + + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + + if (level > 0) { + int pmulevel = pmu_backlight_get_level_brightness(level); + + pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); + pmu_wait_complete(&req); + + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_BACKLIGHT | PMU_POW_ON); + pmu_wait_complete(&req); + } else { + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_BACKLIGHT | PMU_POW_OFF); + pmu_wait_complete(&req); + } + +out: + spin_unlock_irqrestore(&pmu_backlight_lock, flags); + + return 0; +} + +static int pmu_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties pmu_backlight_data = { + .owner = THIS_MODULE, + .get_brightness = pmu_backlight_get_brightness, + .update_status = pmu_backlight_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +#ifdef CONFIG_PM +void pmu_backlight_set_sleep(int sleep) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_backlight_lock, flags); + sleeping = sleep; + spin_unlock_irqrestore(&pmu_backlight_lock, flags); +} +#endif /* CONFIG_PM */ + +void __init pmu_backlight_init() +{ + struct backlight_device *bd; + char name[10]; + int level, autosave; + + /* Special case for the old PowerBook since I can't test on it */ + autosave = + machine_is_compatible("AAPL,3400/2400") || + machine_is_compatible("AAPL,3500"); + + if (!autosave && + !pmac_has_backlight_type("pmu") && + !machine_is_compatible("AAPL,PowerBook1998") && + !machine_is_compatible("PowerBook1,1")) + return; + + snprintf(name, sizeof(name), "pmubl"); + + bd = backlight_device_register(name, NULL, &pmu_backlight_data); + if (IS_ERR(bd)) { + printk("pmubl: Backlight registration failed\n"); + goto error; + } + pmu_backlight_init_curve(0x7F, 0x46, 0x0E); + + level = pmu_backlight_data.max_brightness; + + if (autosave) { + /* read autosaved value if available */ + struct adb_request req; + pmu_request(&req, NULL, 2, 0xd9, 0); + pmu_wait_complete(&req); + + level = pmu_backlight_curve_lookup( + (req.reply[0] >> 4) * + pmu_backlight_data.max_brightness / 15); + } + + down(&bd->sem); + bd->props->brightness = level; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + up(&bd->sem); + + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); + + printk("pmubl: Backlight initialized (%s)\n", name); + + return; + +error: + return; +} diff --git a/drivers/macintosh/via-pmu-event.c b/drivers/macintosh/via-pmu-event.c new file mode 100644 index 00000000000..25cd5654232 --- /dev/null +++ b/drivers/macintosh/via-pmu-event.c @@ -0,0 +1,80 @@ +/* + * via-pmu event device for reporting some events that come through the PMU + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <linux/input.h> +#include <linux/adb.h> +#include <linux/pmu.h> +#include "via-pmu-event.h" + +static struct input_dev *pmu_input_dev; + +static int __init via_pmu_event_init(void) +{ + int err; + + /* do other models report button/lid status? */ + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return -ENODEV; + + pmu_input_dev = input_allocate_device(); + if (!pmu_input_dev) + return -ENOMEM; + + pmu_input_dev->name = "PMU"; + pmu_input_dev->id.bustype = BUS_HOST; + pmu_input_dev->id.vendor = 0x0001; + pmu_input_dev->id.product = 0x0001; + pmu_input_dev->id.version = 0x0100; + + set_bit(EV_KEY, pmu_input_dev->evbit); + set_bit(EV_SW, pmu_input_dev->evbit); + set_bit(KEY_POWER, pmu_input_dev->keybit); + set_bit(SW_LID, pmu_input_dev->swbit); + + err = input_register_device(pmu_input_dev); + if (err) + input_free_device(pmu_input_dev); + return err; +} + +void via_pmu_event(int key, int down) +{ + + if (unlikely(!pmu_input_dev)) + return; + + switch (key) { + case PMU_EVT_POWER: + input_report_key(pmu_input_dev, KEY_POWER, down); + break; + case PMU_EVT_LID: + input_report_switch(pmu_input_dev, SW_LID, down); + break; + default: + /* no such key handled */ + return; + } + + input_sync(pmu_input_dev); +} + +late_initcall(via_pmu_event_init); diff --git a/drivers/macintosh/via-pmu-event.h b/drivers/macintosh/via-pmu-event.h new file mode 100644 index 00000000000..72c54de408e --- /dev/null +++ b/drivers/macintosh/via-pmu-event.h @@ -0,0 +1,8 @@ +#ifndef __VIA_PMU_EVENT_H +#define __VIA_PMU_EVENT_H + +#define PMU_EVT_POWER 0 +#define PMU_EVT_LID 1 +extern void via_pmu_event(int key, int down); + +#endif /* __VIA_PMU_EVENT_H */ diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c new file mode 100644 index 00000000000..179af10105d --- /dev/null +++ b/drivers/macintosh/via-pmu-led.c @@ -0,0 +1,144 @@ +/* + * via-pmu LED class device + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/leds.h> +#include <linux/adb.h> +#include <linux/pmu.h> +#include <asm/prom.h> + +static spinlock_t pmu_blink_lock; +static struct adb_request pmu_blink_req; +/* -1: no change, 0: request off, 1: request on */ +static int requested_change; +static int sleeping; + +static void pmu_req_done(struct adb_request * req) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + /* if someone requested a change in the meantime + * (we only see the last one which is fine) + * then apply it now */ + if (requested_change != -1 && !sleeping) + pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); + /* reset requested change */ + requested_change = -1; + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static void pmu_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + switch (brightness) { + case LED_OFF: + requested_change = 0; + break; + case LED_FULL: + requested_change = 1; + break; + default: + goto out; + break; + } + /* if request isn't done, then don't do anything */ + if (pmu_blink_req.complete && !sleeping) + pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); + out: + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static struct led_classdev pmu_led = { + .name = "pmu-front-led", +#ifdef CONFIG_ADB_PMU_LED_IDE + .default_trigger = "ide-disk", +#endif + .brightness_set = pmu_led_set, +}; + +#ifdef CONFIG_PM +static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + + switch (when) { + case PBOOK_SLEEP_REQUEST: + sleeping = 1; + break; + case PBOOK_WAKE: + sleeping = 0; + break; + default: + /* do nothing */ + break; + } + spin_unlock_irqrestore(&pmu_blink_lock, flags); + + return PBOOK_SLEEP_OK; +} + +static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { + .notifier_call = pmu_led_sleep_call, +}; +#endif + +static int __init via_pmu_led_init(void) +{ + struct device_node *dt; + const char *model; + + /* only do this on keylargo based models */ + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return -ENODEV; + + dt = of_find_node_by_path("/"); + if (dt == NULL) + return -ENODEV; + model = get_property(dt, "model", NULL); + if (model == NULL) + return -ENODEV; + if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && + strncmp(model, "iBook", strlen("iBook")) != 0) { + of_node_put(dt); + /* ignore */ + return -ENODEV; + } + of_node_put(dt); + + spin_lock_init(&pmu_blink_lock); + /* no outstanding req */ + pmu_blink_req.complete = 1; + pmu_blink_req.done = pmu_req_done; +#ifdef CONFIG_PM + pmu_register_sleep_notifier(&via_pmu_led_sleep_notif); +#endif + return led_classdev_register(NULL, &pmu_led); +} + +late_initcall(via_pmu_led_init); diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c63d4e7984b..dda03985dcf 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -16,12 +16,10 @@ * a sleep or a freq. switch * - Move sleep code out of here to pmac_pm, merge into new * common PM infrastructure - * - Move backlight code out as well * - Save/Restore PCI space properly * */ #include <stdarg.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> @@ -61,13 +59,9 @@ #include <asm/mmu_context.h> #include <asm/cputable.h> #include <asm/time.h> -#ifdef CONFIG_PMAC_BACKLIGHT #include <asm/backlight.h> -#endif -#ifdef CONFIG_PPC32 -#include <asm/open_pic.h> -#endif +#include "via-pmu-event.h" /* Some compile options */ #undef SUSPEND_USES_PMU @@ -144,14 +138,13 @@ static int data_index; static int data_len; static volatile int adb_int_pending; static volatile int disable_poll; -static struct adb_request bright_req_1, bright_req_2; static struct device_node *vias; static int pmu_kind = PMU_UNKNOWN; static int pmu_fully_inited = 0; static int pmu_has_adb; static struct device_node *gpio_node; static unsigned char __iomem *gpio_reg = NULL; -static int gpio_irq = -1; +static int gpio_irq = NO_IRQ; static int gpio_irq_enabled = -1; static volatile int pmu_suspended = 0; static spinlock_t pmu_lock; @@ -161,7 +154,7 @@ static int drop_interrupts; #if defined(CONFIG_PM) && defined(CONFIG_PPC32) static int option_lid_wakeup = 1; #endif /* CONFIG_PM && CONFIG_PPC32 */ -#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT) +#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY) static int sleep_in_progress; #endif static unsigned long async_req_locks; @@ -181,10 +174,6 @@ static int query_batt_timer = BATTERY_POLLING_COUNT; static struct adb_request batt_req; static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; -#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) -extern int disable_kernel_backlight; -#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ - int __fake_sleep; int asleep; BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); @@ -208,10 +197,6 @@ static int proc_get_info(char *page, char **start, off_t off, int count, int *eof, void *data); static int proc_get_irqstats(char *page, char **start, off_t off, int count, int *eof, void *data); -#ifdef CONFIG_PMAC_BACKLIGHT -static int pmu_set_backlight_level(int level, void* data); -static int pmu_set_backlight_enable(int on, int level, void* data); -#endif /* CONFIG_PMAC_BACKLIGHT */ static void pmu_pass_intr(unsigned char *data, int len); static int proc_get_batt(char *page, char **start, off_t off, int count, int *eof, void *data); @@ -292,17 +277,10 @@ static char *pbook_type[] = { "Core99" }; -#ifdef CONFIG_PMAC_BACKLIGHT -static struct backlight_controller pmu_backlight_controller = { - pmu_set_backlight_enable, - pmu_set_backlight_level -}; -#endif /* CONFIG_PMAC_BACKLIGHT */ - int __init find_via_pmu(void) { u64 taddr; - u32 *reg; + const u32 *reg; if (via != 0) return 1; @@ -310,7 +288,7 @@ int __init find_via_pmu(void) if (vias == NULL) return 0; - reg = (u32 *)get_property(vias, "reg", NULL); + reg = get_property(vias, "reg", NULL); if (reg == NULL) { printk(KERN_ERR "via-pmu: No \"reg\" property !\n"); goto fail; @@ -352,7 +330,7 @@ int __init find_via_pmu(void) gpiop = of_find_node_by_name(NULL, "gpio"); if (gpiop) { - reg = (u32 *)get_property(gpiop, "reg", NULL); + reg = get_property(gpiop, "reg", NULL); if (reg) gaddr = of_translate_address(gpiop, reg); if (gaddr != OF_BAD_ADDR) @@ -414,24 +392,21 @@ static int __init pmu_init(void) */ static int __init via_pmu_start(void) { + unsigned int irq; + if (vias == NULL) return -ENODEV; - bright_req_1.complete = 1; - bright_req_2.complete = 1; batt_req.complete = 1; -#ifndef CONFIG_PPC_MERGE - if (pmu_kind == PMU_KEYLARGO_BASED) - openpic_set_irq_priority(vias->intrs[0].line, - OPENPIC_PRIORITY_DEFAULT + 1); -#endif - - if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", - (void *)0)) { - printk(KERN_ERR "VIA-PMU: can't get irq %d\n", - vias->intrs[0].line); - return -EAGAIN; + irq = irq_of_parse_and_map(vias, 0); + if (irq == NO_IRQ) { + printk(KERN_ERR "via-pmu: can't map interruptn"); + return -ENODEV; + } + if (request_irq(irq, via_pmu_interrupt, 0, "VIA-PMU", (void *)0)) { + printk(KERN_ERR "via-pmu: can't request irq %d\n", irq); + return -ENODEV; } if (pmu_kind == PMU_KEYLARGO_BASED) { @@ -439,10 +414,10 @@ static int __init via_pmu_start(void) if (gpio_node == NULL) gpio_node = of_find_node_by_name(NULL, "pmu-interrupt"); - if (gpio_node && gpio_node->n_intrs > 0) - gpio_irq = gpio_node->intrs[0].line; + if (gpio_node) + gpio_irq = irq_of_parse_and_map(gpio_node, 0); - if (gpio_irq != -1) { + if (gpio_irq != NO_IRQ) { if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0)) printk(KERN_ERR "pmu: can't get irq %d" @@ -483,9 +458,9 @@ static int __init via_pmu_dev_init(void) return -ENODEV; #ifdef CONFIG_PMAC_BACKLIGHT - /* Enable backlight */ - register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); -#endif /* CONFIG_PMAC_BACKLIGHT */ + /* Initialize backlight */ + pmu_backlight_init(); +#endif #ifdef CONFIG_PPC32 if (machine_is_compatible("AAPL,3400/2400") || @@ -504,9 +479,9 @@ static int __init via_pmu_dev_init(void) pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } else { struct device_node* prim = find_devices("power-mgt"); - u32 *prim_info = NULL; + const u32 *prim_info = NULL; if (prim) - prim_info = (u32 *)get_property(prim, "prim-info", NULL); + prim_info = get_property(prim, "prim-info", NULL); if (prim_info) { /* Other stuffs here yet unknown */ pmu_battery_count = (prim_info[6] >> 16) & 0xff; @@ -1421,11 +1396,8 @@ next: else if ((1 << pirq) & PMU_INT_SNDBRT) { #ifdef CONFIG_PMAC_BACKLIGHT if (len == 3) -#ifdef CONFIG_INPUT_ADBHID - if (!disable_kernel_backlight) -#endif /* CONFIG_INPUT_ADBHID */ - set_backlight_level(data[1] >> 4); -#endif /* CONFIG_PMAC_BACKLIGHT */ + pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4); +#endif } /* Tick interrupt */ else if ((1 << pirq) & PMU_INT_TICK) { @@ -1441,6 +1413,12 @@ next: if (pmu_battery_count) query_battery_state(); pmu_pass_intr(data, len); + /* len == 6 is probably a bad check. But how do I + * know what PMU versions send what events here? */ + if (len == 6) { + via_pmu_event(PMU_EVT_POWER, !!(data[1]&8)); + via_pmu_event(PMU_EVT_LID, data[1]&1); + } } else { pmu_pass_intr(data, len); } @@ -1674,61 +1652,6 @@ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs) return IRQ_NONE; } -#ifdef CONFIG_PMAC_BACKLIGHT -static int backlight_to_bright[] = { - 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, - 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e -}; - -static int -pmu_set_backlight_enable(int on, int level, void* data) -{ - struct adb_request req; - - if (vias == NULL) - return -ENODEV; - - if (on) { - pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, - backlight_to_bright[level]); - pmu_wait_complete(&req); - } - pmu_request(&req, NULL, 2, PMU_POWER_CTRL, - PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); - pmu_wait_complete(&req); - - return 0; -} - -static void -pmu_bright_complete(struct adb_request *req) -{ - if (req == &bright_req_1) - clear_bit(1, &async_req_locks); - if (req == &bright_req_2) - clear_bit(2, &async_req_locks); -} - -static int -pmu_set_backlight_level(int level, void* data) -{ - if (vias == NULL) - return -ENODEV; - - if (test_and_set_bit(1, &async_req_locks)) - return -EAGAIN; - pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT, - backlight_to_bright[level]); - if (test_and_set_bit(2, &async_req_locks)) - return -EAGAIN; - pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL, - PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ? - PMU_POW_ON : PMU_POW_OFF)); - - return 0; -} -#endif /* CONFIG_PMAC_BACKLIGHT */ - void pmu_enable_irled(int on) { @@ -2072,6 +1995,8 @@ restore_via_state(void) out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } +extern void pmu_backlight_set_sleep(int sleep); + static int pmac_suspend_devices(void) { @@ -2109,6 +2034,11 @@ pmac_suspend_devices(void) return -EBUSY; } +#ifdef CONFIG_PMAC_BACKLIGHT + /* Tell backlight code not to muck around with the chip anymore */ + pmu_backlight_set_sleep(1); +#endif + /* Call platform functions marked "on sleep" */ pmac_pfunc_i2c_suspend(); pmac_pfunc_base_suspend(); @@ -2145,9 +2075,8 @@ pmac_suspend_devices(void) return -EBUSY; } - /* Wait for completion of async backlight requests */ - while (!bright_req_1.complete || !bright_req_2.complete || - !batt_req.complete) + /* Wait for completion of async requests */ + while (!batt_req.complete) pmu_poll(); /* Giveup the lazy FPU & vec so we don't have to back them @@ -2168,6 +2097,11 @@ pmac_wakeup_devices(void) { mdelay(100); +#ifdef CONFIG_PMAC_BACKLIGHT + /* Tell backlight code it can use the chip again */ + pmu_backlight_set_sleep(0); +#endif + /* Power back up system devices (including the PIC) */ device_power_up(); @@ -2482,7 +2416,7 @@ struct pmu_private { spinlock_t lock; #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) int backlight_locker; -#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ +#endif }; static LIST_HEAD(all_pmu_pvt); @@ -2532,7 +2466,7 @@ pmu_open(struct inode *inode, struct file *file) spin_lock_irqsave(&all_pvt_lock, flags); #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) pp->backlight_locker = 0; -#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ +#endif list_add(&pp->list, &all_pmu_pvt); spin_unlock_irqrestore(&all_pvt_lock, flags); file->private_data = pp; @@ -2627,13 +2561,12 @@ pmu_release(struct inode *inode, struct file *file) spin_lock_irqsave(&all_pvt_lock, flags); list_del(&pp->list); spin_unlock_irqrestore(&all_pvt_lock, flags); + #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) - if (pp->backlight_locker) { - spin_lock_irqsave(&pmu_lock, flags); - disable_kernel_backlight--; - spin_unlock_irqrestore(&pmu_lock, flags); - } -#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ + if (pp->backlight_locker) + pmac_backlight_enable(); +#endif + kfree(pp); } unlock_kernel(); @@ -2678,42 +2611,50 @@ pmu_ioctl(struct inode * inode, struct file *filp, return put_user(1, argp); #endif /* CONFIG_PM && CONFIG_PPC32 */ -#ifdef CONFIG_PMAC_BACKLIGHT - /* Backlight should have its own device or go via - * the fbdev - */ +#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY + /* Compatibility ioctl's for backlight */ case PMU_IOC_GET_BACKLIGHT: + { + int brightness; + if (sleep_in_progress) return -EBUSY; - error = get_backlight_level(); - if (error < 0) - return error; - return put_user(error, argp); + + brightness = pmac_backlight_get_legacy_brightness(); + if (brightness < 0) + return brightness; + else + return put_user(brightness, argp); + + } case PMU_IOC_SET_BACKLIGHT: { - __u32 value; + int brightness; + if (sleep_in_progress) return -EBUSY; - error = get_user(value, argp); - if (!error) - error = set_backlight_level(value); - break; + + error = get_user(brightness, argp); + if (error) + return error; + + return pmac_backlight_set_legacy_brightness(brightness); } #ifdef CONFIG_INPUT_ADBHID case PMU_IOC_GRAB_BACKLIGHT: { struct pmu_private *pp = filp->private_data; - unsigned long flags; if (pp->backlight_locker) return 0; + pp->backlight_locker = 1; - spin_lock_irqsave(&pmu_lock, flags); - disable_kernel_backlight++; - spin_unlock_irqrestore(&pmu_lock, flags); + pmac_backlight_disable(); + return 0; } #endif /* CONFIG_INPUT_ADBHID */ -#endif /* CONFIG_PMAC_BACKLIGHT */ +#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ + case PMU_IOC_GET_MODEL: return put_user(pmu_kind, argp); case PMU_IOC_HAS_ADB: diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c index 81337cd16e8..900aade0619 100644 --- a/drivers/macintosh/windfarm_cpufreq_clamp.c +++ b/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index f1df6efcbe6..2ff546e4c92 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c @@ -396,7 +396,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st) static void wf_smu_create_cpu_fans(void) { struct wf_cpu_pid_param pid_param; - struct smu_sdbp_header *hdr; + const struct smu_sdbp_header *hdr; struct smu_sdbp_cpupiddata *piddata; struct smu_sdbp_fvt *fvt; s32 tmax, tdelta, maxpow, powadj; @@ -702,7 +702,7 @@ static struct notifier_block wf_smu_events = { static int wf_init_pm(void) { - struct smu_sdbp_header *hdr; + const struct smu_sdbp_header *hdr; hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL); if (hdr != 0) { diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c index 0d6372e96d3..59e9ffe37c3 100644 --- a/drivers/macintosh/windfarm_pm91.c +++ b/drivers/macintosh/windfarm_pm91.c @@ -144,7 +144,7 @@ static struct wf_smu_slots_fans_state *wf_smu_slots_fans; static void wf_smu_create_cpu_fans(void) { struct wf_cpu_pid_param pid_param; - struct smu_sdbp_header *hdr; + const struct smu_sdbp_header *hdr; struct smu_sdbp_cpupiddata *piddata; struct smu_sdbp_fvt *fvt; s32 tmax, tdelta, maxpow, powadj; diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index a9e88edc0c7..bff1f372f18 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -159,14 +159,15 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, int pwm_fan) { struct smu_fan_control *fct; - s32 *v; u32 *reg; - char *l; + const s32 *v; + const u32 *reg; + const char *l; fct = kmalloc(sizeof(struct smu_fan_control), GFP_KERNEL); if (fct == NULL) return NULL; fct->ctrl.ops = &smu_fan_ops; - l = (char *)get_property(node, "location", NULL); + l = get_property(node, "location", NULL); if (l == NULL) goto fail; @@ -223,17 +224,17 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, goto fail; /* Get min & max values*/ - v = (s32 *)get_property(node, "min-value", NULL); + v = get_property(node, "min-value", NULL); if (v == NULL) goto fail; fct->min = *v; - v = (s32 *)get_property(node, "max-value", NULL); + v = get_property(node, "max-value", NULL); if (v == NULL) goto fail; fct->max = *v; /* Get "reg" value */ - reg = (u32 *)get_property(node, "reg", NULL); + reg = get_property(node, "reg", NULL); if (reg == NULL) goto fail; fct->reg = *reg; diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index e295a07a1eb..83f79de7174 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -233,15 +233,15 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) { struct wf_sat *sat; struct wf_sat_sensor *sens; - u32 *reg; - char *loc, *type; + const u32 *reg; + const char *loc, *type; u8 addr, chip, core; struct device_node *child; int shift, cpu, index; char *name; int vsens[2], isens[2]; - reg = (u32 *) get_property(dev, "reg", NULL); + reg = get_property(dev, "reg", NULL); if (reg == NULL) return; addr = *reg; @@ -268,7 +268,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) isens[0] = isens[1] = -1; child = NULL; while ((child = of_get_next_child(dev, child)) != NULL) { - reg = (u32 *) get_property(child, "reg", NULL); + reg = get_property(child, "reg", NULL); type = get_property(child, "device_type", NULL); loc = get_property(child, "location", NULL); if (reg == NULL || loc == NULL) @@ -397,12 +397,7 @@ static int wf_sat_detach(struct i2c_client *client) static int __init sat_sensors_init(void) { - int err; - - err = i2c_add_driver(&wf_sat_driver); - if (err < 0) - return err; - return 0; + return i2c_add_driver(&wf_sat_driver); } static void __exit sat_sensors_exit(void) diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index bed25dcf8a1..defe9922ebd 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c @@ -198,14 +198,14 @@ static struct wf_sensor_ops smu_slotspow_ops = { static struct smu_ad_sensor *smu_ads_create(struct device_node *node) { struct smu_ad_sensor *ads; - char *c, *l; - u32 *v; + const char *c, *l; + const u32 *v; ads = kmalloc(sizeof(struct smu_ad_sensor), GFP_KERNEL); if (ads == NULL) return NULL; - c = (char *)get_property(node, "device_type", NULL); - l = (char *)get_property(node, "location", NULL); + c = get_property(node, "device_type", NULL); + l = get_property(node, "location", NULL); if (c == NULL || l == NULL) goto fail; @@ -255,7 +255,7 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node) } else goto fail; - v = (u32 *)get_property(node, "reg", NULL); + v = get_property(node, "reg", NULL); if (v == NULL) goto fail; ads->reg = *v; @@ -382,7 +382,7 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps) static void smu_fetch_param_partitions(void) { - struct smu_sdbp_header *hdr; + const struct smu_sdbp_header *hdr; /* Get CPU voltage/current/power calibration data */ hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL); |