summaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/macintosh')
-rw-r--r--drivers/macintosh/Kconfig14
-rw-r--r--drivers/macintosh/apm_emu.c521
-rw-r--r--drivers/macintosh/mac_hid.c8
-rw-r--r--drivers/macintosh/macio_sysfs.c27
-rw-r--r--drivers/macintosh/mediabay.c2
-rw-r--r--drivers/macintosh/smu.c2
-rw-r--r--drivers/macintosh/therm_adt746x.c5
-rw-r--r--drivers/macintosh/therm_pm72.c1
-rw-r--r--drivers/macintosh/therm_windtunnel.c3
-rw-r--r--drivers/macintosh/via-cuda.c58
-rw-r--r--drivers/macintosh/via-macii.c582
-rw-r--r--drivers/macintosh/via-pmu-led.c35
-rw-r--r--drivers/macintosh/via-pmu.c12
-rw-r--r--drivers/macintosh/via-pmu68k.c3
-rw-r--r--drivers/macintosh/windfarm_core.c1
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c4
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c2
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c2
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c2
19 files changed, 359 insertions, 925 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 1a86387..58926da 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -1,6 +1,10 @@
-menu "Macintosh device drivers"
+menuconfig MACINTOSH_DRIVERS
+ bool "Macintosh device drivers"
depends on PPC || MAC || X86
+ default y
+
+if MACINTOSH_DRIVERS
config ADB
bool "Apple Desktop Bus (ADB) support"
@@ -109,7 +113,9 @@ config PMAC_SMU
config PMAC_APM_EMU
tristate "APM emulation"
- depends on PPC_PMAC && PPC32 && PM && ADB_PMU
+ select SYS_SUPPORTS_APM_EMULATION
+ select APM_EMULATION
+ depends on ADB_PMU && PM
config PMAC_MEDIABAY
bool "Support PowerBook hotswap media bay"
@@ -231,7 +237,7 @@ config PMAC_RACKMETER
tristate "Support for Apple XServe front panel LEDs"
depends on PPC_PMAC
help
- This driver procides some support to control the front panel
+ This driver provides some support to control the front panel
blue LEDs "vu-meter" of the XServer macs.
-endmenu
+endif # MACINTOSH_DRIVERS
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
index cdb0bea..9821e63 100644
--- a/drivers/macintosh/apm_emu.c
+++ b/drivers/macintosh/apm_emu.c
@@ -1,9 +1,7 @@
-/* APM emulation layer for PowerMac
- *
- * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+/*
+ * APM emulation for PMU-based machines
*
- * Lots of code inherited from apm.c, see appropriate notice in
- * arch/i386/kernel/apm.c
+ * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* 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
@@ -18,429 +16,39 @@
*
*/
-#include <linux/module.h>
-
-#include <linux/poll.h>
-#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/timer.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
#include <linux/kernel.h>
-#include <linux/smp_lock.h>
-
+#include <linux/module.h>
+#include <linux/apm-emulation.h>
#include <linux/adb.h>
#include <linux/pmu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(args...) printk(KERN_DEBUG args)
-//#define DBG(args...) xmon_printf(args)
-#else
-#define DBG(args...) do { } while (0)
-#endif
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define APM_MINOR_DEV 134
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS 20
-
-#define FAKE_APM_BIOS_VERSION 0x0101
-
-#define APM_USER_NOTIFY_TIMEOUT (5*HZ)
-
-/*
- * The per-file APM data
- */
-struct apm_user {
- int magic;
- struct apm_user * next;
- int suser: 1;
- int suspend_waiting: 1;
- int suspends_pending;
- int suspends_read;
- int event_head;
- int event_tail;
- apm_event_t events[APM_MAX_EVENTS];
-};
-
-/*
- * The magic number in apm_user
- */
-#define APM_BIOS_MAGIC 0x4101
-
-/*
- * Local variables
- */
-static int suspends_pending;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-static struct apm_user * user_list;
-
-static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier apm_sleep_notifier = {
- apm_notify_sleep,
- SLEEP_LEVEL_USERLAND,
-};
-
-static const char driver_version[] = "0.5"; /* no spaces */
-
-#ifdef DEBUG
-static char * apm_event_name[] = {
- "system standby",
- "system suspend",
- "normal resume",
- "critical resume",
- "low battery",
- "power status change",
- "update time",
- "critical suspend",
- "user standby",
- "user suspend",
- "system standby resume",
- "capabilities change"
-};
-#define NR_APM_EVENT_NAME \
- (sizeof(apm_event_name) / sizeof(apm_event_name[0]))
-
-#endif
-
-static int queue_empty(struct apm_user *as)
-{
- return as->event_head == as->event_tail;
-}
-
-static apm_event_t get_queued_event(struct apm_user *as)
-{
- as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
- return as->events[as->event_tail];
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
- struct apm_user * as;
-
- DBG("apm_emu: queue_event(%s)\n", apm_event_name[event-1]);
- if (user_list == NULL)
- return;
- for (as = user_list; as != NULL; as = as->next) {
- if (as == sender)
- continue;
- as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
- if (as->event_head == as->event_tail) {
- static int notified;
-
- if (notified++ == 0)
- printk(KERN_ERR "apm_emu: an event queue overflowed\n");
- as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
- }
- as->events[as->event_head] = event;
- if (!as->suser)
- continue;
- switch (event) {
- case APM_SYS_SUSPEND:
- case APM_USER_SUSPEND:
- as->suspends_pending++;
- suspends_pending++;
- break;
- case APM_NORMAL_RESUME:
- as->suspend_waiting = 0;
- break;
- }
- }
- wake_up_interruptible(&apm_waitqueue);
-}
-
-static int check_apm_user(struct apm_user *as, const char *func)
-{
- if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
- printk(KERN_ERR "apm_emu: %s passed bad filp\n", func);
- return 1;
- }
- return 0;
-}
-
-static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
- struct apm_user * as;
- size_t i;
- apm_event_t event;
- DECLARE_WAITQUEUE(wait, current);
-
- as = fp->private_data;
- if (check_apm_user(as, "read"))
- return -EIO;
- if (count < sizeof(apm_event_t))
- return -EINVAL;
- if (queue_empty(as)) {
- if (fp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- add_wait_queue(&apm_waitqueue, &wait);
-repeat:
- set_current_state(TASK_INTERRUPTIBLE);
- if (queue_empty(as) && !signal_pending(current)) {
- schedule();
- goto repeat;
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&apm_waitqueue, &wait);
- }
- i = count;
- while ((i >= sizeof(event)) && !queue_empty(as)) {
- event = get_queued_event(as);
- DBG("apm_emu: do_read, returning: %s\n", apm_event_name[event-1]);
- if (copy_to_user(buf, &event, sizeof(event))) {
- if (i < count)
- break;
- return -EFAULT;
- }
- switch (event) {
- case APM_SYS_SUSPEND:
- case APM_USER_SUSPEND:
- as->suspends_read++;
- break;
- }
- buf += sizeof(event);
- i -= sizeof(event);
- }
- if (i < count)
- return count - i;
- if (signal_pending(current))
- return -ERESTARTSYS;
- return 0;
-}
-
-static unsigned int do_poll(struct file *fp, poll_table * wait)
-{
- struct apm_user * as;
-
- as = fp->private_data;
- if (check_apm_user(as, "poll"))
- return 0;
- poll_wait(fp, &apm_waitqueue, wait);
- if (!queue_empty(as))
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-static int do_ioctl(struct inode * inode, struct file *filp,
- u_int cmd, u_long arg)
-{
- struct apm_user * as;
- DECLARE_WAITQUEUE(wait, current);
-
- as = filp->private_data;
- if (check_apm_user(as, "ioctl"))
- return -EIO;
- if (!as->suser)
- return -EPERM;
- switch (cmd) {
- case APM_IOC_SUSPEND:
- /* If a suspend message was sent to userland, we
- * consider this as a confirmation message
- */
- if (as->suspends_read > 0) {
- as->suspends_read--;
- as->suspends_pending--;
- suspends_pending--;
- } else {
- // Route to PMU suspend ?
- break;
- }
- as->suspend_waiting = 1;
- add_wait_queue(&apm_waitqueue, &wait);
- DBG("apm_emu: ioctl waking up sleep waiter !\n");
- wake_up(&apm_suspend_waitqueue);
- mb();
- while(as->suspend_waiting && !signal_pending(current)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&apm_waitqueue, &wait);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int do_release(struct inode * inode, struct file * filp)
-{
- struct apm_user * as;
-
- as = filp->private_data;
- if (check_apm_user(as, "release"))
- return 0;
- filp->private_data = NULL;
- lock_kernel();
- if (as->suspends_pending > 0) {
- suspends_pending -= as->suspends_pending;
- if (suspends_pending <= 0)
- wake_up(&apm_suspend_waitqueue);
- }
- if (user_list == as)
- user_list = as->next;
- else {
- struct apm_user * as1;
-
- for (as1 = user_list;
- (as1 != NULL) && (as1->next != as);
- as1 = as1->next)
- ;
- if (as1 == NULL)
- printk(KERN_ERR "apm: filp not in user list\n");
- else
- as1->next = as->next;
- }
- unlock_kernel();
- kfree(as);
- return 0;
-}
-
-static int do_open(struct inode * inode, struct file * filp)
-{
- struct apm_user * as;
-
- as = kmalloc(sizeof(*as), GFP_KERNEL);
- if (as == NULL) {
- printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
- sizeof(*as));
- return -ENOMEM;
- }
- as->magic = APM_BIOS_MAGIC;
- as->event_tail = as->event_head = 0;
- as->suspends_pending = 0;
- as->suspends_read = 0;
- /*
- * XXX - this is a tiny bit broken, when we consider BSD
- * process accounting. If the device is opened by root, we
- * instantly flag that we used superuser privs. Who knows,
- * we might close the device immediately without doing a
- * privileged operation -- cevans
- */
- as->suser = capable(CAP_SYS_ADMIN);
- as->next = user_list;
- user_list = as;
- filp->private_data = as;
-
- DBG("apm_emu: opened by %s, suser: %d\n", current->comm, (int)as->suser);
-
- return 0;
-}
-
-/* Wait for all clients to ack the suspend request. APM API
- * doesn't provide a way to NAK, but this could be added
- * here.
- */
-static void wait_all_suspend(void)
-{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(&apm_suspend_waitqueue, &wait);
- DBG("apm_emu: wait_all_suspend(), suspends_pending: %d\n", suspends_pending);
- while(suspends_pending > 0) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&apm_suspend_waitqueue, &wait);
-
- DBG("apm_emu: wait_all_suspend() - complete !\n");
-}
-
-static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
-{
- switch(when) {
- case PBOOK_SLEEP_REQUEST:
- queue_event(APM_SYS_SUSPEND, NULL);
- wait_all_suspend();
- break;
- case PBOOK_WAKE:
- queue_event(APM_NORMAL_RESUME, NULL);
- break;
- }
-}
-
#define APM_CRITICAL 10
#define APM_LOW 30
-static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
+static void pmu_apm_get_power_status(struct apm_power_info *info)
{
- /* Arguments, with symbols from linux/apm_bios.h. Information is
- from the Get Power Status (0x0a) call unless otherwise noted.
+ int percentage = -1;
+ int batteries = 0;
+ int time_units = -1;
+ int real_count = 0;
+ int i;
+ char charging = 0;
+ long charge = -1;
+ long amperage = 0;
+ unsigned long btype = 0;
+
+ info->battery_status = APM_BATTERY_STATUS_UNKNOWN;
+ info->battery_flag = APM_BATTERY_FLAG_UNKNOWN;
+ info->units = APM_UNITS_MINS;
+
+ if (pmu_power_flags & PMU_PWR_AC_PRESENT)
+ info->ac_line_status = APM_AC_ONLINE;
+ else
+ info->ac_line_status = APM_AC_OFFLINE;
- 0) Linux driver version (this will change if format changes)
- 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
- 2) APM flags from APM Installation Check (0x00):
- bit 0: APM_16_BIT_SUPPORT
- bit 1: APM_32_BIT_SUPPORT
- bit 2: APM_IDLE_SLOWS_CLOCK
- bit 3: APM_BIOS_DISABLED
- bit 4: APM_BIOS_DISENGAGED
- 3) AC line status
- 0x00: Off-line
- 0x01: On-line
- 0x02: On backup power (BIOS >= 1.1 only)
- 0xff: Unknown
- 4) Battery status
- 0x00: High
- 0x01: Low
- 0x02: Critical
- 0x03: Charging
- 0x04: Selected battery not present (BIOS >= 1.2 only)
- 0xff: Unknown
- 5) Battery flag
- bit 0: High
- bit 1: Low
- bit 2: Critical
- bit 3: Charging
- bit 7: No system battery
- 0xff: Unknown
- 6) Remaining battery life (percentage of charge):
- 0-100: valid
- -1: Unknown
- 7) Remaining battery life (time units):
- Number of remaining minutes or seconds
- -1: Unknown
- 8) min = minutes; sec = seconds */
-
- unsigned short ac_line_status;
- unsigned short battery_status = 0;
- unsigned short battery_flag = 0xff;
- int percentage = -1;
- int time_units = -1;
- int real_count = 0;
- int i;
- char * p = buf;
- char charging = 0;
- long charge = -1;
- long amperage = 0;
- unsigned long btype = 0;
-
- ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0);
for (i=0; i<pmu_battery_count; i++) {
if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
- battery_status++;
+ batteries++;
if (percentage < 0)
percentage = 0;
if (charge < 0)
@@ -456,9 +64,9 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
charging++;
}
}
- if (0 == battery_status)
- ac_line_status = 1;
- battery_status = 0xff;
+ if (batteries == 0)
+ info->ac_line_status = APM_AC_ONLINE;
+
if (real_count) {
if (amperage < 0) {
if (btype == PMU_BATT_TYPE_SMART)
@@ -468,85 +76,44 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
}
percentage /= real_count;
if (charging > 0) {
- battery_status = 0x03;
- battery_flag = 0x08;
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ info->battery_flag = APM_BATTERY_FLAG_CHARGING;
} else if (percentage <= APM_CRITICAL) {
- battery_status = 0x02;
- battery_flag = 0x04;
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ info->battery_flag = APM_BATTERY_FLAG_CRITICAL;
} else if (percentage <= APM_LOW) {
- battery_status = 0x01;
- battery_flag = 0x02;
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ info->battery_flag = APM_BATTERY_FLAG_LOW;
} else {
- battery_status = 0x00;
- battery_flag = 0x01;
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ info->battery_flag = APM_BATTERY_FLAG_HIGH;
}
}
- p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
- driver_version,
- (FAKE_APM_BIOS_VERSION >> 8) & 0xff,
- FAKE_APM_BIOS_VERSION & 0xff,
- 0,
- ac_line_status,
- battery_status,
- battery_flag,
- percentage,
- time_units,
- "min");
- return p - buf;
+ info->battery_life = percentage;
+ info->time = time_units;
}
-static const struct file_operations apm_bios_fops = {
- .owner = THIS_MODULE,
- .read = do_read,
- .poll = do_poll,
- .ioctl = do_ioctl,
- .open = do_open,
- .release = do_release,
-};
-
-static struct miscdevice apm_device = {
- APM_MINOR_DEV,
- "apm_bios",
- &apm_bios_fops
-};
-
static int __init apm_emu_init(void)
{
- struct proc_dir_entry *apm_proc;
-
- if (sys_ctrler != SYS_CTRLER_PMU) {
- printk(KERN_INFO "apm_emu: Requires a machine with a PMU.\n");
- return -ENODEV;
- }
-
- apm_proc = create_proc_info_entry("apm", 0, NULL, apm_emu_get_info);
- if (apm_proc)
- apm_proc->owner = THIS_MODULE;
+ apm_get_power_status = pmu_apm_get_power_status;
- if (misc_register(&apm_device) != 0)
- printk(KERN_INFO "Could not create misc. device for apm\n");
-
- pmu_register_sleep_notifier(&apm_sleep_notifier);
-
- printk(KERN_INFO "apm_emu: APM Emulation %s initialized.\n", driver_version);
+ printk(KERN_INFO "apm_emu: PMU APM Emulation initialized.\n");
return 0;
}
static void __exit apm_emu_exit(void)
{
- pmu_unregister_sleep_notifier(&apm_sleep_notifier);
- misc_deregister(&apm_device);
- remove_proc_entry("apm", NULL);
+ if (apm_get_power_status == pmu_apm_get_power_status)
+ apm_get_power_status = NULL;
- printk(KERN_INFO "apm_emu: APM Emulation removed.\n");
+ printk(KERN_INFO "apm_emu: PMU APM Emulation removed.\n");
}
module_init(apm_emu_init);
module_exit(apm_emu_exit);
MODULE_AUTHOR("Benjamin Herrenschmidt");
-MODULE_DESCRIPTION("APM emulation layer for PowerMac");
+MODULE_DESCRIPTION("APM emulation for PowerMac");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 1599dc3..76c1e8e 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -24,7 +24,7 @@ static int mouse_last_keycode;
#if defined(CONFIG_SYSCTL)
/* file(s) in /proc/sys/dev/mac_hid */
-ctl_table mac_hid_files[] = {
+static ctl_table mac_hid_files[] = {
{
.ctl_name = DEV_MAC_HID_MOUSE_BUTTON_EMULATION,
.procname = "mouse_button_emulation",
@@ -53,7 +53,7 @@ ctl_table mac_hid_files[] = {
};
/* dir in /proc/sys/dev */
-ctl_table mac_hid_dir[] = {
+static ctl_table mac_hid_dir[] = {
{
.ctl_name = DEV_MAC_HID,
.procname = "mac_hid",
@@ -65,7 +65,7 @@ ctl_table mac_hid_dir[] = {
};
/* /proc/sys/dev itself, in case that is not there yet */
-ctl_table mac_hid_root_dir[] = {
+static ctl_table mac_hid_root_dir[] = {
{
.ctl_name = CTL_DEV,
.procname = "dev",
@@ -127,7 +127,7 @@ static int emumousebtn_input_register(void)
return ret;
}
-int __init mac_hid_init(void)
+static int __init mac_hid_init(void)
{
int err;
diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c
index cc82679..112e5ef 100644
--- a/drivers/macintosh/macio_sysfs.c
+++ b/drivers/macintosh/macio_sysfs.c
@@ -41,28 +41,15 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct of_device *of;
- const char *compat;
- int cplen;
- int length;
+ struct of_device *ofdev = to_of_device(dev);
+ int len;
- of = &to_macio_device (dev)->ofdev;
- compat = of_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;
- while (cplen > 0) {
- int l;
- l = sprintf (buf, "C%s", compat);
- length += l;
- buf += l;
- l = strlen (compat) + 1;
- compat += l;
- cplen -= l;
- }
- length += sprintf(buf, "\n");
+ len = of_device_get_modalias(ofdev, buf, PAGE_SIZE);
- return length;
+ buf[len] = '\n';
+ buf[len+1] = 0;
+
+ return len+1;
}
macio_config_of_attr (name, "%s\n");
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 0acf2f7..c803d2b 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -563,7 +563,7 @@ static void media_bay_step(int i)
ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL);
hw.irq = bay->cd_irq;
hw.chipset = ide_pmac;
- bay->cd_index = ide_register_hw(&hw, NULL);
+ bay->cd_index = ide_register_hw(&hw, 0, NULL);
pmu_resume();
}
if (bay->cd_index == -1) {
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index a98a328..f8e1a13 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -606,7 +606,7 @@ static void smu_expose_childs(struct work_struct *unused)
struct device_node *np;
for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;)
- if (device_is_compatible(np, "smu-sensors"))
+ if (of_device_is_compatible(np, "smu-sensors"))
of_platform_device_create(np, "smu-sensors",
&smu->of_dev->dev);
}
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 2289034..bd55e6a 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -19,7 +19,6 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <linux/wait.h>
#include <linux/suspend.h>
#include <linux/kthread.h>
@@ -560,9 +559,9 @@ thermostat_init(void)
np = of_find_node_by_name(NULL, "fan");
if (!np)
return -ENODEV;
- if (device_is_compatible(np, "adt7460"))
+ if (of_device_is_compatible(np, "adt7460"))
therm_type = ADT7460;
- else if (device_is_compatible(np, "adt7467"))
+ else if (of_device_is_compatible(np, "adt7467"))
therm_type = ADT7467;
else
return -ENODEV;
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 78ff186..dbb2240 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -117,7 +117,6 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <linux/wait.h>
#include <linux/reboot.h>
#include <linux/kmod.h>
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 35233de..3d0354e 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -459,7 +459,8 @@ therm_of_probe( struct of_device *dev, const struct of_device_id *match )
static int
therm_of_remove( struct of_device *dev )
{
- return i2c_del_driver( &g4fan_driver );
+ i2c_del_driver( &g4fan_driver );
+ return 0;
}
static struct of_device_id therm_of_match[] = {{
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 76d2177..741a93a 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -82,6 +82,7 @@ static unsigned char cuda_rbuf[16];
static unsigned char *reply_ptr;
static int reading_reply;
static int data_index;
+static int cuda_irq;
#ifdef CONFIG_PPC
static struct device_node *vias;
#endif
@@ -160,10 +161,8 @@ int __init find_via_cuda(void)
/* Clear and enable interrupts, but only on PPC. On 68K it's done */
/* for us by the main VIA driver in arch/m68k/mac/via.c */
-#ifndef CONFIG_MAC
out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */
out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
-#endif
/* enable autopoll */
cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
@@ -181,24 +180,22 @@ int __init find_via_cuda(void)
static int __init via_cuda_start(void)
{
- unsigned int irq;
-
if (via == NULL)
return -ENODEV;
#ifdef CONFIG_MAC
- irq = IRQ_MAC_ADB;
+ cuda_irq = IRQ_MAC_ADB;
#else /* CONFIG_MAC */
- irq = irq_of_parse_and_map(vias, 0);
- if (irq == NO_IRQ) {
+ cuda_irq = irq_of_parse_and_map(vias, 0);
+ if (cuda_irq == NO_IRQ) {
printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
vias->full_name);
return -ENODEV;
}
-#endif /* CONFIG_MAP */
+#endif /* CONFIG_MAC */
- if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
- printk(KERN_ERR "via-cuda: can't request irq %d\n", irq);
+ if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
+ printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
return -EAGAIN;
}
@@ -238,6 +235,7 @@ cuda_init(void)
printk(KERN_ERR "cuda_init_via() failed\n");
return -ENODEV;
}
+ out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
return via_cuda_start();
#endif
@@ -263,15 +261,17 @@ cuda_init_via(void)
out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */
out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */
(void)in_8(&via[SR]); /* clear any left-over data */
-#ifndef CONFIG_MAC
+#ifdef CONFIG_PPC
out_8(&via[IER], 0x7f); /* disable interrupts from VIA */
(void)in_8(&via[IER]);
+#else
+ out_8(&via[IER], SR_INT); /* disable SR interrupt from VIA */
#endif
/* delay 4ms and then clear any pending interrupt */
mdelay(4);
(void)in_8(&via[SR]);
- out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+ out_8(&via[IFR], SR_INT);
/* sync with the CUDA - assert TACK without TIP */
out_8(&via[B], in_8(&via[B]) & ~TACK);
@@ -282,7 +282,7 @@ cuda_init_via(void)
/* wait for the interrupt and then clear it */
WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
(void)in_8(&via[SR]);
- out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+ out_8(&via[IFR], SR_INT);
/* finish the sync by negating TACK */
out_8(&via[B], in_8(&via[B]) | TACK);
@@ -291,7 +291,7 @@ cuda_init_via(void)
WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)");
WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
(void)in_8(&via[SR]);
- out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+ out_8(&via[IFR], SR_INT);
out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */
return 0;
@@ -428,16 +428,12 @@ cuda_start(void)
void
cuda_poll(void)
{
- unsigned long flags;
-
/* cuda_interrupt only takes a normal lock, we disable
* interrupts here to avoid re-entering and thus deadlocking.
- * An option would be to disable only the IRQ source with
- * disable_irq(), would that work on m68k ? --BenH
*/
- local_irq_save(flags);
+ disable_irq(cuda_irq);
cuda_interrupt(0, NULL);
- local_irq_restore(flags);
+ enable_irq(cuda_irq);
}
static irqreturn_t
@@ -448,15 +444,25 @@ cuda_interrupt(int irq, void *arg)
unsigned char ibuf[16];
int ibuf_len = 0;
int complete = 0;
- unsigned char virq;
spin_lock(&cuda_lock);
- virq = in_8(&via[IFR]) & 0x7f;
- out_8(&via[IFR], virq);
- if ((virq & SR_INT) == 0) {
- spin_unlock(&cuda_lock);
- return IRQ_NONE;
+ /* On powermacs, this handler is registered for the VIA IRQ. But it uses
+ * just the shift register IRQ -- other VIA interrupt sources are disabled.
+ * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
+ * we are polling, the shift register IRQ flag has already been cleared.
+ */
+
+#ifdef CONFIG_MAC
+ if (!arg)
+#endif
+ {
+ if ((in_8(&via[IFR]) & SR_INT) == 0) {
+ spin_unlock(&cuda_lock);
+ return IRQ_NONE;
+ } else {
+ out_8(&via[IFR], SR_INT);
+ }
}
status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 1b3bad6..01b8eca 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -12,6 +12,15 @@
* 1999-08-02 (jmt) - Initial rewrite for Unified ADB.
* 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org>
* - Big overhaul, should actually work now.
+ * 2006-12-31 Finn Thain <fthain@telegraphics.com.au> - Another overhaul.
+ *
+ * Suggested reading:
+ * Inside Macintosh, ch. 5 ADB Manager
+ * Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus
+ * Rockwell R6522 VIA datasheet
+ *
+ * Apple's "ADB Analyzer" bus sniffer is invaluable:
+ * ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
*/
#include <stdarg.h>
@@ -26,7 +35,6 @@
#include <asm/macints.h>
#include <asm/machw.h>
#include <asm/mac_via.h>
-#include <asm/io.h>
#include <asm/system.h>
static volatile unsigned char *via;
@@ -51,9 +59,7 @@ static volatile unsigned char *via;
#define ANH (15*RS) /* A-side data, no handshake */
/* Bits in B data register: all active low */
-#define TREQ 0x08 /* Transfer request (input) */
-#define TACK 0x10 /* Transfer acknowledge (output) */
-#define TIP 0x20 /* Transfer in progress (output) */
+#define CTLR_IRQ 0x08 /* Controller rcv status (input) */
#define ST_MASK 0x30 /* mask for selecting ADB state bits */
/* Bits in ACR */
@@ -65,8 +71,6 @@ static volatile unsigned char *via;
#define IER_SET 0x80 /* set bits in IER */
#define IER_CLR 0 /* clear bits in IER */
#define SR_INT 0x04 /* Shift register full/empty */
-#define SR_DATA 0x08 /* Shift register data */
-#define SR_CLOCK 0x10 /* Shift register clock */
/* ADB transaction states according to GMHW */
#define ST_CMD 0x00 /* ADB state: command byte */
@@ -77,7 +81,6 @@ static volatile unsigned char *via;
static int macii_init_via(void);
static void macii_start(void);
static irqreturn_t macii_interrupt(int irq, void *arg);
-static void macii_retransmit(int);
static void macii_queue_poll(void);
static int macii_probe(void);
@@ -103,29 +106,37 @@ static enum macii_state {
sending,
reading,
read_done,
- awaiting_reply
} macii_state;
-static int need_poll;
-static int command_byte;
-static int last_reply;
-static int last_active;
-
-static struct adb_request *current_req;
-static struct adb_request *last_req;
-static struct adb_request *retry_req;
-static unsigned char reply_buf[16];
-static unsigned char *reply_ptr;
-static int reply_len;
-static int reading_reply;
-static int data_index;
-static int first_byte;
-static int prefix_len;
-static int status = ST_IDLE|TREQ;
-static int last_status;
-static int driver_running;
-
-/* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
+static struct adb_request *current_req; /* first request struct in the queue */
+static struct adb_request *last_req; /* last request struct in the queue */
+static unsigned char reply_buf[16]; /* storage for autopolled replies */
+static unsigned char *reply_ptr; /* next byte in req->data or reply_buf */
+static int reading_reply; /* store reply in reply_buf else req->reply */
+static int data_index; /* index of the next byte to send from req->data */
+static int reply_len; /* number of bytes received in reply_buf or req->reply */
+static int status; /* VIA's ADB status bits captured upon interrupt */
+static int last_status; /* status bits as at previous interrupt */
+static int srq_asserted; /* have to poll for the device that asserted it */
+static int command_byte; /* the most recent command byte transmitted */
+static int autopoll_devs; /* bits set are device addresses to be polled */
+
+/* Sanity check for request queue. Doesn't check for cycles. */
+static int request_is_queued(struct adb_request *req) {
+ struct adb_request *cur;
+ unsigned long flags;
+ local_irq_save(flags);
+ cur = current_req;
+ while (cur) {
+ if (cur == req) {
+ local_irq_restore(flags);
+ return 1;
+ }
+ cur = cur->next;
+ }
+ local_irq_restore(flags);
+ return 0;
+}
/* Check for MacII style ADB */
static int macii_probe(void)
@@ -147,15 +158,16 @@ int macii_init(void)
local_irq_save(flags);
err = macii_init_via();
- if (err) return err;
+ if (err) goto out;
err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
macii_interrupt);
- if (err) return err;
+ if (err) goto out;
macii_state = idle;
+out:
local_irq_restore(flags);
- return 0;
+ return err;
}
/* initialize the hardware */
@@ -163,12 +175,12 @@ static int macii_init_via(void)
{
unsigned char x;
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;
+ /* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */
+ via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ;
/* Set up state: idle */
via[B] |= ST_IDLE;
- last_status = via[B] & (ST_MASK|TREQ);
+ last_status = via[B] & (ST_MASK|CTLR_IRQ);
/* Shift register on input */
via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;
@@ -179,81 +191,72 @@ static int macii_init_via(void)
return 0;
}
-/* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */
+/* Send an ADB poll (Talk Register 0 command prepended to the request queue) */
static void macii_queue_poll(void)
{
- static int device = 0;
- static int in_poll=0;
+ /* No point polling the active device as it will never assert SRQ, so
+ * poll the next device in the autopoll list. This could leave us
+ * stuck in a polling loop if an unprobed device is asserting SRQ.
+ * In theory, that could only happen if a device was plugged in after
+ * probing started. Unplugging it again will break the cycle.
+ * (Simply polling the next higher device often ends up polling almost
+ * every device (after wrapping around), which takes too long.)
+ */
+ int device_mask;
+ int next_device;
static struct adb_request req;
- unsigned long flags;
-
- if (in_poll) printk("macii_queue_poll: double poll!\n");
-
- in_poll++;
- if (++device > 15) device = 1;
-
- adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
- ADB_READREG(device, 0));
-
- local_irq_save(flags);
-
- req.next = current_req;
- current_req = &req;
- local_irq_restore(flags);
- macii_start();
- in_poll--;
-}
+ if (!autopoll_devs) return;
-/* Send an ADB retransmit (Talk, appended to the request queue) */
-static void macii_retransmit(int device)
-{
- static int in_retransmit = 0;
- static struct adb_request rt;
- unsigned long flags;
-
- if (in_retransmit) printk("macii_retransmit: double retransmit!\n");
+ device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1;
+ if (autopoll_devs & ~device_mask)
+ next_device = ffs(autopoll_devs & ~device_mask) - 1;
+ else
+ next_device = ffs(autopoll_devs) - 1;
- in_retransmit++;
+ BUG_ON(request_is_queued(&req));
- adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
- ADB_READREG(device, 0));
+ adb_request(&req, NULL, ADBREQ_NOSEND, 1,
+ ADB_READREG(next_device, 0));
- local_irq_save(flags);
+ req.sent = 0;
+ req.complete = 0;
+ req.reply_len = 0;
+ req.next = current_req;
if (current_req != NULL) {
- last_req->next = &rt;
- last_req = &rt;
+ current_req = &req;
} else {
- current_req = &rt;
- last_req = &rt;
+ current_req = &req;
+ last_req = &req;
}
-
- if (macii_state == idle) macii_start();
-
- local_irq_restore(flags);
- in_retransmit--;
}
/* Send an ADB request; if sync, poll out the reply 'till it's done */
static int macii_send_request(struct adb_request *req, int sync)
{
- int i;
+ int err;
+ unsigned long flags;
- i = macii_write(req);
- if (i) return i;
+ BUG_ON(request_is_queued(req));
- if (sync) {
- while (!req->complete) macii_poll();
+ local_irq_save(flags);
+ err = macii_write(req);
+ local_irq_restore(flags);
+
+ if (!err && sync) {
+ while (!req->complete) {
+ macii_poll();
+ }
+ BUG_ON(request_is_queued(req));
}
- return 0;
+
+ return err;
}
-/* Send an ADB request */
+/* Send an ADB request (append to request queue) */
static int macii_write(struct adb_request *req)
{
- unsigned long flags;
-
if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
req->complete = 1;
return -EINVAL;
@@ -264,8 +267,6 @@ static int macii_write(struct adb_request *req)
req->complete = 0;
req->reply_len = 0;
- local_irq_save(flags);
-
if (current_req != NULL) {
last_req->next = req;
last_req = req;
@@ -274,28 +275,52 @@ static int macii_write(struct adb_request *req)
last_req = req;
if (macii_state == idle) macii_start();
}
-
- local_irq_restore(flags);
return 0;
}
/* Start auto-polling */
static int macii_autopoll(int devs)
{
- /* Just ping a random default address */
- if (!(current_req || retry_req))
- macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3);
- return 0;
+ static struct adb_request req;
+ unsigned long flags;
+ int err = 0;
+
+ /* bit 1 == device 1, and so on. */
+ autopoll_devs = devs & 0xFFFE;
+
+ if (!autopoll_devs) return 0;
+
+ local_irq_save(flags);
+
+ if (current_req == NULL) {
+ /* Send a Talk Reg 0. The controller will repeatedly transmit
+ * this as long as it is idle.
+ */
+ adb_request(&req, NULL, ADBREQ_NOSEND, 1,
+ ADB_READREG(ffs(autopoll_devs) - 1, 0));
+ err = macii_write(&req);
+ }
+
+ local_irq_restore(flags);
+ return err;
+}
+
+static inline int need_autopoll(void) {
+ /* Was the last command Talk Reg 0
+ * and is the target on the autopoll list?
+ */
+ if ((command_byte & 0x0F) == 0x0C &&
+ ((1 << ((command_byte & 0xF0) >> 4)) & autopoll_devs))
+ return 0;
+ return 1;
}
/* Prod the chip without interrupts */
static void macii_poll(void)
{
- unsigned long flags;
-
- local_irq_save(flags);
- if (via[IFR] & SR_INT) macii_interrupt(0, NULL);
- local_irq_restore(flags);
+ disable_irq(IRQ_MAC_ADB);
+ macii_interrupt(0, NULL);
+ enable_irq(IRQ_MAC_ADB);
}
/* Reset the bus */
@@ -303,73 +328,34 @@ static int macii_reset_bus(void)
{
static struct adb_request req;
+ if (request_is_queued(&req))
+ return 0;
+
/* Command = 0, Address = ignored */
adb_request(&req, NULL, 0, 1, ADB_BUSRESET);
+ /* Don't want any more requests during the Global Reset low time. */
+ udelay(3000);
+
return 0;
}
/* Start sending ADB packet */
static void macii_start(void)
{
- unsigned long flags;
struct adb_request *req;
req = current_req;
- if (!req) return;
-
- /* assert macii_state == idle */
- if (macii_state != idle) {
- printk("macii_start: called while driver busy (%p %x %x)!\n",
- req, macii_state, (uint) via1[B] & (ST_MASK|TREQ));
- return;
- }
- local_irq_save(flags);
-
- /*
- * IRQ signaled ?? (means ADB controller wants to send, or might
- * be end of packet if we were reading)
- */
-#if 0 /* FIXME: This is broke broke broke, for some reason */
- if ((via[B] & TREQ) == 0) {
- printk("macii_start: weird poll stuff. huh?\n");
- /*
- * FIXME - we need to restart this on a timer
- * or a collision at boot hangs us.
- * Never set macii_state to idle here, or macii_start
- * won't be called again from send_request!
- * (need to re-check other cases ...)
- */
- /*
- * if the interrupt handler set the need_poll
- * flag, it's hopefully a SRQ poll or re-Talk
- * so we try to send here anyway
- */
- if (!need_poll) {
- if (console_loglevel == 10)
- printk("macii_start: device busy - retry %p state %d status %x!\n",
- req, macii_state,
- (uint) via[B] & (ST_MASK|TREQ));
- retry_req = req;
- /* set ADB status here ? */
- local_irq_restore(flags);
- return;
- } else {
- need_poll = 0;
- }
- }
-#endif
- /*
- * Another retry pending? (sanity check)
+ BUG_ON(req == NULL);
+
+ BUG_ON(macii_state != idle);
+
+ /* Now send it. Be careful though, that first byte of the request
+ * is actually ADB_PACKET; the real data begins at index 1!
+ * And req->nbytes is the number of bytes of real data plus one.
*/
- if (retry_req) {
- retry_req = NULL;
- }
- /* Now send it. Be careful though, that first byte of the request */
- /* is actually ADB_PACKET; the real data begins at index 1! */
-
/* store command byte */
command_byte = req->data[1];
/* Output mode */
@@ -381,115 +367,97 @@ static void macii_start(void)
macii_state = sending;
data_index = 2;
-
- local_irq_restore(flags);
}
/*
- * The notorious ADB interrupt handler - does all of the protocol handling,
- * except for starting new send operations. Relies heavily on the ADB
- * controller sending and receiving data, thereby generating SR interrupts
- * for us. This means there has to be always activity on the ADB bus, otherwise
- * the whole process dies and has to be re-kicked by sending TALK requests ...
- * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type
- * ADB the problem isn't solved yet (retransmit of the latest active TALK seems
- * a good choice; either on timeout or on a timer interrupt).
+ * The notorious ADB interrupt handler - does all of the protocol handling.
+ * Relies on the ADB controller sending and receiving data, thereby
+ * generating shift register interrupts (SR_INT) for us. This means there has
+ * to be activity on the ADB bus. The chip will poll to achieve this.
*
* The basic ADB state machine was left unchanged from the original MacII code
* by Alan Cox, which was based on the CUDA driver for PowerMac.
- * The syntax of the ADB status lines seems to be totally different on MacII,
- * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for
- * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start
- * and end of a receive packet are signaled by asserting /IRQ on the interrupt
- * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on
- * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the
- * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB
- * protocol with a logic analyzer!!)
- *
- * Note: As of 21/10/97, the MacII ADB part works including timeout detection
- * and retransmit (Talk to the last active device).
+ * The syntax of the ADB status lines is totally different on MacII,
+ * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle
+ * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving.
+ * Start and end of a receive packet are signalled by asserting /IRQ on the
+ * interrupt line (/IRQ means the CTLR_IRQ bit in port B; not to be confused
+ * with the VIA shift register interrupt. /IRQ never actually interrupts the
+ * processor, it's just an ordinary input.)
*/
static irqreturn_t macii_interrupt(int irq, void *arg)
{
- int x, adbdir;
- unsigned long flags;
+ int x;
+ static int entered;
struct adb_request *req;
- last_status = status;
-
- /* prevent races due to SCSI enabling ints */
- local_irq_save(flags);
-
- if (driver_running) {
- local_irq_restore(flags);
- return IRQ_NONE;
+ if (!arg) {
+ /* Clear the SR IRQ flag when polling. */
+ if (via[IFR] & SR_INT)
+ via[IFR] = SR_INT;
+ else
+ return IRQ_NONE;
}
- driver_running = 1;
-
- status = via[B] & (ST_MASK|TREQ);
- adbdir = via[ACR] & SR_OUT;
+ BUG_ON(entered++);
+
+ last_status = status;
+ status = via[B] & (ST_MASK|CTLR_IRQ);
switch (macii_state) {
case idle:
+ if (reading_reply) {
+ reply_ptr = current_req->reply;
+ } else {
+ BUG_ON(current_req != NULL);
+ reply_ptr = reply_buf;
+ }
+
x = via[SR];
- first_byte = x;
- /* set ADB state = even for first data byte */
- via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
- reply_buf[0] = first_byte; /* was command_byte?? */
- reply_ptr = reply_buf + 1;
- reply_len = 1;
- prefix_len = 1;
- reading_reply = 0;
-
- macii_state = reading;
- break;
+ if ((status & CTLR_IRQ) && (x == 0xFF)) {
+ /* Bus timeout without SRQ sequence:
+ * data is "FF" while CTLR_IRQ is "H"
+ */
+ reply_len = 0;
+ srq_asserted = 0;
+ macii_state = read_done;
+ } else {
+ macii_state = reading;
+ *reply_ptr = x;
+ reply_len = 1;
+ }
- case awaiting_reply:
- /* handshake etc. for II ?? */
- x = via[SR];
- first_byte = x;
/* set ADB state = even for first data byte */
via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
-
- current_req->reply[0] = first_byte;
- reply_ptr = current_req->reply + 1;
- reply_len = 1;
- prefix_len = 1;
- reading_reply = 1;
-
- macii_state = reading;
break;
case sending:
req = current_req;
if (data_index >= req->nbytes) {
- /* print an error message if a listen command has no data */
- if (((command_byte & 0x0C) == 0x08)
- /* && (console_loglevel == 10) */
- && (data_index == 2))
- printk("MacII ADB: listen command with no data: %x!\n",
- command_byte);
- /* reset to shift in */
- via[ACR] &= ~SR_OUT;
- x = via[SR];
- /* set ADB state idle - might get SRQ */
- via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
-
req->sent = 1;
+ macii_state = idle;
if (req->reply_expected) {
- macii_state = awaiting_reply;
+ reading_reply = 1;
} else {
req->complete = 1;
current_req = req->next;
if (req->done) (*req->done)(req);
- macii_state = idle;
- if (current_req || retry_req)
+
+ if (current_req)
macii_start();
else
- macii_retransmit((command_byte & 0xF0) >> 4);
+ if (need_autopoll())
+ macii_autopoll(autopoll_devs);
+ }
+
+ if (macii_state == idle) {
+ /* reset to shift in */
+ via[ACR] &= ~SR_OUT;
+ x = via[SR];
+ /* set ADB state idle - might get SRQ */
+ via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
}
} else {
via[SR] = req->data[data_index++];
@@ -505,147 +473,79 @@ static irqreturn_t macii_interrupt(int irq, void *arg)
break;
case reading:
+ x = via[SR];
+ BUG_ON((status & ST_MASK) == ST_CMD ||
+ (status & ST_MASK) == ST_IDLE);
+
+ /* Bus timeout with SRQ sequence:
+ * data is "XX FF" while CTLR_IRQ is "L L"
+ * End of packet without SRQ sequence:
+ * data is "XX...YY 00" while CTLR_IRQ is "L...H L"
+ * End of packet SRQ sequence:
+ * data is "XX...YY 00" while CTLR_IRQ is "L...L L"
+ * (where XX is the first response byte and
+ * YY is the last byte of valid response data.)
+ */
- /* timeout / SRQ handling for II hw */
- if( (first_byte == 0xFF && (reply_len-prefix_len)==2
- && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) ||
- ((reply_len-prefix_len)==3
- && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))
- {
- /*
- * possible timeout (in fact, most probably a
- * timeout, since SRQ can't be signaled without
- * transfer on the bus).
- * The last three bytes seen were FF, together
- * with the starting byte (in case we started
- * on 'idle' or 'awaiting_reply') this probably
- * makes four. So this is mostl likely #5!
- * The timeout signal is a pattern 1 0 1 0 0..
- * on /INT, meaning we missed it :-(
- */
- x = via[SR];
- if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n");
-
- if ((status & TREQ) == (last_status & TREQ)) {
- /* Not a timeout. Unsolicited SRQ? weird. */
- /* Terminate the SRQ packet and poll */
- need_poll = 1;
+ srq_asserted = 0;
+ if (!(status & CTLR_IRQ)) {
+ if (x == 0xFF) {
+ if (!(last_status & CTLR_IRQ)) {
+ macii_state = read_done;
+ reply_len = 0;
+ srq_asserted = 1;
+ }
+ } else if (x == 0x00) {
+ macii_state = read_done;
+ if (!(last_status & CTLR_IRQ))
+ srq_asserted = 1;
}
- /* There's no packet to get, so reply is blank */
- via[B] ^= ST_MASK;
- reply_ptr -= (reply_len-prefix_len);
- reply_len = prefix_len;
- macii_state = read_done;
- break;
- } /* end timeout / SRQ handling for II hw. */
-
- if((reply_len-prefix_len)>3
- && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
- {
- /* SRQ tacked on data packet */
- /* Terminate the packet (SRQ never ends) */
- x = via[SR];
- macii_state = read_done;
- reply_len -= 3;
- reply_ptr -= 3;
- need_poll = 1;
- /* need to continue; next byte not seen else */
- } else {
- /* Sanity check */
- if (reply_len > 15) reply_len = 0;
- /* read byte */
- x = via[SR];
- *reply_ptr = x;
+ }
+
+ if (macii_state == reading) {
+ BUG_ON(reply_len > 15);
reply_ptr++;
+ *reply_ptr = x;
reply_len++;
}
- /* The usual handshake ... */
-
- /*
- * NetBSD hints that the next to last byte
- * is sent with IRQ !!
- * Guido found out it's the last one (0x0),
- * but IRQ should be asserted already.
- * Problem with timeout detection: First
- * transition to /IRQ might be second
- * byte of timeout packet!
- * Timeouts are signaled by 4x FF.
- */
- if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */
- /* invert state bits, toggle ODD/EVEN */
- via[B] ^= ST_MASK;
- /* adjust packet length */
- reply_len--;
- reply_ptr--;
- macii_state = read_done;
- } else {
- /* not caught: ST_CMD */
- /* required for re-entry 'reading'! */
- if ((status & ST_MASK) == ST_IDLE) {
- /* (in)sanity check - set even */
- via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
- } else {
- /* invert state bits */
- via[B] ^= ST_MASK;
- }
- }
+ /* invert state bits, toggle ODD/EVEN */
+ via[B] ^= ST_MASK;
break;
case read_done:
x = via[SR];
+
if (reading_reply) {
+ reading_reply = 0;
req = current_req;
- req->reply_len = reply_ptr - req->reply;
+ req->reply_len = reply_len;
req->complete = 1;
current_req = req->next;
if (req->done) (*req->done)(req);
- } else {
- adb_input(reply_buf, reply_ptr - reply_buf, 0);
- }
+ } else if (reply_len && autopoll_devs)
+ adb_input(reply_buf, reply_len, 0);
- /*
- * remember this device ID; it's the latest we got a
- * reply from!
- */
- last_reply = command_byte;
- last_active = (command_byte & 0xF0) >> 4;
+ macii_state = idle;
/* SRQ seen before, initiate poll now */
- if (need_poll) {
- macii_state = idle;
+ if (srq_asserted)
macii_queue_poll();
- need_poll = 0;
- break;
- }
-
- /* set ADB state to idle */
- via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
-
- /* /IRQ seen, so the ADB controller has data for us */
- if ((via[B] & TREQ) != 0) {
- macii_state = reading;
- reply_buf[0] = command_byte;
- reply_ptr = reply_buf + 1;
- reply_len = 1;
- prefix_len = 1;
- reading_reply = 0;
- } else {
- /* no IRQ, send next packet or wait */
- macii_state = idle;
- if (current_req)
- macii_start();
- else
- macii_retransmit(last_active);
- }
+ if (current_req)
+ macii_start();
+ else
+ if (need_autopoll())
+ macii_autopoll(autopoll_devs);
+
+ if (macii_state == idle)
+ via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
break;
default:
break;
}
- /* reset mutex and interrupts */
- driver_running = 0;
- local_irq_restore(flags);
+
+ entered--;
return IRQ_HANDLED;
}
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index fc89a70..55ad956 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -31,7 +31,6 @@ 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)
{
@@ -41,7 +40,7 @@ static void pmu_req_done(struct adb_request * req)
/* 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)
+ if (requested_change != -1 && !pmu_sys_suspended)
pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
/* reset requested change */
requested_change = -1;
@@ -66,7 +65,7 @@ static void pmu_led_set(struct led_classdev *led_cdev,
break;
}
/* if request isn't done, then don't do anything */
- if (pmu_blink_req.complete && !sleeping)
+ if (pmu_blink_req.complete && !pmu_sys_suspended)
pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
out:
spin_unlock_irqrestore(&pmu_blink_lock, flags);
@@ -80,32 +79,6 @@ static struct led_classdev pmu_led = {
.brightness_set = pmu_led_set,
};
-#ifdef CONFIG_PM
-static void 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);
-}
-
-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;
@@ -135,9 +108,7 @@ static int __init via_pmu_led_init(void)
/* 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);
}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 1729d3f..157080b 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -310,14 +310,14 @@ int __init find_via_pmu(void)
PMU_INT_TICK;
if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
- || device_is_compatible(vias->parent, "ohare")))
+ || of_device_is_compatible(vias->parent, "ohare")))
pmu_kind = PMU_OHARE_BASED;
- else if (device_is_compatible(vias->parent, "paddington"))
+ else if (of_device_is_compatible(vias->parent, "paddington"))
pmu_kind = PMU_PADDINGTON_BASED;
- else if (device_is_compatible(vias->parent, "heathrow"))
+ else if (of_device_is_compatible(vias->parent, "heathrow"))
pmu_kind = PMU_HEATHROW_BASED;
- else if (device_is_compatible(vias->parent, "Keylargo")
- || device_is_compatible(vias->parent, "K2-Keylargo")) {
+ else if (of_device_is_compatible(vias->parent, "Keylargo")
+ || of_device_is_compatible(vias->parent, "K2-Keylargo")) {
struct device_node *gpiop;
struct device_node *adbp;
u64 gaddr = OF_BAD_ADDR;
@@ -2759,7 +2759,7 @@ pmu_polled_request(struct adb_request *req)
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
-static int pmu_sys_suspended;
+int pmu_sys_suspended;
static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
{
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 356c721..dfdf11c 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -111,7 +111,6 @@ static int pmu_send_request(struct adb_request *req, int sync);
static int pmu_autopoll(int devs);
void pmu_poll(void);
static int pmu_reset_bus(void);
-static int pmu_queue_request(struct adb_request *req);
static void pmu_start(void);
static void send_byte(int x);
@@ -475,7 +474,7 @@ pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
return pmu_queue_request(req);
}
-static int
+int
pmu_queue_request(struct adb_request *req)
{
unsigned long flags;
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 94c117e..192b26e 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -27,7 +27,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <linux/kthread.h>
#include <linux/jiffies.h>
#include <linux/reboot.h>
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index ab4d1b6..a0fabf3 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -188,10 +188,10 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
if (loc == NULL || addr == 0)
continue;
/* real lm75 */
- if (device_is_compatible(dev, "lm75"))
+ if (of_device_is_compatible(dev, "lm75"))
wf_lm75_create(adapter, addr, 0, loc);
/* ds1775 (compatible, better resolution */
- else if (device_is_compatible(dev, "ds1775"))
+ else if (of_device_is_compatible(dev, "ds1775"))
wf_lm75_create(adapter, addr, 1, loc);
}
return 0;
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index eaa74af..5f03aab 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -131,7 +131,7 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
*/
if (!pmac_i2c_match_adapter(dev, adapter))
continue;
- if (!device_is_compatible(dev, "max6690"))
+ if (!of_device_is_compatible(dev, "max6690"))
continue;
addr = pmac_i2c_get_dev_addr(dev);
loc = of_get_property(dev, "hwsensor-location", NULL);
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index ff398ad..58c2590 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -263,7 +263,7 @@ static int __init smu_controls_init(void)
/* Look for RPM fans */
for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;)
if (!strcmp(fans->name, "rpm-fans") ||
- device_is_compatible(fans, "smu-rpm-fans"))
+ of_device_is_compatible(fans, "smu-rpm-fans"))
break;
for (fan = NULL;
fans && (fan = of_get_next_child(fans, fan)) != NULL;) {
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 9a6c2cf..1043b39 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -380,7 +380,7 @@ static int wf_sat_attach(struct i2c_adapter *adapter)
busnode = pmac_i2c_get_bus_node(bus);
while ((dev = of_get_next_child(busnode, dev)) != NULL)
- if (device_is_compatible(dev, "smu-sat"))
+ if (of_device_is_compatible(dev, "smu-sat"))
wf_sat_create(adapter, dev);
return 0;
}
OpenPOWER on IntegriCloud