Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c16a85a5 authored by Finn Thain's avatar Finn Thain Committed by Michael Ellerman
Browse files

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: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent c70c35da
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+90 −11
Original line number Diff line number Diff line
// 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 @@ pmu_handle_data(unsigned char *data, int len)
			}
			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 @@ pmu_handle_data(unsigned char *data, int len)
					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 (;;) {
		/* 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 */