macintosh/via-pmu: Add support for m68k PowerBooks
Put #ifdefs around the Open Firmware, xmon, interrupt dispatch, battery and suspend code. Add the necessary interrupt handling to support m68k PowerBooks. The pmu_kind value is available to userspace using the PMU_IOC_GET_MODEL ioctl. It is not clear yet what hardware classes are be needed to describe m68k PowerBook models, so pmu_kind is given the provisional value PMU_UNKNOWN. To find out about the hardware, user programs can use /proc/bootinfo or /proc/hardware, or send the PMU_GET_VERSION command using /dev/adb. Tested-by: Stan Johnson <userm57@yahoo.com> Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
c70c35da52
commit
c16a85a5aa
|
@ -65,7 +65,7 @@ config ADB_CUDA
|
|||
If unsure say Y.
|
||||
|
||||
config ADB_PMU
|
||||
bool "Support for PMU based PowerMacs"
|
||||
bool "Support for PMU based PowerMacs and PowerBooks"
|
||||
depends on PPC_PMAC
|
||||
help
|
||||
On PowerBooks, iBooks, and recent iMacs and Power Macintoshes, the
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device driver for the via-pmu on Apple Powermacs.
|
||||
* Device driver for the PMU in Apple PowerBooks and PowerMacs.
|
||||
*
|
||||
* The VIA (versatile interface adapter) interfaces to the PMU,
|
||||
* a 6805 microprocessor core whose primary function is to control
|
||||
|
@ -49,20 +49,26 @@
|
|||
#include <linux/compat.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/irq.h>
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/pmac_pfunc.h>
|
||||
#include <asm/pmac_low_i2c.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/backlight.h>
|
||||
#else
|
||||
#include <asm/macintosh.h>
|
||||
#include <asm/macints.h>
|
||||
#include <asm/mac_via.h>
|
||||
#endif
|
||||
|
||||
#include "via-pmu-event.h"
|
||||
|
||||
|
@ -97,8 +103,13 @@ static DEFINE_MUTEX(pmu_info_proc_mutex);
|
|||
#define ANH (15*RS) /* A-side data, no handshake */
|
||||
|
||||
/* Bits in B data register: both active low */
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
#define TACK 0x08 /* Transfer acknowledge (input) */
|
||||
#define TREQ 0x10 /* Transfer request (output) */
|
||||
#else
|
||||
#define TACK 0x02
|
||||
#define TREQ 0x04
|
||||
#endif
|
||||
|
||||
/* Bits in ACR */
|
||||
#define SR_CTRL 0x1c /* Shift register control bits */
|
||||
|
@ -140,13 +151,15 @@ static int data_index;
|
|||
static int data_len;
|
||||
static volatile int adb_int_pending;
|
||||
static volatile int disable_poll;
|
||||
static struct device_node *vias;
|
||||
static int pmu_kind = PMU_UNKNOWN;
|
||||
static int pmu_fully_inited;
|
||||
static int pmu_has_adb;
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
static volatile unsigned char __iomem *via1;
|
||||
static volatile unsigned char __iomem *via2;
|
||||
static struct device_node *vias;
|
||||
static struct device_node *gpio_node;
|
||||
#endif
|
||||
static unsigned char __iomem *gpio_reg;
|
||||
static int gpio_irq = 0;
|
||||
static int gpio_irq_enabled = -1;
|
||||
|
@ -273,6 +286,7 @@ static char *pbook_type[] = {
|
|||
|
||||
int __init find_via_pmu(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
u64 taddr;
|
||||
const u32 *reg;
|
||||
|
||||
|
@ -355,9 +369,6 @@ int __init find_via_pmu(void)
|
|||
if (!init_pmu())
|
||||
goto fail_init;
|
||||
|
||||
printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n",
|
||||
PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
|
||||
|
||||
sys_ctrler = SYS_CTRLER_PMU;
|
||||
|
||||
return 1;
|
||||
|
@ -373,6 +384,30 @@ int __init find_via_pmu(void)
|
|||
vias = NULL;
|
||||
pmu_state = uninitialized;
|
||||
return 0;
|
||||
#else
|
||||
if (macintosh_config->adb_type != MAC_ADB_PB2)
|
||||
return 0;
|
||||
|
||||
pmu_kind = PMU_UNKNOWN;
|
||||
|
||||
spin_lock_init(&pmu_lock);
|
||||
|
||||
pmu_has_adb = 1;
|
||||
|
||||
pmu_intr_mask = PMU_INT_PCEJECT |
|
||||
PMU_INT_SNDBRT |
|
||||
PMU_INT_ADB |
|
||||
PMU_INT_TICK;
|
||||
|
||||
pmu_state = idle;
|
||||
|
||||
if (!init_pmu()) {
|
||||
pmu_state = uninitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#endif /* !CONFIG_PPC_PMAC */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADB
|
||||
|
@ -396,13 +431,14 @@ static int pmu_init(void)
|
|||
*/
|
||||
static int __init via_pmu_start(void)
|
||||
{
|
||||
unsigned int irq;
|
||||
unsigned int __maybe_unused irq;
|
||||
|
||||
if (pmu_state == uninitialized)
|
||||
return -ENODEV;
|
||||
|
||||
batt_req.complete = 1;
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
irq = irq_of_parse_and_map(vias, 0);
|
||||
if (!irq) {
|
||||
printk(KERN_ERR "via-pmu: can't map interrupt\n");
|
||||
|
@ -439,6 +475,19 @@ static int __init via_pmu_start(void)
|
|||
|
||||
/* Enable interrupts */
|
||||
out_8(&via1[IER], IER_SET | SR_INT | CB1_INT);
|
||||
#else
|
||||
if (request_irq(IRQ_MAC_ADB_SR, via_pmu_interrupt, IRQF_NO_SUSPEND,
|
||||
"VIA-PMU-SR", NULL)) {
|
||||
pr_err("%s: couldn't get SR irq\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (request_irq(IRQ_MAC_ADB_CL, via_pmu_interrupt, IRQF_NO_SUSPEND,
|
||||
"VIA-PMU-CL", NULL)) {
|
||||
pr_err("%s: couldn't get CL irq\n", __func__);
|
||||
free_irq(IRQ_MAC_ADB_SR, NULL);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* !CONFIG_PPC_PMAC */
|
||||
|
||||
pmu_fully_inited = 1;
|
||||
|
||||
|
@ -589,6 +638,10 @@ init_pmu(void)
|
|||
option_server_mode ? "enabled" : "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n",
|
||||
PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -627,6 +680,7 @@ static void pmu_set_server_mode(int server_mode)
|
|||
static void
|
||||
done_battery_state_ohare(struct adb_request* req)
|
||||
{
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
/* format:
|
||||
* [0] : flags
|
||||
* 0x01 : AC indicator
|
||||
|
@ -708,6 +762,7 @@ done_battery_state_ohare(struct adb_request* req)
|
|||
pmu_batteries[pmu_cur_battery].amperage = amperage;
|
||||
pmu_batteries[pmu_cur_battery].voltage = voltage;
|
||||
pmu_batteries[pmu_cur_battery].time_remaining = time;
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
||||
clear_bit(0, &async_req_locks);
|
||||
}
|
||||
|
@ -1356,6 +1411,7 @@ next:
|
|||
}
|
||||
pmu_done(req);
|
||||
} else {
|
||||
#ifdef CONFIG_XMON
|
||||
if (len == 4 && data[1] == 0x2c) {
|
||||
extern int xmon_wants_key, xmon_adb_keycode;
|
||||
if (xmon_wants_key) {
|
||||
|
@ -1363,6 +1419,7 @@ next:
|
|||
return;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_XMON */
|
||||
#ifdef CONFIG_ADB
|
||||
/*
|
||||
* XXX On the [23]400 the PMU gives us an up
|
||||
|
@ -1530,7 +1587,25 @@ via_pmu_interrupt(int irq, void *arg)
|
|||
++disable_poll;
|
||||
|
||||
for (;;) {
|
||||
intr = in_8(&via1[IFR]) & (SR_INT | CB1_INT);
|
||||
/* On 68k Macs, VIA interrupts are dispatched individually.
|
||||
* Unless we are polling, the relevant IRQ flag has already
|
||||
* been cleared.
|
||||
*/
|
||||
intr = 0;
|
||||
if (IS_ENABLED(CONFIG_PPC_PMAC) || !irq) {
|
||||
intr = in_8(&via1[IFR]) & (SR_INT | CB1_INT);
|
||||
out_8(&via1[IFR], intr);
|
||||
}
|
||||
#ifndef CONFIG_PPC_PMAC
|
||||
switch (irq) {
|
||||
case IRQ_MAC_ADB_CL:
|
||||
intr = CB1_INT;
|
||||
break;
|
||||
case IRQ_MAC_ADB_SR:
|
||||
intr = SR_INT;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (intr == 0)
|
||||
break;
|
||||
handled = 1;
|
||||
|
@ -1540,7 +1615,6 @@ via_pmu_interrupt(int irq, void *arg)
|
|||
intr, in_8(&via1[IER]), pmu_state);
|
||||
break;
|
||||
}
|
||||
out_8(&via1[IFR], intr);
|
||||
if (intr & CB1_INT) {
|
||||
adb_int_pending = 1;
|
||||
pmu_irq_stats[0]++;
|
||||
|
@ -1550,6 +1624,9 @@ via_pmu_interrupt(int irq, void *arg)
|
|||
if (req)
|
||||
break;
|
||||
}
|
||||
#ifndef CONFIG_PPC_PMAC
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
recheck:
|
||||
|
@ -1616,7 +1693,7 @@ pmu_unlock(void)
|
|||
}
|
||||
|
||||
|
||||
static irqreturn_t
|
||||
static __maybe_unused irqreturn_t
|
||||
gpio1_interrupt(int irq, void *arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -2250,6 +2327,7 @@ static int pmu_ioctl(struct file *filp,
|
|||
int error = -EINVAL;
|
||||
|
||||
switch (cmd) {
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
case PMU_IOC_SLEEP:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
@ -2259,6 +2337,7 @@ static int pmu_ioctl(struct file *filp,
|
|||
return put_user(0, argp);
|
||||
else
|
||||
return put_user(1, argp);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
|
||||
/* Compatibility ioctl's for backlight */
|
||||
|
|
Loading…
Reference in New Issue