VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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