^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Device driver for the PMU in Apple PowerBooks and PowerMacs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * The VIA (versatile interface adapter) interfaces to the PMU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * a 6805 microprocessor core whose primary function is to control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * battery charging and system power on the PowerBook 3400 and 2400.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * The PMU also controls the ADB (Apple Desktop Bus) which connects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * to the keyboard and mouse, as well as the non-volatile RAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * and the RTC (real time clock) chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2001-2002 Benjamin Herrenschmidt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2006-2007 Johannes Berg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * THIS DRIVER IS BECOMING A TOTAL MESS !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - Cleanup atomically disabling reply to PMU events after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * a sleep or a freq. switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/adb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/pmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/cuda.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/syscore_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/pgtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <asm/pmac_feature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <asm/pmac_pfunc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <asm/pmac_low_i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <asm/cputable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <asm/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <asm/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <asm/macintosh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <asm/macints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <asm/mac_via.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include "via-pmu-event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Some compile options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #undef DEBUG_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* How many iterations between battery polls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define BATTERY_POLLING_COUNT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static DEFINE_MUTEX(pmu_info_proc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* VIA registers - spaced 0x200 bytes apart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define RS 0x200 /* skip between registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define B 0 /* B-side data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define A RS /* A-side data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define DIRB (2*RS) /* B-side direction (1=output) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define DIRA (3*RS) /* A-side direction (1=output) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SR (10*RS) /* Shift register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define ACR (11*RS) /* Auxiliary control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define PCR (12*RS) /* Peripheral control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define IFR (13*RS) /* Interrupt flag register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define IER (14*RS) /* Interrupt enable register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define ANH (15*RS) /* A-side data, no handshake */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Bits in B data register: both active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define TACK 0x08 /* Transfer acknowledge (input) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define TREQ 0x10 /* Transfer request (output) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define TACK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define TREQ 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Bits in ACR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define SR_CTRL 0x1c /* Shift register control bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define SR_EXT 0x0c /* Shift on external clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define SR_OUT 0x10 /* Shift out if 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Bits in IFR and IER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define IER_SET 0x80 /* set bits in IER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define IER_CLR 0 /* clear bits in IER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define SR_INT 0x04 /* Shift register full/empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define CB2_INT 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define CB1_INT 0x10 /* transition on CB1 input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static volatile enum pmu_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) uninitialized = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) idle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) sending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) intack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) reading,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) reading_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) locked,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } pmu_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static volatile enum int_data_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int_data_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int_data_fill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int_data_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int_data_flush
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } int_data_state[2] = { int_data_empty, int_data_empty };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static struct adb_request *current_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct adb_request *last_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct adb_request *req_awaiting_reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static unsigned char interrupt_data[2][32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int interrupt_data_len[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int int_data_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static unsigned char *reply_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int data_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static volatile int adb_int_pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static volatile int disable_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int pmu_kind = PMU_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static int pmu_fully_inited;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static int pmu_has_adb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static volatile unsigned char __iomem *via1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static volatile unsigned char __iomem *via2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static struct device_node *vias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static struct device_node *gpio_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static unsigned char __iomem *gpio_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int gpio_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int gpio_irq_enabled = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static volatile int pmu_suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static spinlock_t pmu_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static u8 pmu_intr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int pmu_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int drop_interrupts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int option_lid_wakeup = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static unsigned long async_req_locks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define NUM_IRQ_STATS 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static unsigned int pmu_irq_stats[NUM_IRQ_STATS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct proc_dir_entry *proc_pmu_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static struct proc_dir_entry *proc_pmu_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static struct proc_dir_entry *proc_pmu_irqstats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static struct proc_dir_entry *proc_pmu_options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static int option_server_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int pmu_battery_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int pmu_cur_battery;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int pmu_power_flags = PMU_PWR_AC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int query_batt_timer = BATTERY_POLLING_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static struct adb_request batt_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int __fake_sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int asleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #ifdef CONFIG_ADB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int adb_dev_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int pmu_adb_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int pmu_probe(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int pmu_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int pmu_send_request(struct adb_request *req, int sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static int pmu_adb_autopoll(int devs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int pmu_adb_reset_bus(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #endif /* CONFIG_ADB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int init_pmu(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void pmu_start(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static irqreturn_t via_pmu_interrupt(int irq, void *arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static irqreturn_t gpio1_interrupt(int irq, void *arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int pmu_info_proc_show(struct seq_file *m, void *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int pmu_irqstats_proc_show(struct seq_file *m, void *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int pmu_battery_proc_show(struct seq_file *m, void *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static void pmu_pass_intr(unsigned char *data, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const struct proc_ops pmu_options_proc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #ifdef CONFIG_ADB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) const struct adb_driver via_pmu_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .name = "PMU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .probe = pmu_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .init = pmu_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .send_request = pmu_send_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .autopoll = pmu_adb_autopoll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .poll = pmu_poll_adb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .reset_bus = pmu_adb_reset_bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #endif /* CONFIG_ADB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) extern void low_sleep_handler(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) extern void enable_kernel_altivec(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) extern void enable_kernel_fp(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #ifdef DEBUG_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int pmu_polled_request(struct adb_request *req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void pmu_blink(int n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * This table indicates for each PMU opcode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * - the number of data bytes to be sent with the command, or -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * if a length byte should be sent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * - the number of response bytes which the PMU will return, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * -1 if it will send a length byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static const s8 pmu_data_len[256][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* 0 1 2 3 4 5 6 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*10*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /*18*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*20*/ {-1, 0},{ 0, 0},{ 2, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*28*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /*30*/ { 4, 0},{20, 0},{-1, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*38*/ { 0, 4},{ 0,20},{ 2,-1},{ 2, 1},{ 3,-1},{-1,-1},{-1,-1},{ 4, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*40*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /*48*/ { 0, 1},{ 0, 1},{-1,-1},{ 1, 0},{ 1, 0},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*50*/ { 1, 0},{ 0, 0},{ 2, 0},{ 2, 0},{-1, 0},{ 1, 0},{ 3, 0},{ 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*58*/ { 0, 1},{ 1, 0},{ 0, 2},{ 0, 2},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*60*/ { 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*68*/ { 0, 3},{ 0, 3},{ 0, 2},{ 0, 8},{ 0,-1},{ 0,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /*70*/ { 1, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /*78*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{ 5, 1},{ 4, 1},{ 4, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*80*/ { 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*88*/ { 0, 5},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*90*/ { 1, 0},{ 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*98*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*a0*/ { 2, 0},{ 2, 0},{ 2, 0},{ 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /*a8*/ { 1, 1},{ 1, 0},{ 3, 0},{ 2, 0},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*b0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*b8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /*c0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /*c8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*d0*/ { 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*d8*/ { 1, 1},{ 1, 1},{-1,-1},{-1,-1},{ 0, 1},{ 0,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /*e0*/ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{ 4, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*e8*/ { 3,-1},{-1,-1},{ 0, 1},{-1,-1},{ 0,-1},{-1,-1},{-1,-1},{ 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /*f0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*f8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static char *pbook_type[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) "Unknown PowerBook",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) "PowerBook 2400/3400/3500(G3)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) "PowerBook G3 Series",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) "1999 PowerBook G3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) "Core99"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int __init find_via_pmu(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) u64 taddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) const u32 *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (pmu_state != uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) vias = of_find_node_by_name(NULL, "via-pmu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (vias == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) reg = of_get_property(vias, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (reg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) printk(KERN_ERR "via-pmu: No \"reg\" property !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) taddr = of_translate_address(vias, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (taddr == OF_BAD_ADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) printk(KERN_ERR "via-pmu: Can't translate address !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) spin_lock_init(&pmu_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pmu_has_adb = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pmu_intr_mask = PMU_INT_PCEJECT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) PMU_INT_SNDBRT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) PMU_INT_ADB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) PMU_INT_TICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (of_node_name_eq(vias->parent, "ohare") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) of_device_is_compatible(vias->parent, "ohare"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pmu_kind = PMU_OHARE_BASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) else if (of_device_is_compatible(vias->parent, "paddington"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) pmu_kind = PMU_PADDINGTON_BASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) else if (of_device_is_compatible(vias->parent, "heathrow"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pmu_kind = PMU_HEATHROW_BASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) else if (of_device_is_compatible(vias->parent, "Keylargo")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) || of_device_is_compatible(vias->parent, "K2-Keylargo")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct device_node *gpiop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct device_node *adbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) u64 gaddr = OF_BAD_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) pmu_kind = PMU_KEYLARGO_BASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) adbp = of_find_node_by_type(NULL, "adb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) pmu_has_adb = (adbp != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) of_node_put(adbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) pmu_intr_mask = PMU_INT_PCEJECT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) PMU_INT_SNDBRT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) PMU_INT_ADB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) PMU_INT_TICK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) PMU_INT_ENVIRONMENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) gpiop = of_find_node_by_name(NULL, "gpio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (gpiop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) reg = of_get_property(gpiop, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) gaddr = of_translate_address(gpiop, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (gaddr != OF_BAD_ADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) gpio_reg = ioremap(gaddr, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) of_node_put(gpiop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (gpio_reg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) printk(KERN_ERR "via-pmu: Can't find GPIO reg !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) pmu_kind = PMU_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) via1 = via2 = ioremap(taddr, 0x2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (via1 == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) printk(KERN_ERR "via-pmu: Can't map address !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) goto fail_via_remap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) out_8(&via1[IER], IER_CLR | 0x7f); /* disable all intrs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) out_8(&via1[IFR], 0x7f); /* clear IFR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) pmu_state = idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!init_pmu())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto fail_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sys_ctrler = SYS_CTRLER_PMU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) fail_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) iounmap(via1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) via1 = via2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) fail_via_remap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) iounmap(gpio_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) gpio_reg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) of_node_put(vias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) vias = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pmu_state = uninitialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (macintosh_config->adb_type != MAC_ADB_PB2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) pmu_kind = PMU_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) spin_lock_init(&pmu_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pmu_has_adb = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) pmu_intr_mask = PMU_INT_PCEJECT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) PMU_INT_SNDBRT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) PMU_INT_ADB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) PMU_INT_TICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) pmu_state = idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (!init_pmu()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) pmu_state = uninitialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #endif /* !CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #ifdef CONFIG_ADB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static int pmu_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return pmu_state == uninitialized ? -ENODEV : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static int pmu_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return pmu_state == uninitialized ? -ENODEV : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) #endif /* CONFIG_ADB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * We can't wait until pmu_init gets called, that happens too late.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * It happens after IDE and SCSI initialization, which can take a few
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * seconds, and by that time the PMU could have given up on us and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * turned us off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * Thus this is called with arch_initcall rather than device_initcall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static int __init via_pmu_start(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) unsigned int __maybe_unused irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) batt_req.complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) irq = irq_of_parse_and_map(vias, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (!irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) printk(KERN_ERR "via-pmu: can't map interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* We set IRQF_NO_SUSPEND because we don't want the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * to be disabled between the 2 passes of driver suspend, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * control our own disabling for that one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (request_irq(irq, via_pmu_interrupt, IRQF_NO_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) "VIA-PMU", (void *)0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) printk(KERN_ERR "via-pmu: can't request irq %d\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (pmu_kind == PMU_KEYLARGO_BASED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) gpio_node = of_find_node_by_name(NULL, "extint-gpio1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (gpio_node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) gpio_node = of_find_node_by_name(NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) "pmu-interrupt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (gpio_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) gpio_irq = irq_of_parse_and_map(gpio_node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (gpio_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (request_irq(gpio_irq, gpio1_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) IRQF_NO_SUSPEND, "GPIO1 ADB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) (void *)0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) printk(KERN_ERR "pmu: can't get irq %d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) " (GPIO1)\n", gpio_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) gpio_irq_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* Enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) out_8(&via1[IER], IER_SET | SR_INT | CB1_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (request_irq(IRQ_MAC_ADB_SR, via_pmu_interrupt, IRQF_NO_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) "VIA-PMU-SR", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pr_err("%s: couldn't get SR irq\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (request_irq(IRQ_MAC_ADB_CL, via_pmu_interrupt, IRQF_NO_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) "VIA-PMU-CL", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) pr_err("%s: couldn't get CL irq\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) free_irq(IRQ_MAC_ADB_SR, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) #endif /* !CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) pmu_fully_inited = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* Make sure PMU settle down before continuing. This is _very_ important
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * since the IDE probe may shut interrupts down for quite a bit of time. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * a PMU communication is pending while this happens, the PMU may timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * Not that on Core99 machines, the PMU keeps sending us environement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * messages, we should find a way to either fix IDE or make it call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * pmu_suspend() before masking interrupts. This can also happens while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * scolling with some fbdevs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) } while (pmu_state != idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) arch_initcall(via_pmu_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * This has to be done after pci_init, which is a subsys_initcall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static int __init via_pmu_dev_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) #ifdef CONFIG_PMAC_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* Initialize backlight */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pmu_backlight_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) #ifdef CONFIG_PPC32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (of_machine_is_compatible("AAPL,3400/2400") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) of_machine_is_compatible("AAPL,3500")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) NULL, PMAC_MB_INFO_MODEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pmu_battery_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (mb == PMAC_TYPE_COMET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) pmu_batteries[0].flags |= PMU_BATT_TYPE_COMET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) pmu_batteries[0].flags |= PMU_BATT_TYPE_HOOPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) } else if (of_machine_is_compatible("AAPL,PowerBook1998") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) of_machine_is_compatible("PowerBook1,1")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) pmu_battery_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct device_node* prim =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) of_find_node_by_name(NULL, "power-mgt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) const u32 *prim_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (prim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) prim_info = of_get_property(prim, "prim-info", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (prim_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* Other stuffs here yet unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) pmu_battery_count = (prim_info[6] >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (pmu_battery_count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) of_node_put(prim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) #endif /* CONFIG_PPC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* Create /proc/pmu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) proc_pmu_root = proc_mkdir("pmu", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (proc_pmu_root) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) for (i=0; i<pmu_battery_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) char title[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) sprintf(title, "battery_%ld", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) proc_pmu_batt[i] = proc_create_single_data(title, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) proc_pmu_root, pmu_battery_proc_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) (void *)i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) proc_pmu_info = proc_create_single("info", 0, proc_pmu_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pmu_info_proc_show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) proc_pmu_irqstats = proc_create_single("interrupts", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) proc_pmu_root, pmu_irqstats_proc_show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) proc_pmu_options = proc_create("options", 0600, proc_pmu_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) &pmu_options_proc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) device_initcall(via_pmu_dev_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) init_pmu(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Negate TREQ. Set TACK to input and TREQ to output. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) out_8(&via2[B], in_8(&via2[B]) | TREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) out_8(&via2[DIRB], (in_8(&via2[DIRB]) | TREQ) & ~TACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) timeout = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) while (!req.complete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (--timeout < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) printk(KERN_ERR "init_pmu: no response from PMU\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* ack all pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) timeout = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) interrupt_data[0][0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) while (interrupt_data[0][0] || pmu_state != idle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (--timeout < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) printk(KERN_ERR "init_pmu: timed out acking intrs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (pmu_state == idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* Tell PMU we are ready. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (pmu_kind == PMU_KEYLARGO_BASED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) while (!req.complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* Read PMU version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pmu_request(&req, NULL, 1, PMU_GET_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (req.reply_len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) pmu_version = req.reply[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* Read server mode setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (pmu_kind == PMU_KEYLARGO_BASED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) pmu_request(&req, NULL, 2, PMU_POWER_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) PMU_PWR_GET_POWERUP_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (req.reply_len == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (req.reply[1] & PMU_PWR_WAKEUP_AC_INSERT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) option_server_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) printk(KERN_INFO "via-pmu: Server Mode is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) option_server_mode ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) pmu_get_model(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return pmu_kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static void pmu_set_server_mode(int server_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (pmu_kind != PMU_KEYLARGO_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) option_server_mode = server_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) pmu_request(&req, NULL, 2, PMU_POWER_EVENTS, PMU_PWR_GET_POWERUP_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (req.reply_len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (server_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) pmu_request(&req, NULL, 4, PMU_POWER_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) PMU_PWR_SET_POWERUP_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) req.reply[0], PMU_PWR_WAKEUP_AC_INSERT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) pmu_request(&req, NULL, 4, PMU_POWER_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) PMU_PWR_CLR_POWERUP_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) req.reply[0], PMU_PWR_WAKEUP_AC_INSERT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /* This new version of the code for 2400/3400/3500 powerbooks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * is inspired from the implementation in gkrellm-pmu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) done_battery_state_ohare(struct adb_request* req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * [0] : flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * 0x01 : AC indicator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * 0x02 : charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * 0x04 : battery exist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * 0x08 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * 0x10 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * 0x20 : full charged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * 0x40 : pcharge reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * 0x80 : battery exist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * [1][2] : battery voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * [3] : CPU temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * [4] : battery temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * [5] : current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * [6][7] : pcharge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * --tkoba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) unsigned int bat_flags = PMU_BATT_TYPE_HOOPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) long pcharge, charge, vb, vmax, lmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) long vmax_charging, vmax_charged;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) long amperage, voltage, time, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) NULL, PMAC_MB_INFO_MODEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (req->reply[0] & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) pmu_power_flags |= PMU_PWR_AC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) pmu_power_flags &= ~PMU_PWR_AC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (mb == PMAC_TYPE_COMET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) vmax_charged = 189;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) vmax_charging = 213;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) lmax = 6500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) vmax_charged = 330;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) vmax_charging = 330;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) lmax = 6500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) vmax = vmax_charged;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* If battery installed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (req->reply[0] & 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) bat_flags |= PMU_BATT_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (req->reply[0] & 0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) bat_flags |= PMU_BATT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) vb = (req->reply[1] << 8) | req->reply[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) voltage = (vb * 265 + 72665) / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) amperage = req->reply[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if ((req->reply[0] & 0x01) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (amperage > 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) vb += ((amperage - 200) * 15)/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) } else if (req->reply[0] & 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) vb = (vb * 97) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) vmax = vmax_charging;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) charge = (100 * vb) / vmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (req->reply[0] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) pcharge = (req->reply[6] << 8) + req->reply[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (pcharge > lmax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) pcharge = lmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) pcharge *= 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) pcharge = 100 - pcharge / lmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (pcharge < charge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) charge = pcharge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (amperage > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) time = (charge * 16440) / amperage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) max = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) amperage = -amperage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) charge = max = amperage = voltage = time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) pmu_batteries[pmu_cur_battery].flags = bat_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) pmu_batteries[pmu_cur_battery].charge = charge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) pmu_batteries[pmu_cur_battery].max_charge = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) pmu_batteries[pmu_cur_battery].amperage = amperage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) pmu_batteries[pmu_cur_battery].voltage = voltage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) pmu_batteries[pmu_cur_battery].time_remaining = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) clear_bit(0, &async_req_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) done_battery_state_smart(struct adb_request* req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * [0] : format of this structure (known: 3,4,5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * [1] : flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * format 3 & 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * [2] : charge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * [3] : max charge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * [4] : current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * [5] : voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * format 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * [2][3] : charge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * [4][5] : max charge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * [6][7] : current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * [8][9] : voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) unsigned int bat_flags = PMU_BATT_TYPE_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) int amperage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) unsigned int capa, max, voltage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (req->reply[1] & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) pmu_power_flags |= PMU_PWR_AC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) pmu_power_flags &= ~PMU_PWR_AC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) capa = max = amperage = voltage = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (req->reply[1] & 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) bat_flags |= PMU_BATT_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) switch(req->reply[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) case 4: capa = req->reply[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) max = req->reply[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) amperage = *((signed char *)&req->reply[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) voltage = req->reply[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) case 5: capa = (req->reply[2] << 8) | req->reply[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) max = (req->reply[4] << 8) | req->reply[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) amperage = *((signed short *)&req->reply[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) voltage = (req->reply[8] << 8) | req->reply[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) pr_warn("pmu.c: unrecognized battery info, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) "len: %d, %4ph\n", req->reply_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) req->reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if ((req->reply[1] & 0x01) && (amperage > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) bat_flags |= PMU_BATT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) pmu_batteries[pmu_cur_battery].flags = bat_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) pmu_batteries[pmu_cur_battery].charge = capa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) pmu_batteries[pmu_cur_battery].max_charge = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) pmu_batteries[pmu_cur_battery].amperage = amperage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) pmu_batteries[pmu_cur_battery].voltage = voltage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (amperage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if ((req->reply[1] & 0x01) && (amperage > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) pmu_batteries[pmu_cur_battery].time_remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) = ((max-capa) * 3600) / amperage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) pmu_batteries[pmu_cur_battery].time_remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) = (capa * 3600) / (-amperage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) pmu_batteries[pmu_cur_battery].time_remaining = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pmu_cur_battery = (pmu_cur_battery + 1) % pmu_battery_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) clear_bit(0, &async_req_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) query_battery_state(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (test_and_set_bit(0, &async_req_locks))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (pmu_kind == PMU_OHARE_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) pmu_request(&batt_req, done_battery_state_ohare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 1, PMU_BATTERY_STATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pmu_request(&batt_req, done_battery_state_smart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static int pmu_info_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) seq_printf(m, "PMU driver version : %d\n", PMU_DRIVER_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) seq_printf(m, "PMU firmware version : %02x\n", pmu_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) seq_printf(m, "AC Power : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0) || pmu_battery_count == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) seq_printf(m, "Battery count : %d\n", pmu_battery_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int pmu_irqstats_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static const char *irq_names[NUM_IRQ_STATS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) "Unknown interrupt (type 0)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) "Unknown interrupt (type 1)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) "PC-Card eject button",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) "Sound/Brightness button",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) "ADB message",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) "Battery state change",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) "Environment interrupt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) "Tick timer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) "Ghost interrupt (zero len)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) "Empty interrupt (empty mask)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) "Max irqs in a row",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) "Total CB1 triggered events",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) "Total GPIO1 triggered events",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) for (i = 0; i < NUM_IRQ_STATS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) seq_printf(m, " %2u: %10u (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) i, pmu_irq_stats[i], irq_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static int pmu_battery_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) long batnum = (long)m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) seq_printf(m, "flags : %08x\n", pmu_batteries[batnum].flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) seq_printf(m, "charge : %d\n", pmu_batteries[batnum].charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) seq_printf(m, "max_charge : %d\n", pmu_batteries[batnum].max_charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) seq_printf(m, "current : %d\n", pmu_batteries[batnum].amperage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) seq_printf(m, "voltage : %d\n", pmu_batteries[batnum].voltage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) seq_printf(m, "time rem. : %d\n", pmu_batteries[batnum].time_remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static int pmu_options_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (pmu_kind == PMU_KEYLARGO_BASED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) seq_printf(m, "lid_wakeup=%d\n", option_lid_wakeup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (pmu_kind == PMU_KEYLARGO_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) seq_printf(m, "server_mode=%d\n", option_server_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static int pmu_options_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return single_open(file, pmu_options_proc_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) static ssize_t pmu_options_proc_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) const char __user *buffer, size_t count, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) char tmp[33];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) char *label, *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) size_t fcount = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (count > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) count = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (copy_from_user(tmp, buffer, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) tmp[count] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) label = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) while(*label == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) label++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) val = label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) while(*val && (*val != '=')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (*val == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if ((*val) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) *(val++) = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) while(*val == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (pmu_kind == PMU_KEYLARGO_BASED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (!strcmp(label, "lid_wakeup"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) option_lid_wakeup = ((*val) == '1');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) int new_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) new_value = ((*val) == '1');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (new_value != option_server_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) pmu_set_server_mode(new_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return fcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static const struct proc_ops pmu_options_proc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .proc_open = pmu_options_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .proc_read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .proc_release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .proc_write = pmu_options_proc_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) #ifdef CONFIG_ADB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* Send an ADB command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int pmu_send_request(struct adb_request *req, int sync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (pmu_state == uninitialized || !pmu_fully_inited) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) switch (req->data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case PMU_PACKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) for (i = 0; i < req->nbytes - 1; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) req->data[i] = req->data[i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) --req->nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (pmu_data_len[req->data[0]][1] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) req->reply[0] = ADB_RET_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) req->reply_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) req->reply_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) ret = pmu_queue_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case CUDA_PACKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) switch (req->data[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) case CUDA_GET_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (req->nbytes != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) req->data[0] = PMU_READ_RTC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) req->nbytes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) req->reply_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) req->reply[0] = CUDA_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) req->reply[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) req->reply[2] = CUDA_GET_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ret = pmu_queue_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) case CUDA_SET_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (req->nbytes != 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) req->data[0] = PMU_SET_RTC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) req->nbytes = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) for (i = 1; i <= 4; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) req->data[i] = req->data[i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) req->reply_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) req->reply[0] = CUDA_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) req->reply[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) req->reply[2] = CUDA_SET_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ret = pmu_queue_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) case ADB_PACKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (!pmu_has_adb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) for (i = req->nbytes - 1; i > 1; --i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) req->data[i+2] = req->data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) req->data[3] = req->nbytes - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) req->data[2] = pmu_adb_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /*req->data[1] = req->data[1];*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) req->data[0] = PMU_ADB_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) req->nbytes += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) req->reply_expected = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) req->reply_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ret = pmu_queue_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (sync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) while (!req->complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* Enable/disable autopolling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) static int __pmu_adb_autopoll(int devs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (devs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) adb_dev_map >> 8, adb_dev_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) pmu_adb_flags = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) pmu_request(&req, NULL, 1, PMU_ADB_POLL_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) pmu_adb_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) while (!req.complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static int pmu_adb_autopoll(int devs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (pmu_state == uninitialized || !pmu_fully_inited || !pmu_has_adb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) adb_dev_map = devs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return __pmu_adb_autopoll(devs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* Reset the ADB bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static int pmu_adb_reset_bus(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) int save_autopoll = adb_dev_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (pmu_state == uninitialized || !pmu_fully_inited || !pmu_has_adb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) /* anyone got a better idea?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) __pmu_adb_autopoll(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) req.nbytes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) req.done = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) req.data[0] = PMU_ADB_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) req.data[1] = ADB_BUSRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) req.data[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) req.data[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) req.data[4] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) req.reply_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) req.reply_expected = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (pmu_queue_request(&req) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (save_autopoll != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) __pmu_adb_autopoll(save_autopoll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) #endif /* CONFIG_ADB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /* Construct and send a pmu request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) int nbytes, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) va_list list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (nbytes < 0 || nbytes > 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) printk(KERN_ERR "pmu_request: bad nbytes (%d)\n", nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) req->nbytes = nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) req->done = done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) va_start(list, nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) for (i = 0; i < nbytes; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) req->data[i] = va_arg(list, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) va_end(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) req->reply_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) req->reply_expected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return pmu_queue_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) pmu_queue_request(struct adb_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) int nsend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (pmu_state == uninitialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (req->nbytes <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) nsend = pmu_data_len[req->data[0]][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (nsend >= 0 && req->nbytes != nsend + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) req->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) req->sent = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) req->complete = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (current_req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) last_req->next = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) last_req = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) current_req = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) last_req = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (pmu_state == idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) pmu_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) wait_for_ack(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* Sightly increased the delay, I had one occurrence of the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) int timeout = 4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) while ((in_8(&via2[B]) & TACK) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (--timeout < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) printk(KERN_ERR "PMU not responding (!ack)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* New PMU seems to be very sensitive to those timings, so we make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * PCI is flushed immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) send_byte(int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) out_8(&via1[ACR], in_8(&via1[ACR]) | SR_OUT | SR_EXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) out_8(&via1[SR], x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) out_8(&via2[B], in_8(&via2[B]) & ~TREQ); /* assert TREQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) (void)in_8(&via2[B]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) recv_byte(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) out_8(&via1[ACR], (in_8(&via1[ACR]) & ~SR_OUT) | SR_EXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) in_8(&via1[SR]); /* resets SR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) out_8(&via2[B], in_8(&via2[B]) & ~TREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) (void)in_8(&via2[B]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) pmu_done(struct adb_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) void (*done)(struct adb_request *) = req->done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* Here, we assume that if the request has a done member, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * struct request will survive to setting req->complete to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) (*done)(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) pmu_start(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) struct adb_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /* assert pmu_state == idle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /* get the packet to send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) req = current_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (!req || pmu_state != idle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) || (/*req->reply_expected && */req_awaiting_reply))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) pmu_state = sending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) data_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) data_len = pmu_data_len[req->data[0]][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /* Sounds safer to make sure ACK is high before writing. This helped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * kill a problem with ADB and some iBooks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) wait_for_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) /* set the shift register to shift out and send a byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) send_byte(req->data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) pmu_poll(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (disable_poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) pmu_poll_adb(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (disable_poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* Kicks ADB read when PMU is suspended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) } while (pmu_suspended && (adb_int_pending || pmu_state != idle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) || req_awaiting_reply));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) pmu_wait_complete(struct adb_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) while((pmu_state != idle && pmu_state != locked) || !req->complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /* This function loops until the PMU is idle and prevents it from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * anwsering to ADB interrupts. pmu_request can still be called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * This is done to avoid spurrious shutdowns when we know we'll have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * interrupts switched off for a long time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) pmu_suspend(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) pmu_suspended++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (pmu_suspended > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (req_awaiting_reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (gpio_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) disable_irq_nosync(gpio_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) out_8(&via1[IER], CB1_INT | IER_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) pmu_resume(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (pmu_state == uninitialized || pmu_suspended < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) pmu_suspended--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (pmu_suspended > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (gpio_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) enable_irq(gpio_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) out_8(&via1[IER], CB1_INT | IER_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) /* Interrupt data could be the result data from an ADB cmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) pmu_handle_data(unsigned char *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) unsigned char ints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) asleep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (drop_interrupts || len < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) adb_int_pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) pmu_irq_stats[8]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /* Get PMU interrupt mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) ints = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) /* Record zero interrupts for stats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (ints == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) pmu_irq_stats[9]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) /* Hack to deal with ADB autopoll flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (ints & PMU_INT_ADB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) ints &= ~(PMU_INT_ADB_AUTO | PMU_INT_AUTO_SRQ_POLL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (ints == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) if (i > pmu_irq_stats[10])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) pmu_irq_stats[10] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) idx = ffs(ints) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) ints &= ~BIT(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) pmu_irq_stats[idx]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) /* Note: for some reason, we get an interrupt with len=1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * data[0]==0 after each normal ADB interrupt, at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) * on the Pismo. Still investigating... --BenH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) switch (BIT(idx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) case PMU_INT_ADB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if ((data[0] & PMU_INT_ADB_AUTO) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) struct adb_request *req = req_awaiting_reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (!req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) printk(KERN_ERR "PMU: extra ADB reply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) req_awaiting_reply = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (len <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) req->reply_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) memcpy(req->reply, data + 1, len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) req->reply_len = len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) pmu_done(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) #ifdef CONFIG_XMON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (len == 4 && data[1] == 0x2c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) extern int xmon_wants_key, xmon_adb_keycode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (xmon_wants_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) xmon_adb_keycode = data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) #endif /* CONFIG_XMON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) #ifdef CONFIG_ADB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * XXX On the [23]400 the PMU gives us an up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * event for keycodes 0x74 or 0x75 when the PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * card eject buttons are released, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * ignore those events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!(pmu_kind == PMU_OHARE_BASED && len == 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) && data[1] == 0x2c && data[3] == 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) && (data[2] & ~1) == 0xf4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) adb_input(data+1, len-1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) #endif /* CONFIG_ADB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) /* Sound/brightness button pressed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) case PMU_INT_SNDBRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) #ifdef CONFIG_PMAC_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (len == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) /* Tick interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) case PMU_INT_TICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /* Environment or tick interrupt, query batteries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (pmu_battery_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if ((--query_batt_timer) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) query_battery_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) query_batt_timer = BATTERY_POLLING_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) case PMU_INT_ENVIRONMENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (pmu_battery_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) query_battery_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) pmu_pass_intr(data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) /* len == 6 is probably a bad check. But how do I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) * know what PMU versions send what events here? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (len == 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) via_pmu_event(PMU_EVT_POWER, !!(data[1]&8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) via_pmu_event(PMU_EVT_LID, data[1]&1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) pmu_pass_intr(data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) static struct adb_request*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) pmu_sr_intr(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) struct adb_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) int bite = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (in_8(&via2[B]) & TREQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) printk(KERN_ERR "PMU: spurious SR intr (%x)\n", in_8(&via2[B]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* The ack may not yet be low when we get the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) while ((in_8(&via2[B]) & TACK) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) /* if reading grab the byte, and reset the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (pmu_state == reading || pmu_state == reading_intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) bite = in_8(&via1[SR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) /* reset TREQ and wait for TACK to go high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) out_8(&via2[B], in_8(&via2[B]) | TREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) wait_for_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) switch (pmu_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) case sending:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) req = current_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (data_len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) data_len = req->nbytes - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) send_byte(data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (data_index <= data_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) send_byte(req->data[data_index++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) req->sent = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) data_len = pmu_data_len[req->data[0]][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (data_len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) pmu_state = idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) current_req = req->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) if (req->reply_expected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) req_awaiting_reply = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) pmu_state = reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) data_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) reply_ptr = req->reply + req->reply_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) recv_byte();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) case intack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) data_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) data_len = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) pmu_state = reading_intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) reply_ptr = interrupt_data[int_data_last];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) recv_byte();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if (gpio_irq >= 0 && !gpio_irq_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) enable_irq(gpio_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) gpio_irq_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) case reading:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) case reading_intr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (data_len == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) data_len = bite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (bite > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) printk(KERN_ERR "PMU: bad reply len %d\n", bite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) } else if (data_index < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) reply_ptr[data_index++] = bite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) if (data_index < data_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) recv_byte();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (pmu_state == reading_intr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) pmu_state = idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) int_data_state[int_data_last] = int_data_ready;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) interrupt_data_len[int_data_last] = data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) req = current_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) * For PMU sleep and freq change requests, we lock the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) * PMU until it's explicitly unlocked. This avoids any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) * spurrious event polling getting in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) current_req = req->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) req->reply_len += data_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (req->data[0] == PMU_SLEEP || req->data[0] == PMU_CPU_SPEED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) pmu_state = locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) pmu_state = idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) printk(KERN_ERR "via_pmu_interrupt: unknown state %d?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) pmu_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) static irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) via_pmu_interrupt(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) int intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) int nloop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) int int_data = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) struct adb_request *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) /* This is a bit brutal, we can probably do better */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) ++disable_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) /* On 68k Macs, VIA interrupts are dispatched individually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) * Unless we are polling, the relevant IRQ flag has already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * been cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) intr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) if (IS_ENABLED(CONFIG_PPC_PMAC) || !irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) intr = in_8(&via1[IFR]) & (SR_INT | CB1_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) out_8(&via1[IFR], intr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) #ifndef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) switch (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) case IRQ_MAC_ADB_CL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) intr = CB1_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) case IRQ_MAC_ADB_SR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) intr = SR_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) if (intr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) if (++nloop > 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) printk(KERN_DEBUG "PMU: stuck in intr loop, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) "intr=%x, ier=%x pmu_state=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) intr, in_8(&via1[IER]), pmu_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (intr & CB1_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) pmu_irq_stats[11]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) if (intr & SR_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) req = pmu_sr_intr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) if (req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) #ifndef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) recheck:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) if (pmu_state == idle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (adb_int_pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) if (int_data_state[0] == int_data_empty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) int_data_last = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) else if (int_data_state[1] == int_data_empty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) int_data_last = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) goto no_free_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) pmu_state = intack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) int_data_state[int_data_last] = int_data_fill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) /* Sounds safer to make sure ACK is high before writing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) * This helped kill a problem with ADB and some iBooks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) wait_for_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) send_byte(PMU_INT_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) adb_int_pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) } else if (current_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) pmu_start();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) no_free_slot:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) /* Mark the oldest buffer for flushing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) if (int_data_state[!int_data_last] == int_data_ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) int_data_state[!int_data_last] = int_data_flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) int_data = !int_data_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) } else if (int_data_state[int_data_last] == int_data_ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) int_data_state[int_data_last] = int_data_flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) int_data = int_data_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) --disable_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) /* Deal with completed PMU requests outside of the lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) if (req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) pmu_done(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) /* Deal with interrupt datas outside of the lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (int_data >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) ++disable_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) int_data_state[int_data] = int_data_empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) int_data = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) goto recheck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) return IRQ_RETVAL(handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) pmu_unlock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (pmu_state == locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) pmu_state = idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) static __maybe_unused irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) gpio1_interrupt(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if ((in_8(gpio_reg + 0x9) & 0x02) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) spin_lock_irqsave(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) if (gpio_irq_enabled > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) disable_irq_nosync(gpio_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) gpio_irq_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) pmu_irq_stats[12]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) spin_unlock_irqrestore(&pmu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) pmu_enable_irled(int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (pmu_kind == PMU_KEYLARGO_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) (on ? PMU_POW_ON : PMU_POW_OFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) /* Offset between Unix time (1970-based) and Mac time (1904-based) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) #define RTC_OFFSET 2082844800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) time64_t pmu_get_time(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) u32 now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) if (req.reply_len != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) pr_err("%s: got %d byte reply\n", __func__, req.reply_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) now = (req.reply[0] << 24) + (req.reply[1] << 16) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) (req.reply[2] << 8) + req.reply[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) return (time64_t)now - RTC_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) int pmu_set_rtc_time(struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) u32 now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) now = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) now >> 24, now >> 16, now >> 8, now) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) if (req.reply_len != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) pr_err("%s: got %d byte reply\n", __func__, req.reply_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) pmu_restart(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) drop_interrupts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (pmu_kind != PMU_KEYLARGO_BASED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) PMU_INT_TICK );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) while(!req.complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) pmu_request(&req, NULL, 1, PMU_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) for (;;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) pmu_shutdown(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) drop_interrupts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if (pmu_kind != PMU_KEYLARGO_BASED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) PMU_INT_TICK );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) /* Disable server mode on shutdown or we'll just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) * wake up again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) pmu_set_server_mode(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) pmu_request(&req, NULL, 5, PMU_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 'M', 'A', 'T', 'T');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) for (;;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) pmu_present(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) return pmu_state != uninitialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) * Put the powerbook to sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) static u32 save_via[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) save_via_state(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) save_via[0] = in_8(&via1[ANH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) save_via[1] = in_8(&via1[DIRA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) save_via[2] = in_8(&via1[B]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) save_via[3] = in_8(&via1[DIRB]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) save_via[4] = in_8(&via1[PCR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) save_via[5] = in_8(&via1[ACR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) save_via[6] = in_8(&via1[T1CL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) save_via[7] = in_8(&via1[T1CH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) restore_via_state(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) out_8(&via1[ANH], save_via[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) out_8(&via1[DIRA], save_via[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) out_8(&via1[B], save_via[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) out_8(&via1[DIRB], save_via[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) out_8(&via1[PCR], save_via[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) out_8(&via1[ACR], save_via[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) out_8(&via1[T1CL], save_via[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) out_8(&via1[T1CH], save_via[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) out_8(&via1[IER], IER_CLR | 0x7f); /* disable all intrs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) out_8(&via1[IFR], 0x7f); /* clear IFR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) out_8(&via1[IER], IER_SET | SR_INT | CB1_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) #define GRACKLE_PM (1<<7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) #define GRACKLE_DOZE (1<<5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) #define GRACKLE_NAP (1<<4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) #define GRACKLE_SLEEP (1<<3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) static int powerbook_sleep_grackle(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) unsigned long save_l2cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) unsigned short pmcr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) struct pci_dev *grackle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) grackle = pci_get_domain_bus_and_slot(0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) if (!grackle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) /* Turn off various things. Darwin does some retry tests here... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) /* For 750, save backside cache setting and disable it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) save_l2cr = _get_L2CR(); /* (returns -1 if not available) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) if (!__fake_sleep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) /* Ask the PMU to put us to sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) /* The VIA is supposed not to be restored correctly*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) save_via_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) /* We shut down some HW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) pci_read_config_word(grackle, 0x70, &pmcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) /* Apparently, MacOS uses NAP mode for Grackle ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) pci_write_config_word(grackle, 0x70, pmcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) /* Call low-level ASM sleep handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (__fake_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) mdelay(5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) low_sleep_handler();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) /* We're awake again, stop grackle PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) pci_read_config_word(grackle, 0x70, &pmcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) pci_write_config_word(grackle, 0x70, pmcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) pci_dev_put(grackle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) /* Make sure the PMU is idle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) restore_via_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) /* Restore L2 cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) _set_L2CR(save_l2cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) /* Restore userland MMU context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) switch_mmu_context(NULL, current->active_mm, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) /* Power things up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) pmu_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) PMU_POW0_ON|PMU_POW0_HARD_DRIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) powerbook_sleep_Core99(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) unsigned long save_l2cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) unsigned long save_l3cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) printk(KERN_ERR "Sleep mode not supported on this machine\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) if (num_online_cpus() > 1 || cpu_is_offline(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) /* Stop environment and ADB interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) /* Tell PMU what events will wake us up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) 0xff, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) 0, PMU_PWR_WAKEUP_KEY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) (option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) /* Save the state of the L2 and L3 caches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) save_l3cr = _get_L3CR(); /* (returns -1 if not available) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) save_l2cr = _get_L2CR(); /* (returns -1 if not available) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) if (!__fake_sleep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) /* Ask the PMU to put us to sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) /* The VIA is supposed not to be restored correctly*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) save_via_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) /* Shut down various ASICs. There's a chance that we can no longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) * talk to the PMU after this, so I moved it to _after_ sending the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) * sleep command to it. Still need to be checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) /* Call low-level ASM sleep handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) if (__fake_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) mdelay(5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) low_sleep_handler();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) /* Restore Apple core ASICs state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) /* Restore VIA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) restore_via_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) /* tweak LPJ before cpufreq is there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) loops_per_jiffy *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) /* Restore video */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) pmac_call_early_video_resume();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) /* Restore L2 cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) _set_L2CR(save_l2cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) /* Restore L3 cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) _set_L3CR(save_l3cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) /* Restore userland MMU context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) switch_mmu_context(NULL, current->active_mm, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) /* Tell PMU we are ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) pmu_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) /* Restore LPJ, cpufreq will adjust the cpu frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) loops_per_jiffy /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) #define PB3400_MEM_CTRL 0xf8000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) #define PB3400_MEM_CTRL_SLEEP 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) static void __iomem *pb3400_mem_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) static void powerbook_sleep_init_3400(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) /* map in the memory controller registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) if (pb3400_mem_ctrl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) printk(KERN_WARNING "ioremap failed: sleep won't be possible");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) static int powerbook_sleep_3400(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) int i, x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) unsigned int hid0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) unsigned long msr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) struct adb_request sleep_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) unsigned int __iomem *mem_ctrl_sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) if (pb3400_mem_ctrl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) /* Set the memory controller to keep the memory refreshed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) while we're asleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) for (i = 0x403f; i >= 0x4000; --i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) out_be32(mem_ctrl_sleep, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) } while (x == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (x >= 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) /* Ask the PMU to put us to sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) pmu_wait_complete(&sleep_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) pmu_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) asleep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) /* Put the CPU into sleep mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) hid0 = mfspr(SPRN_HID0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) mtspr(SPRN_HID0, hid0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) msr = mfmsr() | MSR_POW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) while (asleep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) mtmsr(msr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) isync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) /* OK, we're awake again, start restoring things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) out_be32(mem_ctrl_sleep, 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) * Support for /dev/pmu device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) #define RB_SIZE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) struct pmu_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) int rb_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) int rb_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) struct rb_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) unsigned short len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) unsigned char data[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) } rb_buf[RB_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) wait_queue_head_t wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) int backlight_locker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) static LIST_HEAD(all_pmu_pvt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) static DEFINE_SPINLOCK(all_pvt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) pmu_pass_intr(unsigned char *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) struct pmu_private *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) struct list_head *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) if (len > sizeof(pp->rb_buf[0].data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) len = sizeof(pp->rb_buf[0].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) spin_lock_irqsave(&all_pvt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) for (list = &all_pmu_pvt; (list = list->next) != &all_pmu_pvt; ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) pp = list_entry(list, struct pmu_private, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) spin_lock(&pp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) i = pp->rb_put + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) if (i >= RB_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) if (i != pp->rb_get) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) struct rb_entry *rp = &pp->rb_buf[pp->rb_put];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) rp->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) memcpy(rp->data, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) pp->rb_put = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) wake_up_interruptible(&pp->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) spin_unlock(&pp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) spin_unlock_irqrestore(&all_pvt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) pmu_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) struct pmu_private *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) pp = kmalloc(sizeof(struct pmu_private), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if (!pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) pp->rb_get = pp->rb_put = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) spin_lock_init(&pp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) init_waitqueue_head(&pp->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) mutex_lock(&pmu_info_proc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) spin_lock_irqsave(&all_pvt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) pp->backlight_locker = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) list_add(&pp->list, &all_pmu_pvt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) spin_unlock_irqrestore(&all_pvt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) file->private_data = pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) mutex_unlock(&pmu_info_proc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) pmu_read(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) struct pmu_private *pp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) if (count < 1 || !pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) spin_lock_irqsave(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) add_wait_queue(&pp->wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) if (pp->rb_get != pp->rb_put) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) int i = pp->rb_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) struct rb_entry *rp = &pp->rb_buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) ret = rp->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) spin_unlock_irqrestore(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (ret > count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) if (ret > 0 && copy_to_user(buf, rp->data, ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if (++i >= RB_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) spin_lock_irqsave(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) pp->rb_get = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) if (file->f_flags & O_NONBLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) ret = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) spin_unlock_irqrestore(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) spin_lock_irqsave(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) remove_wait_queue(&pp->wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) spin_unlock_irqrestore(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) pmu_write(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) static __poll_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) pmu_fpoll(struct file *filp, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) struct pmu_private *pp = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) __poll_t mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) if (!pp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) poll_wait(filp, &pp->wait, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) spin_lock_irqsave(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) if (pp->rb_get != pp->rb_put)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) mask |= EPOLLIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) spin_unlock_irqrestore(&pp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) pmu_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) struct pmu_private *pp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) if (pp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) file->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) spin_lock_irqsave(&all_pvt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) list_del(&pp->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) spin_unlock_irqrestore(&all_pvt_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) if (pp->backlight_locker)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) pmac_backlight_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) kfree(pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) static void pmac_suspend_disable_irqs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) /* Call platform functions marked "on sleep" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) pmac_pfunc_i2c_suspend();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) pmac_pfunc_base_suspend();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) static int powerbook_sleep(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) /* Wait for completion of async requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) while (!batt_req.complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) /* Giveup the lazy FPU & vec so we don't have to back them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) * up from the low level code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) enable_kernel_fp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) #ifdef CONFIG_ALTIVEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) if (cpu_has_feature(CPU_FTR_ALTIVEC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) enable_kernel_altivec();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) #endif /* CONFIG_ALTIVEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) switch (pmu_kind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) case PMU_OHARE_BASED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) error = powerbook_sleep_3400();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) case PMU_HEATHROW_BASED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) case PMU_PADDINGTON_BASED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) error = powerbook_sleep_grackle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) case PMU_KEYLARGO_BASED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) error = powerbook_sleep_Core99();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) mdelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) static void pmac_suspend_enable_irqs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) /* Force a poll of ADB interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) adb_int_pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) via_pmu_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) /* Call platform functions marked "on wake" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) pmac_pfunc_base_resume();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) pmac_pfunc_i2c_resume();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) static int pmu_sleep_valid(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) return state == PM_SUSPEND_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) && (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) static const struct platform_suspend_ops pmu_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) .enter = powerbook_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) .valid = pmu_sleep_valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) static int register_pmu_pm_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) if (pmu_kind == PMU_OHARE_BASED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) powerbook_sleep_init_3400();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) ppc_md.suspend_disable_irqs = pmac_suspend_disable_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) ppc_md.suspend_enable_irqs = pmac_suspend_enable_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) suspend_set_ops(&pmu_pm_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) device_initcall(register_pmu_pm_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) static int pmu_ioctl(struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) u_int cmd, u_long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) __u32 __user *argp = (__u32 __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) int error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) case PMU_IOC_SLEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) return pm_suspend(PM_SUSPEND_MEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) case PMU_IOC_CAN_SLEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) if (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) return put_user(0, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) return put_user(1, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) /* Compatibility ioctl's for backlight */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) case PMU_IOC_GET_BACKLIGHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) int brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) brightness = pmac_backlight_get_legacy_brightness();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) if (brightness < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) return brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) return put_user(brightness, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) case PMU_IOC_SET_BACKLIGHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) int brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) error = get_user(brightness, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) return pmac_backlight_set_legacy_brightness(brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) #ifdef CONFIG_INPUT_ADBHID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) case PMU_IOC_GRAB_BACKLIGHT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) struct pmu_private *pp = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) if (pp->backlight_locker)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) pp->backlight_locker = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) pmac_backlight_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) #endif /* CONFIG_INPUT_ADBHID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) case PMU_IOC_GET_MODEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) return put_user(pmu_kind, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) case PMU_IOC_HAS_ADB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) return put_user(pmu_has_adb, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) static long pmu_unlocked_ioctl(struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) u_int cmd, u_long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) mutex_lock(&pmu_info_proc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) ret = pmu_ioctl(filp, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) mutex_unlock(&pmu_info_proc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) #define PMU_IOC_GET_BACKLIGHT32 _IOR('B', 1, compat_size_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) #define PMU_IOC_SET_BACKLIGHT32 _IOW('B', 2, compat_size_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) #define PMU_IOC_GET_MODEL32 _IOR('B', 3, compat_size_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) #define PMU_IOC_HAS_ADB32 _IOR('B', 4, compat_size_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) #define PMU_IOC_CAN_SLEEP32 _IOR('B', 5, compat_size_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) #define PMU_IOC_GRAB_BACKLIGHT32 _IOR('B', 6, compat_size_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) static long compat_pmu_ioctl (struct file *filp, u_int cmd, u_long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) case PMU_IOC_SLEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) case PMU_IOC_GET_BACKLIGHT32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) cmd = PMU_IOC_GET_BACKLIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) case PMU_IOC_SET_BACKLIGHT32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) cmd = PMU_IOC_SET_BACKLIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) case PMU_IOC_GET_MODEL32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) cmd = PMU_IOC_GET_MODEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) case PMU_IOC_HAS_ADB32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) cmd = PMU_IOC_HAS_ADB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) case PMU_IOC_CAN_SLEEP32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) cmd = PMU_IOC_CAN_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) case PMU_IOC_GRAB_BACKLIGHT32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) cmd = PMU_IOC_GRAB_BACKLIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) return pmu_unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) static const struct file_operations pmu_device_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) .read = pmu_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) .write = pmu_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) .poll = pmu_fpoll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) .unlocked_ioctl = pmu_unlocked_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) .compat_ioctl = compat_pmu_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) .open = pmu_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) .release = pmu_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) static struct miscdevice pmu_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) PMU_MINOR, "pmu", &pmu_device_fops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) static int pmu_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) if (pmu_state == uninitialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) if (misc_register(&pmu_device) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) printk(KERN_ERR "via-pmu: cannot register misc device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) device_initcall(pmu_device_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) #ifdef DEBUG_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) polled_handshake(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) via2[B] &= ~TREQ; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) while ((via2[B] & TACK) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) via2[B] |= TREQ; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) while ((via2[B] & TACK) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) polled_send_byte(int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) via1[ACR] |= SR_OUT | SR_EXT; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) via1[SR] = x; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) polled_handshake();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) polled_recv_byte(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) via1[ACR] = (via1[ACR] & ~SR_OUT) | SR_EXT; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) x = via1[SR]; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) polled_handshake();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) x = via1[SR]; eieio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) pmu_polled_request(struct adb_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) int i, l, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) req->complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) c = req->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) l = pmu_data_len[c][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) if (l >= 0 && req->nbytes != l + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) while (pmu_state != idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) pmu_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) while ((via2[B] & TACK) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) polled_send_byte(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) if (l < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) l = req->nbytes - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) polled_send_byte(l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) for (i = 1; i <= l; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) polled_send_byte(req->data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) l = pmu_data_len[c][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) if (l < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) l = polled_recv_byte();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) for (i = 0; i < l; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) req->reply[i + req->reply_len] = polled_recv_byte();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) if (req->done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) (*req->done)(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) /* N.B. This doesn't work on the 3400 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) void pmu_blink(int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) for (; n > 0; --n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) req.nbytes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) req.done = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) req.data[0] = 0xee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) req.data[1] = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) req.data[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) req.data[3] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) req.reply[0] = ADB_RET_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) req.reply_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) req.reply_expected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) pmu_polled_request(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) req.nbytes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) req.done = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) req.data[0] = 0xee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) req.data[1] = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) req.data[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) req.data[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) req.reply[0] = ADB_RET_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) req.reply_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) req.reply_expected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) pmu_polled_request(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) #endif /* DEBUG_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) int pmu_sys_suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) static int pmu_syscore_suspend(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) /* Suspend PMU event interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) pmu_suspend();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) pmu_sys_suspended = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) #ifdef CONFIG_PMAC_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) /* Tell backlight code not to muck around with the chip anymore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) pmu_backlight_set_sleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) static void pmu_syscore_resume(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) struct adb_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) if (!pmu_sys_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) /* Tell PMU we are ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) pmu_wait_complete(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) #ifdef CONFIG_PMAC_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) /* Tell backlight code it can use the chip again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) pmu_backlight_set_sleep(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) /* Resume PMU event interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) pmu_resume();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) pmu_sys_suspended = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) static struct syscore_ops pmu_syscore_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) .suspend = pmu_syscore_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) .resume = pmu_syscore_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) static int pmu_syscore_register(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) register_syscore_ops(&pmu_syscore_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) subsys_initcall(pmu_syscore_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) EXPORT_SYMBOL(pmu_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) EXPORT_SYMBOL(pmu_queue_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) EXPORT_SYMBOL(pmu_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) EXPORT_SYMBOL(pmu_poll_adb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) EXPORT_SYMBOL(pmu_wait_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) EXPORT_SYMBOL(pmu_suspend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) EXPORT_SYMBOL(pmu_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) EXPORT_SYMBOL(pmu_unlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) #if defined(CONFIG_PPC32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) EXPORT_SYMBOL(pmu_enable_irled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) EXPORT_SYMBOL(pmu_battery_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) EXPORT_SYMBOL(pmu_batteries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) EXPORT_SYMBOL(pmu_power_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673)