From a0349aa4708c631d1205d47ced5ea30a7a74be86 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Tue, 16 Aug 2011 13:50:36 -0700 Subject: [PATCH] Revert "Drop pmu code from medfield gb-stable on top of linux 3.0." cherry-pick Len Brown's PMU driver from Alan Cox's linux-3.0-mid-ref tree This reverts commit 8b0274a0b21b27e82e532b9d7deaf0bbdf5f50b4. --- arch/x86/platform/Makefile | 3 +- arch/x86/platform/mdfld/Makefile | 5 - arch/x86/platform/mdfld/early_printk_mdfld.c | 319 --- arch/x86/platform/mdfld/mdfld.c | 905 --------- arch/x86/platform/mdfld/pmu.c | 2669 -------------------------- arch/x86/platform/mdfld/pmu.h | 536 ------ arch/x86/platform/mdfld/vrtc.c | 159 -- drivers/idle/intel_idle.c | 12 +- include/linux/intel_mid_pm.h | 146 -- 9 files changed, 3 insertions(+), 4751 deletions(-) delete mode 100644 arch/x86/platform/mdfld/Makefile delete mode 100644 arch/x86/platform/mdfld/early_printk_mdfld.c delete mode 100644 arch/x86/platform/mdfld/mdfld.c delete mode 100644 arch/x86/platform/mdfld/pmu.c delete mode 100644 arch/x86/platform/mdfld/pmu.h delete mode 100644 arch/x86/platform/mdfld/vrtc.c delete mode 100644 include/linux/intel_mid_pm.h diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 67339b4..021eee9 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile @@ -2,10 +2,9 @@ obj-y += ce4100/ obj-y += efi/ obj-y += iris/ +obj-y += mrst/ obj-y += olpc/ obj-y += scx200/ obj-y += sfi/ obj-y += visws/ obj-y += uv/ -obj-$(CONFIG_X86_MRST) += mrst/ -obj-$(CONFIG_X86_MDFLD) += mdfld/ diff --git a/arch/x86/platform/mdfld/Makefile b/arch/x86/platform/mdfld/Makefile deleted file mode 100644 index 6253dca..0000000 --- a/arch/x86/platform/mdfld/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_X86_INTEL_MID) += mdfld.o -obj-$(CONFIG_X86_INTEL_MID) += vrtc.o -obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_mdfld.o -obj-$(CONFIG_X86_MDFLD) += pmu.o - diff --git a/arch/x86/platform/mdfld/early_printk_mdfld.c b/arch/x86/platform/mdfld/early_printk_mdfld.c deleted file mode 100644 index 25bfdbb..0000000 --- a/arch/x86/platform/mdfld/early_printk_mdfld.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * early_printk_mrst.c - early consoles for Intel MID platforms - * - * Copyright (c) 2008-2010, Intel Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 - * of the License. - */ - -/* - * This file implements two early consoles named mrst and hsu. - * mrst is based on Maxim3110 spi-uart device, it exists in both - * Moorestown and Medfield platforms, while hsu is based on a High - * Speed UART device which only exists in the Medfield platform - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define MRST_SPI_TIMEOUT 0x200000 -#define MRST_REGBASE_SPI0 0xff128000 -#define MRST_REGBASE_SPI1 0xff128400 -#define MRST_CLK_SPI0_REG 0xff11d86c - -/* Bit fields in CTRLR0 */ -#define SPI_DFS_OFFSET 0 - -#define SPI_FRF_OFFSET 4 -#define SPI_FRF_SPI 0x0 -#define SPI_FRF_SSP 0x1 -#define SPI_FRF_MICROWIRE 0x2 -#define SPI_FRF_RESV 0x3 - -#define SPI_MODE_OFFSET 6 -#define SPI_SCPH_OFFSET 6 -#define SPI_SCOL_OFFSET 7 -#define SPI_TMOD_OFFSET 8 -#define SPI_TMOD_TR 0x0 /* xmit & recv */ -#define SPI_TMOD_TO 0x1 /* xmit only */ -#define SPI_TMOD_RO 0x2 /* recv only */ -#define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */ - -#define SPI_SLVOE_OFFSET 10 -#define SPI_SRL_OFFSET 11 -#define SPI_CFS_OFFSET 12 - -/* Bit fields in SR, 7 bits */ -#define SR_MASK 0x7f /* cover 7 bits */ -#define SR_BUSY (1 << 0) -#define SR_TF_NOT_FULL (1 << 1) -#define SR_TF_EMPT (1 << 2) -#define SR_RF_NOT_EMPT (1 << 3) -#define SR_RF_FULL (1 << 4) -#define SR_TX_ERR (1 << 5) -#define SR_DCOL (1 << 6) - -struct dw_spi_reg { - u32 ctrl0; - u32 ctrl1; - u32 ssienr; - u32 mwcr; - u32 ser; - u32 baudr; - u32 txfltr; - u32 rxfltr; - u32 txflr; - u32 rxflr; - u32 sr; - u32 imr; - u32 isr; - u32 risr; - u32 txoicr; - u32 rxoicr; - u32 rxuicr; - u32 msticr; - u32 icr; - u32 dmacr; - u32 dmatdlr; - u32 dmardlr; - u32 idr; - u32 version; - - /* Currently operates as 32 bits, though only the low 16 bits matter */ - u32 dr; -} __packed; - -#define dw_readl(dw, name) __raw_readl(&(dw)->name) -#define dw_writel(dw, name, val) __raw_writel((val), &(dw)->name) - -/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */ -static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0; - -static u32 *pclk_spi0; -/* Always contains an accessible address, start with 0 */ -static struct dw_spi_reg *pspi; - -static struct kmsg_dumper dw_dumper; -static int dumper_registered; - -static void dw_kmsg_dump(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason, - const char *s1, unsigned long l1, - const char *s2, unsigned long l2) -{ - int i; - - /* When run to this, we'd better re-init the HW */ - mrst_early_console_init(); - - for (i = 0; i < l1; i++) - early_mrst_console.write(&early_mrst_console, s1 + i, 1); - for (i = 0; i < l2; i++) - early_mrst_console.write(&early_mrst_console, s2 + i, 1); -} - -/* Set the ratio rate to 115200, 8n1, IRQ disabled */ -static void max3110_write_config(void) -{ - u16 config; - - config = 0xc001; - dw_writel(pspi, dr, config); -} - -/* Translate char to a eligible word and send to max3110 */ -static void max3110_write_data(char c) -{ - u16 data; - - data = 0x8000 | c; - dw_writel(pspi, dr, data); -} - -void mrst_early_console_init(void) -{ - u32 ctrlr0 = 0; - u32 spi0_cdiv; - u32 freq; /* Freqency info only need be searched once */ - - /* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */ - pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, - MRST_CLK_SPI0_REG); - spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; - freq = 100000000 / (spi0_cdiv + 1); - - if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL) - mrst_spi_paddr = MRST_REGBASE_SPI1; - - pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, - mrst_spi_paddr); - - /* Disable SPI controller */ - dw_writel(pspi, ssienr, 0); - - /* Set control param, 8 bits, transmit only mode */ - ctrlr0 = dw_readl(pspi, ctrl0); - - ctrlr0 &= 0xfcc0; - ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET) - | (SPI_TMOD_TO << SPI_TMOD_OFFSET); - dw_writel(pspi, ctrl0, ctrlr0); - - /* - * Change the spi0 clk to comply with 115200 bps, use 100000 to - * calculate the clk dividor to make the clock a little slower - * than real baud rate. - */ - dw_writel(pspi, baudr, freq/100000); - - /* Disable all INT for early phase */ - dw_writel(pspi, imr, 0x0); - - /* Set the cs to spi-uart */ - dw_writel(pspi, ser, 0x2); - - /* Enable the HW, the last step for HW init */ - dw_writel(pspi, ssienr, 0x1); - - /* Set the default configuration */ - max3110_write_config(); - - /* Register the kmsg dumper */ - if (!dumper_registered) { - dw_dumper.dump = dw_kmsg_dump; - kmsg_dump_register(&dw_dumper); - dumper_registered = 1; - } -} - -/* Slave select should be called in the read/write function */ -static void early_mrst_spi_putc(char c) -{ - unsigned int timeout; - u32 sr; - - timeout = MRST_SPI_TIMEOUT; - /* Early putc needs to make sure the TX FIFO is not full */ - while (--timeout) { - sr = dw_readl(pspi, sr); - if (!(sr & SR_TF_NOT_FULL)) - cpu_relax(); - else - break; - } - - if (!timeout) - pr_warning("MRST earlycon: timed out\n"); - else - max3110_write_data(c); -} - -/* Early SPI only uses polling mode */ -static void early_mrst_spi_write(struct console *con, const char *str, unsigned n) -{ - int i; - - for (i = 0; i < n && *str; i++) { - if (*str == '\n') - early_mrst_spi_putc('\r'); - early_mrst_spi_putc(*str); - str++; - } -} - -struct console early_mrst_console = { - .name = "earlymrst", - .write = early_mrst_spi_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * Following is the early console based on Medfield HSU (High - * Speed UART) device. - */ -#define HSU_PORT2_PADDR 0xffa28180 - -static void __iomem *phsu; - -void hsu_early_console_init(void) -{ - u8 lcr; - - phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, - HSU_PORT2_PADDR); - - /* Disable FIFO */ - writeb(0x0, phsu + UART_FCR); - - /* Set to default 115200 bps, 8n1 */ - lcr = readb(phsu + UART_LCR); - writeb((0x80 | lcr), phsu + UART_LCR); - writeb(0x18, phsu + UART_DLL); - writeb(lcr, phsu + UART_LCR); - writel(0x3600, phsu + UART_MUL*4); - - writeb(0x8, phsu + UART_MCR); - writeb(0x7, phsu + UART_FCR); - writeb(0x3, phsu + UART_LCR); - - /* Clear IRQ status */ - readb(phsu + UART_LSR); - readb(phsu + UART_RX); - readb(phsu + UART_IIR); - readb(phsu + UART_MSR); - - /* Enable FIFO */ - writeb(0x7, phsu + UART_FCR); -} - -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - -static void early_hsu_putc(char ch) -{ - unsigned int timeout = 10000; /* 10ms */ - u8 status; - - while (--timeout) { - status = readb(phsu + UART_LSR); - if (status & BOTH_EMPTY) - break; - udelay(1); - } - - /* Only write the char when there was no timeout */ - if (timeout) - writeb(ch, phsu + UART_TX); -} - -static void early_hsu_write(struct console *con, const char *str, unsigned n) -{ - int i; - - for (i = 0; i < n && *str; i++) { - if (*str == '\n') - early_hsu_putc('\r'); - early_hsu_putc(*str); - str++; - } -} - -struct console early_hsu_console = { - .name = "earlyhsu", - .write = early_hsu_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; diff --git a/arch/x86/platform/mdfld/mdfld.c b/arch/x86/platform/mdfld/mdfld.c deleted file mode 100644 index b729820..0000000 --- a/arch/x86/platform/mdfld/mdfld.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * mrst.c: Intel Moorestown platform specific setup code - * - * (C) Copyright 2008 Intel Corporation - * Author: Jacob Pan (jacob.jun.pan@intel.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 - * of the License. - */ - -#define pr_fmt(fmt) "mrst: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, - * cmdline option x86_mrst_timer can be used to override the configuration - * to prefer one or the other. - * at runtime, there are basically three timer configurations: - * 1. per cpu apbt clock only - * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only - * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast. - * - * by default (without cmdline option), platform code first detects cpu type - * to see if we are on lincroft or penwell, then set up both lapic or apbt - * clocks accordingly. - * i.e. by default, medfield uses configuration #2, moorestown uses #1. - * config #3 is supported but not recommended on medfield. - * - * rating and feature summary: - * lapic (with C3STOP) --------- 100 - * apbt (always-on) ------------ 110 - * lapic (always-on,ARAT) ------ 150 - */ - -__cpuinitdata enum mrst_timer_options mrst_timer_options; - -static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM]; -static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM]; -enum mrst_cpu_type __mrst_cpu_chip; -EXPORT_SYMBOL_GPL(__mrst_cpu_chip); - -int sfi_mtimer_num; - -struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; -EXPORT_SYMBOL_GPL(sfi_mrtc_array); -int sfi_mrtc_num; - -static void mrst_power_off(void) -{ - if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) - intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1); -} - -static void mrst_reboot(void) -{ - if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) - intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); - else - intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); -} - -/* parse all the mtimer info to a static mtimer array */ -static int __init sfi_parse_mtmr(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_timer_table_entry *pentry; - struct mpc_intsrc mp_irq; - int totallen; - - sb = (struct sfi_table_simple *)table; - if (!sfi_mtimer_num) { - sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb, - struct sfi_timer_table_entry); - pentry = (struct sfi_timer_table_entry *) sb->pentry; - totallen = sfi_mtimer_num * sizeof(*pentry); - memcpy(sfi_mtimer_array, pentry, totallen); - } - - pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); - pentry = sfi_mtimer_array; - for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { - pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz," - " irq = %d\n", totallen, (u32)pentry->phys_addr, - pentry->freq_hz, pentry->irq); - if (!pentry->irq) - continue; - mp_irq.type = MP_INTSRC; - mp_irq.irqtype = mp_INT; -/* triggering mode edge bit 2-3, active high polarity bit 0-1 */ - mp_irq.irqflag = 5; - mp_irq.srcbus = MP_BUS_ISA; - mp_irq.srcbusirq = pentry->irq; /* IRQ */ - mp_irq.dstapic = MP_APIC_ALL; - mp_irq.dstirq = pentry->irq; - mp_save_irq(&mp_irq); - } - - return 0; -} - -struct sfi_timer_table_entry *sfi_get_mtmr(int hint) -{ - int i; - if (hint < sfi_mtimer_num) { - if (!sfi_mtimer_usage[hint]) { - pr_debug("hint taken for timer %d irq %d\n",\ - hint, sfi_mtimer_array[hint].irq); - sfi_mtimer_usage[hint] = 1; - return &sfi_mtimer_array[hint]; - } - } - /* take the first timer available */ - for (i = 0; i < sfi_mtimer_num;) { - if (!sfi_mtimer_usage[i]) { - sfi_mtimer_usage[i] = 1; - return &sfi_mtimer_array[i]; - } - i++; - } - return NULL; -} - -void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr) -{ - int i; - for (i = 0; i < sfi_mtimer_num;) { - if (mtmr->irq == sfi_mtimer_array[i].irq) { - sfi_mtimer_usage[i] = 0; - return; - } - i++; - } -} - -/* parse all the mrtc info to a global mrtc array */ -int __init sfi_parse_mrtc(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_rtc_table_entry *pentry; - struct mpc_intsrc mp_irq; - - int totallen; - - sb = (struct sfi_table_simple *)table; - if (!sfi_mrtc_num) { - sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb, - struct sfi_rtc_table_entry); - pentry = (struct sfi_rtc_table_entry *)sb->pentry; - totallen = sfi_mrtc_num * sizeof(*pentry); - memcpy(sfi_mrtc_array, pentry, totallen); - } - - pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); - pentry = sfi_mrtc_array; - for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { - pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", - totallen, (u32)pentry->phys_addr, pentry->irq); - mp_irq.type = MP_INTSRC; - mp_irq.irqtype = mp_INT; - mp_irq.irqflag = 0xf; /* level trigger and active low */ - mp_irq.srcbus = MP_BUS_ISA; - mp_irq.srcbusirq = pentry->irq; /* IRQ */ - mp_irq.dstapic = MP_APIC_ALL; - mp_irq.dstirq = pentry->irq; - mp_save_irq(&mp_irq); - } - return 0; -} - -static unsigned long __init mrst_calibrate_tsc(void) -{ - unsigned long flags, fast_calibrate; - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - u32 lo, hi, ratio, fsb; - - rdmsr(MSR_IA32_PERF_STATUS, lo, hi); - pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); - ratio = (hi >> 8) & 0x1f; - pr_debug("ratio is %d\n", ratio); - if (!ratio) { - pr_err("read a zero ratio, should be incorrect!\n"); - pr_err("force tsc ratio to 16 ...\n"); - ratio = 16; - } - rdmsr(MSR_FSB_FREQ, lo, hi); - if ((lo & 0x7) == 0x7) - fsb = PENWELL_FSB_FREQ_83SKU; - else - fsb = PENWELL_FSB_FREQ_100SKU; - fast_calibrate = ratio * fsb; - pr_debug("read penwell tsc %lu khz\n", fast_calibrate); - lapic_timer_frequency = fsb * 1000 / HZ; - /* mark tsc clocksource as reliable */ - set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); - } else { - local_irq_save(flags); - fast_calibrate = apbt_quick_calibrate(); - local_irq_restore(flags); - } - - if (fast_calibrate) - return fast_calibrate; - - return 0; -} - -static void __init mrst_time_init(void) -{ - sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); - switch (mrst_timer_options) { - case MRST_TIMER_APBT_ONLY: - break; - case MRST_TIMER_LAPIC_APBT: - x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock; - x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock; - break; - default: - if (!boot_cpu_has(X86_FEATURE_ARAT)) - break; - x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock; - x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock; - return; - } - /* we need at least one APB timer */ - pre_init_apic_IRQ0(); - apbt_time_init(); -} - -static void __cpuinit mrst_arch_setup(void) -{ - if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) - __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; - else if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x26) - __mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT; - else { - pr_err("Unknown Moorestown CPU (%d:%d), default to Lincroft\n", - boot_cpu_data.x86, boot_cpu_data.x86_model); - __mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT; - } - pr_debug("Moorestown CPU %s identified\n", - (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ? - "Lincroft" : "Penwell"); -} - -/* MID systems don't have i8042 controller */ -static int mrst_i8042_detect(void) -{ - return 0; -} - -/* - * Moorestown specific x86_init function overrides and early setup - * calls. - */ -void __init x86_mrst_early_setup(void) -{ - x86_init.resources.probe_roms = x86_init_noop; - x86_init.resources.reserve_resources = x86_init_noop; - - x86_init.timers.timer_init = mrst_time_init; - x86_init.timers.setup_percpu_clockev = x86_init_noop; - - x86_init.irqs.pre_vector_init = x86_init_noop; - - x86_init.oem.arch_setup = mrst_arch_setup; - - x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock; - - x86_platform.calibrate_tsc = mrst_calibrate_tsc; - x86_platform.i8042_detect = mrst_i8042_detect; - x86_init.timers.wallclock_init = mrst_rtc_init; - x86_init.pci.init = pci_mrst_init; - x86_init.pci.fixup_irqs = x86_init_noop; - - legacy_pic = &null_legacy_pic; - - /* Moorestown specific power_off/restart method */ - pm_power_off = mrst_power_off; - machine_ops.emergency_restart = mrst_reboot; - - /* Avoid searching for BIOS MP tables */ - x86_init.mpparse.find_smp_config = x86_init_noop; - x86_init.mpparse.get_smp_config = x86_init_uint_noop; - set_bit(MP_BUS_ISA, mp_bus_not_pci); -} - -/* - * if user does not want to use per CPU apb timer, just give it a lower rating - * than local apic timer and skip the late per cpu timer init. - */ -static inline int __init setup_x86_mrst_timer(char *arg) -{ - if (!arg) - return -EINVAL; - - if (strcmp("apbt_only", arg) == 0) - mrst_timer_options = MRST_TIMER_APBT_ONLY; - else if (strcmp("lapic_and_apbt", arg) == 0) - mrst_timer_options = MRST_TIMER_LAPIC_APBT; - else { - pr_warning("X86 MRST timer option %s not recognised" - " use x86_mrst_timer=apbt_only or lapic_and_apbt\n", - arg); - return -EINVAL; - } - return 0; -} -__setup("x86_mrst_timer=", setup_x86_mrst_timer); - -/* - * Parsing GPIO table first, since the DEVS table will need this table - * to map the pin name to the actual pin. - */ -static struct sfi_gpio_table_entry *gpio_table; -static int gpio_num_entry; - -static int __init sfi_parse_gpio(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_gpio_table_entry *pentry; - int num, i; - - if (gpio_table) - return 0; - sb = (struct sfi_table_simple *)table; - num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); - pentry = (struct sfi_gpio_table_entry *)sb->pentry; - - gpio_table = (struct sfi_gpio_table_entry *) - kmalloc(num * sizeof(*pentry), GFP_KERNEL); - if (!gpio_table) - return -1; - memcpy(gpio_table, pentry, num * sizeof(*pentry)); - gpio_num_entry = num; - - pr_debug("GPIO pin info:\n"); - for (i = 0; i < num; i++, pentry++) - pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," - " pin = %d\n", i, - pentry->controller_name, - pentry->pin_name, - pentry->pin_no); - return 0; -} - -static int get_gpio_by_name(const char *name) -{ - struct sfi_gpio_table_entry *pentry = gpio_table; - int i; - - if (!pentry) - return -1; - for (i = 0; i < gpio_num_entry; i++, pentry++) { - if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) - return pentry->pin_no; - } - return -1; -} - -/* - * Here defines the array of devices platform data that IAFW would export - * through SFI "DEVS" table, we use name and type to match the device and - * its platform data. - */ -struct devs_id { - char name[SFI_NAME_LEN + 1]; - u8 type; - u8 delay; - void *(*get_platform_data)(void *info); -}; - -/* the offset for the mapping of global gpio pin to irq */ -#define MRST_IRQ_OFFSET 0x100 - -static void __init *pmic_gpio_platform_data(void *info) -{ - static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; - int gpio_base = get_gpio_by_name("pmic_gpio_base"); - - if (gpio_base == -1) - gpio_base = 64; - pmic_gpio_pdata.gpio_base = gpio_base; - pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET; - pmic_gpio_pdata.gpiointr = 0xffffeff8; - - return &pmic_gpio_pdata; -} - -static void __init *max3111_platform_data(void *info) -{ - struct spi_board_info *spi_info = info; - int intr = get_gpio_by_name("max3111_int"); - - spi_info->mode = SPI_MODE_0; - if (intr == -1) - return NULL; - spi_info->irq = intr + MRST_IRQ_OFFSET; - return NULL; -} - -/* we have multiple max7315 on the board ... */ -#define MAX7315_NUM 2 -static void __init *max7315_platform_data(void *info) -{ - static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; - static int nr; - struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; - struct i2c_board_info *i2c_info = info; - int gpio_base, intr; - char base_pin_name[SFI_NAME_LEN + 1]; - char intr_pin_name[SFI_NAME_LEN + 1]; - - if (nr == MAX7315_NUM) { - pr_err("too many max7315s, we only support %d\n", - MAX7315_NUM); - return NULL; - } - /* we have several max7315 on the board, we only need load several - * instances of the same pca953x driver to cover them - */ - strcpy(i2c_info->type, "max7315"); - if (nr++) { - sprintf(base_pin_name, "max7315_%d_base", nr); - sprintf(intr_pin_name, "max7315_%d_int", nr); - } else { - strcpy(base_pin_name, "max7315_base"); - strcpy(intr_pin_name, "max7315_int"); - } - - gpio_base = get_gpio_by_name(base_pin_name); - intr = get_gpio_by_name(intr_pin_name); - - if (gpio_base == -1) - return NULL; - max7315->gpio_base = gpio_base; - if (intr != -1) { - i2c_info->irq = intr + MRST_IRQ_OFFSET; - max7315->irq_base = gpio_base + MRST_IRQ_OFFSET; - } else { - i2c_info->irq = -1; - max7315->irq_base = -1; - } - return max7315; -} - -static void *tca6416_platform_data(void *info) -{ - static struct pca953x_platform_data tca6416; - struct i2c_board_info *i2c_info = info; - int gpio_base, intr; - char base_pin_name[SFI_NAME_LEN + 1]; - char intr_pin_name[SFI_NAME_LEN + 1]; - - strcpy(i2c_info->type, "tca6416"); - strcpy(base_pin_name, "tca6416_base"); - strcpy(intr_pin_name, "tca6416_int"); - - gpio_base = get_gpio_by_name(base_pin_name); - intr = get_gpio_by_name(intr_pin_name); - - if (gpio_base == -1) - return NULL; - tca6416.gpio_base = gpio_base; - if (intr != -1) { - i2c_info->irq = intr + MRST_IRQ_OFFSET; - tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET; - } else { - i2c_info->irq = -1; - tca6416.irq_base = -1; - } - return &tca6416; -} - -static void *mpu3050_platform_data(void *info) -{ - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("mpu3050_int"); - - if (intr == -1) - return NULL; - - i2c_info->irq = intr + MRST_IRQ_OFFSET; - return NULL; -} - -static void *ektf2136_spi_platform_data(void *info) -{ - static int dummy; - struct spi_board_info *spi_info = info; - int intr = get_gpio_by_name("ts_int"); - - if (intr == -1) - return NULL; - spi_info->irq = intr + MRST_IRQ_OFFSET; - - /* we return a dummy pdata */ - return &dummy; -} - -static void __init *emc1403_platform_data(void *info) -{ - static short intr2nd_pdata; - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("thermal_int"); - int intr2nd = get_gpio_by_name("thermal_alert"); - - if (intr == -1 || intr2nd == -1) - return NULL; - - i2c_info->irq = intr + MRST_IRQ_OFFSET; - intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; - - return &intr2nd_pdata; -} - -static void __init *lis331dl_platform_data(void *info) -{ - static short intr2nd_pdata; - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("accel_int"); - int intr2nd = get_gpio_by_name("accel_2"); - - if (intr == -1 || intr2nd == -1) - return NULL; - - i2c_info->irq = intr + MRST_IRQ_OFFSET; - intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; - - return &intr2nd_pdata; -} - -static void __init *no_platform_data(void *info) -{ - return NULL; -} - -static const struct devs_id __initconst device_ids[] = { - {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, - {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data}, - {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, - {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, - {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, - {"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data}, - {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, - {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, - {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, - {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, - {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data}, - {"ektf2136_spi", SFI_DEV_TYPE_SPI, 0, &ektf2136_spi_platform_data}, - {}, -}; - -#define MAX_IPCDEVS 24 -static struct platform_device *ipc_devs[MAX_IPCDEVS]; -static int ipc_next_dev; - -#define MAX_SCU_SPI 24 -static struct spi_board_info *spi_devs[MAX_SCU_SPI]; -static int spi_next_dev; - -#define MAX_SCU_I2C 24 -static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; -static int i2c_bus[MAX_SCU_I2C]; -static int i2c_next_dev; - -static void __init intel_scu_device_register(struct platform_device *pdev) -{ - if(ipc_next_dev == MAX_IPCDEVS) - pr_err("too many SCU IPC devices"); - else - ipc_devs[ipc_next_dev++] = pdev; -} - -static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) -{ - struct spi_board_info *new_dev; - - if (spi_next_dev == MAX_SCU_SPI) { - pr_err("too many SCU SPI devices"); - return; - } - - new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); - if (!new_dev) { - pr_err("failed to alloc mem for delayed spi dev %s\n", - sdev->modalias); - return; - } - memcpy(new_dev, sdev, sizeof(*sdev)); - - spi_devs[spi_next_dev++] = new_dev; -} - -static void __init intel_scu_i2c_device_register(int bus, - struct i2c_board_info *idev) -{ - struct i2c_board_info *new_dev; - - if (i2c_next_dev == MAX_SCU_I2C) { - pr_err("too many SCU I2C devices"); - return; - } - - new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); - if (!new_dev) { - pr_err("failed to alloc mem for delayed i2c dev %s\n", - idev->type); - return; - } - memcpy(new_dev, idev, sizeof(*idev)); - - i2c_bus[i2c_next_dev] = bus; - i2c_devs[i2c_next_dev++] = new_dev; -} - -BLOCKING_NOTIFIER_HEAD(intel_scu_notifier); -EXPORT_SYMBOL_GPL(intel_scu_notifier); - -/* Called by IPC driver */ -void intel_scu_devices_create(void) -{ - int i; - - for (i = 0; i < ipc_next_dev; i++) - platform_device_add(ipc_devs[i]); - - for (i = 0; i < spi_next_dev; i++) - spi_register_board_info(spi_devs[i], 1); - - for (i = 0; i < i2c_next_dev; i++) { - struct i2c_adapter *adapter; - struct i2c_client *client; - - adapter = i2c_get_adapter(i2c_bus[i]); - if (adapter) { - client = i2c_new_device(adapter, i2c_devs[i]); - if (!client) - pr_err("can't create i2c device %s\n", - i2c_devs[i]->type); - } else - i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); - } - intel_scu_notifier_post(SCU_AVAILABLE, 0L); -} -EXPORT_SYMBOL_GPL(intel_scu_devices_create); - -/* Called by IPC driver */ -void intel_scu_devices_destroy(void) -{ - int i; - - intel_scu_notifier_post(SCU_DOWN, 0L); - - for (i = 0; i < ipc_next_dev; i++) - platform_device_del(ipc_devs[i]); -} -EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); - -static void __init install_irq_resource(struct platform_device *pdev, int irq) -{ - /* Single threaded */ - static struct resource __initdata res = { - .name = "IRQ", - .flags = IORESOURCE_IRQ, - }; - res.start = irq; - platform_device_add_resources(pdev, &res, 1); -} - -static void __init sfi_handle_ipc_dev(struct platform_device *pdev) -{ - const struct devs_id *dev = device_ids; - void *pdata = NULL; - - while (dev->name[0]) { - if (dev->type == SFI_DEV_TYPE_IPC && - !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { - pdata = dev->get_platform_data(pdev); - break; - } - dev++; - } - pdev->dev.platform_data = pdata; - intel_scu_device_register(pdev); -} - -static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info) -{ - const struct devs_id *dev = device_ids; - void *pdata = NULL; - - while (dev->name[0]) { - if (dev->type == SFI_DEV_TYPE_SPI && - !strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) { - pdata = dev->get_platform_data(spi_info); - break; - } - dev++; - } - spi_info->platform_data = pdata; - if (dev->delay) - intel_scu_spi_device_register(spi_info); - else - spi_register_board_info(spi_info, 1); -} - -static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info) -{ - const struct devs_id *dev = device_ids; - void *pdata = NULL; - - while (dev->name[0]) { - if (dev->type == SFI_DEV_TYPE_I2C && - !strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) { - pdata = dev->get_platform_data(i2c_info); - break; - } - dev++; - } - i2c_info->platform_data = pdata; - - if (dev->delay) - intel_scu_i2c_device_register(bus, i2c_info); - else - i2c_register_board_info(bus, i2c_info, 1); - } - - -static int __init sfi_parse_devs(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_device_table_entry *pentry; - struct spi_board_info spi_info; - struct i2c_board_info i2c_info; - struct platform_device *pdev; - int num, i, bus; - int ioapic; - struct io_apic_irq_attr irq_attr; - - sb = (struct sfi_table_simple *)table; - num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); - pentry = (struct sfi_device_table_entry *)sb->pentry; - - for (i = 0; i < num; i++, pentry++) { - if (pentry->irq != (u8)0xff) { /* native RTE case */ - /* these SPI2 devices are not exposed to system as PCI - * devices, but they have separate RTE entry in IOAPIC - * so we have to enable them one by one here - */ - ioapic = mp_find_ioapic(pentry->irq); - irq_attr.ioapic = ioapic; - irq_attr.ioapic_pin = pentry->irq; - irq_attr.trigger = 1; - irq_attr.polarity = 1; - io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); - } - switch (pentry->type) { - case SFI_DEV_TYPE_IPC: - /* ID as IRQ is a hack that will go away */ - pdev = platform_device_alloc(pentry->name, pentry->irq); - if (pdev == NULL) { - pr_err("out of memory for SFI platform device '%s'.\n", - pentry->name); - continue; - } - install_irq_resource(pdev, pentry->irq); - pr_debug("info[%2d]: IPC bus, name = %16.16s, " - "irq = 0x%2x\n", i, pentry->name, pentry->irq); - sfi_handle_ipc_dev(pdev); - break; - case SFI_DEV_TYPE_SPI: - memset(&spi_info, 0, sizeof(spi_info)); - strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); - spi_info.irq = pentry->irq; - spi_info.bus_num = pentry->host_num; - spi_info.chip_select = pentry->addr; - spi_info.max_speed_hz = pentry->max_freq; - pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, " - "irq = 0x%2x, max_freq = %d, cs = %d\n", i, - spi_info.bus_num, - spi_info.modalias, - spi_info.irq, - spi_info.max_speed_hz, - spi_info.chip_select); - sfi_handle_spi_dev(&spi_info); - break; - case SFI_DEV_TYPE_I2C: - memset(&i2c_info, 0, sizeof(i2c_info)); - bus = pentry->host_num; - strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); - i2c_info.irq = pentry->irq; - i2c_info.addr = pentry->addr; - pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " - "irq = 0x%2x, addr = 0x%x\n", i, bus, - i2c_info.type, - i2c_info.irq, - i2c_info.addr); - sfi_handle_i2c_dev(bus, &i2c_info); - break; - case SFI_DEV_TYPE_UART: - case SFI_DEV_TYPE_HSI: - default: - ; - } - } - return 0; -} - -static int __init mrst_platform_init(void) -{ - sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); - sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); - return 0; -} -arch_initcall(mrst_platform_init); - -/* - * we will search these buttons in SFI GPIO table (by name) - * and register them dynamically. Please add all possible - * buttons here, we will shrink them if no GPIO found. - */ -static struct gpio_keys_button gpio_button[] = { - {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, - {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, - {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, - {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, - {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, - {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, - {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, - {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, - {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, - {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, -}; - -static struct gpio_keys_platform_data mrst_gpio_keys = { - .buttons = gpio_button, - .rep = 1, - .nbuttons = -1, /* will fill it after search */ -}; - -static struct platform_device pb_device = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &mrst_gpio_keys, - }, -}; - -/* - * Shrink the non-existent buttons, register the gpio button - * device if there is some - */ -static int __init pb_keys_init(void) -{ - struct gpio_keys_button *gb = gpio_button; - int i, num, good = 0; - - num = sizeof(gpio_button) / sizeof(struct gpio_keys_button); - for (i = 0; i < num; i++) { - gb[i].gpio = get_gpio_by_name(gb[i].desc); - if (gb[i].gpio == -1) - continue; - - if (i != good) - gb[good] = gb[i]; - good++; - } - - if (good) { - mrst_gpio_keys.nbuttons = good; - return platform_device_register(&pb_device); - } - return 0; -} -late_initcall(pb_keys_init); diff --git a/arch/x86/platform/mdfld/pmu.c b/arch/x86/platform/mdfld/pmu.c deleted file mode 100644 index 6d5f7d2..0000000 --- a/arch/x86/platform/mdfld/pmu.c +++ /dev/null @@ -1,2669 +0,0 @@ -/* - * mid_pmu.c - This driver provides interface to configure the 2 pmu's - * Copyright (c) 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pmu.h" - -/* These are the set of LSS's that are checked - * to be D0i3 before entering S0i1/3 - */ -static u8 s0ix_lss[] = { - PMU_SDIO0_LSS_00, - PMU_EMMC0_LSS_01, - -#ifdef CONFIG_HSI_ARASAN - PMU_HSI_LSS_03, -#endif - -#ifdef CONFIG_DX_SEP - PMU_SECURITY_LSS_04, -#endif - -#ifdef CONFIG_USB_PENWELL_OTG - PMU_USB_OTG_LSS_06, -#endif - -#ifdef TELEPHONY_ENABLE_S0IX - PMU_AUDIO_ENGINE_LSS_08, - PMU_AUDIO_DMA_LSS_09, - PMU_AUDIO_SSP0_LSS_51, - PMU_AUDIO_SSP1_LSS_52, - PMU_SPI3_LSS_36, -#endif - -#ifdef DWSPI_ENABLE_S0IX - PMU_SPI1_LSS_18, -#endif - -#ifdef WLAN_ENABLE_S0IX - PMU_SDIO1_LSS_30, -#endif - -#ifdef I2C_ENABLE_S0IX - PMU_I2C0_LSS_20, - PMU_I2C1_LSS_21, - PMU_I2C2_LSS_27, - PMU_I2C3_LSS_33, - PMU_I2C4_LSS_34, - PMU_I2C5_LSS_35, -#endif - - PMU_UART2_LSS_41, - -}; -static u32 TARGET_CFG[4]; -static u32 s0ix_target[4]; - -/* These are the set of LSS's that are checked - * to be D0i3 before entering LPMP3 mode. - */ -static u8 lpmp3_lss[] = { - PMU_SDIO0_LSS_00, - PMU_EMMC0_LSS_01, - -#ifdef CONFIG_HSI_ARASAN - PMU_HSI_LSS_03, -#endif - -#ifdef CONFIG_DX_SEP - PMU_SECURITY_LSS_04, -#endif - -#ifdef CONFIG_USB_PENWELL_OTG - PMU_USB_OTG_LSS_06, -#endif - -#ifdef TELEPHONY_ENABLE_S0IX - PMU_SPI3_LSS_36, -#endif - -#ifdef DWSPI_ENABLE_S0IX - PMU_SPI1_LSS_18, -#endif - -#ifdef WLAN_ENABLE_S0IX - PMU_SDIO1_LSS_30, -#endif - -#ifdef I2C_ENABLE_S0IX - PMU_I2C0_LSS_20, - PMU_I2C1_LSS_21, - PMU_I2C2_LSS_27, - PMU_I2C3_LSS_33, - PMU_I2C4_LSS_34, - PMU_I2C5_LSS_35, -#endif - - PMU_UART2_LSS_41, - -}; -static u32 LPMP3_CFG[4]; -static u32 lpmp3_target[4]; - -/* These are the LSS that need to be kept - * always ON D0i0, you can add any LSS id - * that you need to keep always on here. - */ -static u8 lss_to_ignore[] = { - PMU_USB_HSIC_LSS_07, - PMU_SRAM_LSS_10, - PMU_SRAM_LSS_11, - PMU_SRAM_LSS_12, - PMU_SRAM_LSS_13, - PMU_PTI_DAFCA_LSS_15, - PMU_SC_DMA_LSS_16, - PMU_SPIO_LSS_17, - PMU_MAIN_FABRIC_LSS_22, - PMU_SEC_FABRIC_LSS_23, - PMU_SC_FABRIC_LSS_24, - PMU_SCU_ROM_LSS_26, - PMU_SSC_LSS_28, - PMU_SECURITY_LSS_29, - PMU_SCU_RAM0_LSS_31, - PMU_SCU_RAM1_LSS_32, - PMU_GPIO1_LSS_37, - PMU_PWR_BUTTON_LSS_38, - PMU_GPIO0_LSS_39, - PMU_ADC_LSS_42, - PMU_CHARGER_LSS_43, - PMU_SEC_TAPC_LSS_44, - PMU_RTC_LSS_45, - PMU_GPI_LSS_46, - PMU_HDMI_VREG_LSS_47, - PMU_IOSF_OCP_BRG_LSS_53, - PMU_SVID_LSS_55, - PMU_SOC_FUSE_LSS_56, - PMU_RSVD3_LSS_57, - PMU_RSVD4_LSS_58, - PMU_RSVD5_LSS_59, - PMU_RSVD6_LSS_60, - PMU_RSVD7_LSS_61, - PMU_RSVD8_LSS_62, - PMU_RSVD9_LSS_63 -}; -static u32 IGNORE_CFG[4]; - -/* These are the LSS that need - * to be configured in SSS registers - * before issuing S0i1 command - */ -static u8 s0i1_sss_lss[] = { - PMU_SDIO0_LSS_00, - PMU_EMMC0_LSS_01, - PMU_AONT_LSS_02, - PMU_HSI_LSS_03, - PMU_SECURITY_LSS_04, - PMU_EMMC1_LSS_05, - PMU_USB_OTG_LSS_06, - PMU_USB_HSIC_LSS_07, - PMU_AUDIO_ENGINE_LSS_08, - PMU_AUDIO_DMA_LSS_09, - PMU_SRAM_LSS_12, - PMU_SRAM_LSS_13, - PMU_SDIO2_LSS_14, - PMU_SPI1_LSS_18, - PMU_SPI2_LSS_19, - PMU_I2C0_LSS_20, - PMU_I2C1_LSS_21, - PMU_AUDIO_RAM_LSS_25, - PMU_I2C2_LSS_27, - PMU_SDIO1_LSS_30, - PMU_I2C3_LSS_33, - PMU_I2C4_LSS_34, - PMU_I2C5_LSS_35, - PMU_SPI3_LSS_36, - PMU_GPIO1_LSS_37, - PMU_PWR_BUTTON_LSS_38, - PMU_KEYBRD_LSS_40, - PMU_UART2_LSS_41, - PMU_AUDIO_SSP2_LSS_48, - PMU_AUDIO_SLIM1_LSS_49, - PMU_RESET_LSS_50, - PMU_AUDIO_SSP0_LSS_51, - PMU_AUDIO_SSP1_LSS_52, - PMU_GP_DMA_LSS_54 -}; -static u32 s0i1_sss[4]; - -/* These are the LSS that need - * to be configured in SSS registers - * before issuing S0i3 command - */ -static u8 s0i3_sss_lss[] = { - PMU_SDIO0_LSS_00, - PMU_EMMC0_LSS_01, - PMU_AONT_LSS_02, - PMU_HSI_LSS_03, - PMU_SECURITY_LSS_04, - PMU_EMMC1_LSS_05, - PMU_USB_OTG_LSS_06, - PMU_USB_HSIC_LSS_07, - PMU_AUDIO_ENGINE_LSS_08, - PMU_AUDIO_DMA_LSS_09, - PMU_SRAM_LSS_12, - PMU_SRAM_LSS_13, - PMU_SDIO2_LSS_14, - PMU_SPI1_LSS_18, - PMU_SPI2_LSS_19, - PMU_I2C0_LSS_20, - PMU_I2C1_LSS_21, - PMU_AUDIO_RAM_LSS_25, - PMU_I2C2_LSS_27, - PMU_SDIO1_LSS_30, - PMU_I2C3_LSS_33, - PMU_I2C4_LSS_34, - PMU_I2C5_LSS_35, - PMU_SPI3_LSS_36, - PMU_GPIO1_LSS_37, - PMU_PWR_BUTTON_LSS_38, - PMU_KEYBRD_LSS_40, - PMU_UART2_LSS_41, - PMU_AUDIO_SSP2_LSS_48, - PMU_AUDIO_SLIM1_LSS_49, - PMU_RESET_LSS_50, - PMU_AUDIO_SSP0_LSS_51, - PMU_AUDIO_SSP1_LSS_52, - PMU_GP_DMA_LSS_54 -}; -static u32 s0i3_sss[4]; -static u32 s3_sss[4]; - -/* These are the LSS that need - * to be configured in SSSarch/x86/kernel/mid_pmu.c registers - * before issuing LPMP3 command - */ -static u8 lpmp3_sss_lss[] = { - PMU_SDIO0_LSS_00, - PMU_EMMC0_LSS_01, - PMU_AONT_LSS_02, - PMU_HSI_LSS_03, - PMU_SECURITY_LSS_04, - PMU_EMMC1_LSS_05, - PMU_USB_OTG_LSS_06, - PMU_USB_HSIC_LSS_07, - PMU_SDIO2_LSS_14, - PMU_SPI1_LSS_18, - PMU_SPI2_LSS_19, - PMU_I2C0_LSS_20, - PMU_I2C1_LSS_21, - PMU_I2C2_LSS_27, - PMU_SDIO1_LSS_30, - PMU_I2C3_LSS_33, - PMU_I2C4_LSS_34, - PMU_I2C5_LSS_35, - PMU_SPI3_LSS_36, - PMU_GPIO1_LSS_37, - PMU_PWR_BUTTON_LSS_38, - PMU_KEYBRD_LSS_40, - PMU_UART2_LSS_41, - PMU_AUDIO_SLIM1_LSS_49, - PMU_RESET_LSS_50, - PMU_AUDIO_SSP0_LSS_51, - PMU_AUDIO_SSP1_LSS_52, - PMU_GP_DMA_LSS_54 -}; -static u32 lpmp3_sss[4]; - -/* These are the LSS that need to be ignored - * as wake sources when in S3 - */ -static u8 ignore_lss_in_wkc[] = { - PMU_AONT_LSS_02, - PMU_ADC_LSS_42 -}; -static u32 IGNORE_WKC_S3_CFG[2]; - -static struct pci_dev_index pci_dev_hash[MID_PCI_INDEX_HASH_SIZE]; - - -static int dev_init_state; -static struct intel_mid_base_addr base_addr; -static struct mrst_pmu_reg __iomem *pmu_reg; - -#ifdef CONFIG_HAS_WAKELOCK -static struct wake_lock pmu_wake_lock; -#endif - -static u32 apm_base; -static u32 ospm_base; -static spinlock_t nc_ready_lock; - -/* - * Locking strategy:: - * - * Two semaphores are used to lock the global variables used in - * the code. The entry points in pmu driver are pmu_pci_set_power_state() - * and PMU interrupt handler contexts, so here is the flow of how - * the semaphores are used. - * - * In D0ix command case:: - * set_power_state process context: - * set_power_state()->acquire_scu_ready_sem()->issue_interactive_cmd-> - * wait_for_interactive_complete_sem->release scu_ready sem - * - * PMU Interrupt context: - * pmu_interrupt_handler()->release interactive_complete_sem->return - * - * In Idle handler case:: - * Idle context: - * idle_handler()->try_acquire_scu_ready_sem->if acquired-> - * issue s0ix command->return - * - * PMU Interrupt context: - * pmu_Interrupt_handler()->release scu_ready_sem->return - * - */ -static struct semaphore scu_ready_sem = - __SEMAPHORE_INITIALIZER(scu_ready_sem, 1); -static struct semaphore set_mode_complete_sem = - __SEMAPHORE_INITIALIZER(set_mode_complete_sem, 0); - -static int scu_comms_okay = 1; - -#ifdef ENABLE_SCU_WATCHDOG -/* scu semaphore watchdog timer */ -static void scu_watchdog_func(unsigned long arg) -{ - struct semaphore* sem = (struct semaphore *) arg; - - WARN(1, "SCU watchdog triggered, dead lock occured," - "diabling SCU comms.\n"); - scu_comms_okay = 0; - - /* unblock the blocking thread */ - up(sem); -} -#endif - -/* - * Acquire the said semaphore and activating a watchdog timer - * that triggers after timeout, if we are able to acquire then - * delete the timer. - */ -static void down_scu_timed(struct semaphore *sem) -{ -#ifdef ENABLE_SCU_WATCHDOG - struct timer_list *scu_watchdog_timer = - kmalloc(sizeof(struct timer_list), GFP_KERNEL); - - if (!scu_watchdog_timer) { - WARN(1, "Malloc failed.\n"); - return; - } - - init_timer(scu_watchdog_timer); - scu_watchdog_timer->function = scu_watchdog_func; - scu_watchdog_timer->data = (unsigned long) sem; - - /*10secs timeout*/ - scu_watchdog_timer->expires = - jiffies + msecs_to_jiffies(10 * 1000); - add_timer(scu_watchdog_timer); -#endif - - down(sem); - -#ifdef ENABLE_SCU_WATCHDOG - del_timer_sync(scu_watchdog_timer); - kfree(scu_watchdog_timer); -#endif -} - -/* Device information for all the PCI devices present on SC */ -static struct pci_dev_info intel_mid_pci_devices[MAX_DEVICES]; -static int num_wakes[MAX_DEVICES]; -static int cmd_error_int; -static u64 pmu_init_time; -static u8 pmu_in_s3; -static struct mid_pmu_stats { - u64 err_count[3]; - u64 count; - u64 time; - u64 last_entry; - u64 last_try; - u64 first_entry; -} pmu_stats[SYS_STATE_S5]; -static enum sys_state pmu_current_state; - -static void pmu_stat_start(enum sys_state type) -{ - pmu_current_state = type; - pmu_stats[type].last_try = cpu_clock(smp_processor_id()); -} - -static void pmu_stat_end(void) -{ - enum sys_state type = pmu_current_state; - - if (type > SYS_STATE_S0I0) { - pmu_stats[type].last_entry = - pmu_stats[type].last_try; - - /*if it is the first entry save the time*/ - if (!pmu_stats[type].count) - pmu_stats[type].first_entry = - pmu_stats[type].last_entry; - - pmu_stats[type].time += - cpu_clock(smp_processor_id()) - - pmu_stats[type].last_entry; - - pmu_stats[type].count++; - } - - pmu_current_state = SYS_STATE_S0I0; -} - -static void pmu_stat_clear(void) -{ - pmu_current_state = SYS_STATE_S0I0; -} - -static void pmu_stat_error(u8 err_type) -{ - enum sys_state type = pmu_current_state; - u8 err_index; - - if (type > SYS_STATE_S0I0) { - switch (err_type) { - case SUBSYS_POW_ERR_INT: - trace_printk("S0ix_POW_ERR_INT\n"); - err_index = 0; - break; - case S0ix_MISS_INT: - trace_printk("S0ix_MISS_INT\n"); - err_index = 1; - break; - case NO_ACKC6_INT: - trace_printk("S0ix_ACKC6_INT\n"); - err_index = 2; - break; - default: - err_index = 3; - break; - } - - if (err_index < 3) - pmu_stats[type].err_count[err_index]++; - } -} - -static void pmu_stat_seq_printf(struct seq_file *s, int type, char *typestr) -{ - unsigned long long t; - unsigned long nanosec_rem, remainder; - unsigned long time, init_2_now_time; - - seq_printf(s, "%s\t%5llu\t%10llu\t%9llu\t%9llu\t", typestr, - pmu_stats[type].count, - pmu_stats[type].err_count[0], - pmu_stats[type].err_count[1], - pmu_stats[type].err_count[2]); - - t = pmu_stats[type].time; - nanosec_rem = do_div(t, 1000000000); - - /* convert time in secs */ - time = (unsigned long)t; - - seq_printf(s, "%5lu.%06lu\t", - (unsigned long) t, nanosec_rem / 1000); - - t = pmu_stats[type].last_entry; - nanosec_rem = do_div(t, 1000000000); - seq_printf(s, "%5lu.%06lu\t", - (unsigned long) t, nanosec_rem / 1000); - - t = pmu_stats[type].first_entry; - nanosec_rem = do_div(t, 1000000000); - seq_printf(s, "%5lu.%06lu\t", - (unsigned long) t, nanosec_rem / 1000); - - t = cpu_clock(raw_smp_processor_id()); - t -= pmu_init_time; - nanosec_rem = do_div(t, 1000000000); - - init_2_now_time = (unsigned long) t; - - /* for calculating percentage residency */ - time = time * 100; - t = (u64) time; - remainder = do_div(t, init_2_now_time); - time = (unsigned long) t; - - /* for getting 3 digit precision after - * decimal dot */ - remainder *= 1000; - t = (u64) remainder; - remainder = do_div(t, init_2_now_time); - seq_printf(s, "%5lu.%03lu\n", time, (unsigned long) t); -} - -/*Experimentally enabling S0i3 as extended C-States*/ -static char s0ix[5] = "s0i3"; -static int extended_cstate_mode = MID_S0I3_STATE; -static int set_extended_cstate_mode(const char *val, struct kernel_param *kp) -{ - char valcp[5]; - strncpy(valcp, val, 5); - valcp[4] = '\0'; - -#ifdef CONFIG_HAS_WAKELOCK - /* will also disable s0ix */ - if (strcmp(valcp, "s3s3") == 0) - wake_unlock(&pmu_wake_lock); -#endif - - /* Acquire the scu_ready_sem */ - down_scu_timed(&scu_ready_sem); - - if (strcmp(valcp, "s0i3") == 0) - extended_cstate_mode = MID_S0I3_STATE; - else if (strcmp(valcp, "s0i1") == 0) - extended_cstate_mode = MID_S0I1_STATE; - else if (strcmp(valcp, "s0ix") == 0) - extended_cstate_mode = MID_S0IX_STATE; - else { - extended_cstate_mode = -1; - strncpy(valcp, "none", 5); - } - strncpy(s0ix, valcp, 5); - - up(&scu_ready_sem); - - return 0; -} - -/* Maps pci power states to SCU D0ix mask */ -static int pci_2_mfld_state(pci_power_t pci_state) -{ - int mfld_state = D0I0_MASK; - - switch (pci_state) { - case PCI_D0: - mfld_state = D0I0_MASK; - break; - - case PCI_D1: - mfld_state = D0I1_MASK; - break; - - case PCI_D2: - mfld_state = D0I2_MASK; - break; - - case PCI_D3cold: - case PCI_D3hot: - mfld_state = D0I3_MASK; - break; - - default: - WARN(1, "%s: wrong pci_state received.\n", __func__); - break; - } - - return mfld_state; -} - -static int get_extended_cstate_mode(char *buffer, struct kernel_param *kp) -{ - strcpy(buffer, s0ix); - return 4; -} - -module_param_call(s0ix, set_extended_cstate_mode, - get_extended_cstate_mode, NULL, 0644); -MODULE_PARM_DESC(s0ix, - "setup extended c state s0ix mode [s0i3|s0i1|s0ix|none]"); - -/* the device object */ -static struct pci_dev *pmu_dev; - -/*virtual memory address for PMU base returned by ioremap_nocache().*/ -static struct mid_pmu_dev intel_mid_pmu_base; - -#ifdef CONFIG_VIDEO_ATOMISP -static int camera_off; -#else -static int camera_off = 1; -#endif - -#ifdef GFX_ENABLE -static int display_off; -#else -/* If Gfx is disabled - * assume s0ix is not blocked - * from gfx side - */ -static int display_off = 1; -#endif - -static int s0i1_possible; -static int lpmp3_possible; -static int s0i3_possible; -static int c6_demoted; -static int interactive_cmd_sent; -static int s0ix_entered; -static u32 pmu1_max_devs, pmu2_max_devs, ss_per_reg; - -static int _pmu_issue_command(struct pmu_ss_states *pm_ssc, int mode, int ioc, - int pmu_num); -static void pmu_read_sss(struct pmu_ss_states *pm_ssc); -static int _pmu2_wait_not_busy(void); - -/* PCI Device Id structure */ -static DEFINE_PCI_DEVICE_TABLE(mid_pm_ids) = { - {PCI_VDEVICE(INTEL, MID_PMU_MRST_DRV_DEV_ID), 0}, - {PCI_VDEVICE(INTEL, MID_PMU_MFLD_DRV_DEV_ID), 0}, - {} -}; - -MODULE_DEVICE_TABLE(pci, mid_pm_ids); - -int get_target_platform_state(void) -{ - if (likely(scu_comms_okay && - (extended_cstate_mode != -1) && display_off\ - && camera_off)) - return extended_cstate_mode; - - return 0; -} -EXPORT_SYMBOL(get_target_platform_state); - -static int _pmu_read_status(int pmu_num, int type) -{ - u32 temp; - union pmu_pm_status result; - - temp = readl(&pmu_reg->pm_sts); - - /* extract the busy bit */ - result.pmu_status_value = temp; - - if (type == PMU_BUSY_STATUS) - return result.pmu_status_parts.pmu_busy; - else if (type == PMU_MODE_ID) - return result.pmu_status_parts.mode_id; - - return 0; -} - -static int _pmu2_wait_not_busy(void) -{ - int pmu_busy_retry = 500000; - - /* wait 500ms that the latest pmu command finished */ - while (--pmu_busy_retry) { - if (_pmu_read_status(PMU_NUM_2, PMU_BUSY_STATUS) == 0) - return 0; - - udelay(1); - } - - WARN(1, "pmu2 busy!"); - - return -EBUSY; -} - -static void pmu_write_subsys_config(struct pmu_ss_states *pm_ssc) -{ - /* South complex in Penwell has multiple registers for - * PM_SSC, etc. - */ - writel(pm_ssc->pmu2_states[0], &pmu_reg->pm_ssc[0]); - - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - writel(pm_ssc->pmu2_states[1], &pmu_reg->pm_ssc[1]); - writel(pm_ssc->pmu2_states[2], &pmu_reg->pm_ssc[2]); - writel(pm_ssc->pmu2_states[3], &pmu_reg->pm_ssc[3]); - } -} - -/** - * pmu_set_cfg_mode_params - platform specific configuration mode parameters - */ -static int pmu_set_cfg_mode_params(struct cfg_mode_params - *cfg_mode_parms, union pmu_pm_set_cfg_cmd_t *command, int pmu_num) -{ - struct cfg_trig_param_t cmd; - - /* parameter check */ - if (cfg_mode_parms->cfg_mode >= CM_INVALID) { - pr_alert("invalid config mode\n"); - return PMU_FAILED; - } - - if (cfg_mode_parms->cfg_cmbi > 1) { - pr_alert("invalid cfg_cmbi bit\n"); - return PMU_FAILED; - } - - if (cfg_mode_parms->cfg_trigger >= INVALID_TRIG) { - pr_alert("invalid cfg_trigger mode\n"); - return PMU_FAILED; - } - - if (command == NULL) { - pr_alert("invalid pointer\n"); - return PMU_FAILED; - } - - if (pmu_num == PMU_NUM_1) { - command->pmu1_params.cfg_mode = cfg_mode_parms->cfg_mode; - command->pmu1_params.cfg_delay = cfg_mode_parms->cfg_delay; - command->pmu1_params.cfg_trigger = cfg_mode_parms->cfg_trigger; - } else if (pmu_num == PMU_NUM_2) { - command->pmu2_params.d_param.cfg_mode = - cfg_mode_parms->cfg_mode; - - /* Based on the cfg_mode set these parameters */ - switch (cfg_mode_parms->cfg_mode) { - case CM_NOP: - case CM_IMMEDIATE: - command->pmu2_params.d_param.cfg_delay = 0; - command->pmu2_params.d_param.rsvd = 0; - break; - case CM_DELAY: - command->pmu2_params.d_param.cfg_delay = - cfg_mode_parms->cfg_delay; - command->pmu2_params.d_param.rsvd = 0; - break; - case CM_TRIGGER: - /* Based on the trigger type construct the cfg_trigger - * parameters - */ - cmd = command->pmu2_params.t_param; - switch (cfg_mode_parms->cfg_trigger) { - case NO_TRIG: - cmd.cfg_trig_type = cfg_mode_parms->cfg_trigger; - cmd.cmbi = cfg_mode_parms->cfg_cmbi; - cmd.rsvd1 = 0; - cmd.cfg_trig_val = cfg_mode_parms->cfg_trig_val; - break; - case LPM_EVENT_TRIG: - cmd.cfg_trig_type = cfg_mode_parms->cfg_trigger; - cmd.cmbi = cfg_mode_parms->cfg_cmbi; - cmd.rsvd1 = 0; - if (cfg_mode_parms->cfg_trig_val != PME_ID_LPE - && cfg_mode_parms->cfg_trig_val != - PME_ID_USB) { - pr_alert("pme_Id" - "not supported in this release\n"); - return PMU_FAILED; - } - cmd.cfg_trig_val = cfg_mode_parms->cfg_trig_val; - break; - case EXT_GPIO_INPUT_TRIG: - cmd.cfg_trig_type = cfg_mode_parms->cfg_trigger; - cmd.cmbi = cfg_mode_parms->cfg_cmbi; - cmd.rsvd1 = 0; - cmd.cfg_trig_val = cfg_mode_parms->cfg_trig_val; - break; - case C_STATE_TRANS_TRIG: - cmd.cfg_trig_type = cfg_mode_parms->cfg_trigger; - cmd.cmbi = cfg_mode_parms->cfg_cmbi; - cmd.rsvd1 = 0; - cmd.cfg_trig_val = cfg_mode_parms->cfg_trig_val; - break; - default: - pr_alert("invalid state\n"); - return PMU_FAILED; - break; - }; - command->pmu2_params.t_param = cmd; - break; - default: - WARN_ON(1); - return PMU_FAILED; - }; - } - return 0; -} - -/** - * pmu_send_set_config_command - Platform specific function to send - * configuration commands to Firmware - */ -static int pmu_send_set_config_command(union pmu_pm_set_cfg_cmd_t - *command, u8 ioc, enum sys_state state, int pmu_num) -{ - /* parameter check */ - if ((ioc != 1) && (ioc != 0)) { - pr_alert("invalid ioc bit\n"); - return PMU_FAILED; - } - - /* construct the command to send SET_CFG to particular PMU */ - if (pmu_num == PMU_NUM_1) { - command->pmu1_params.cmd = SET_CFG_CMD; - command->pmu1_params.ioc = ioc; - command->pmu1_params.mode_id = MODE_ID_MAGIC_NUM; - command->pmu1_params.rsvd = 0; - } else if (pmu_num == PMU_NUM_2) { - command->pmu2_params.d_param.cmd = - SET_CFG_CMD; - command->pmu2_params.d_param.ioc = ioc; - command->pmu2_params.d_param.mode_id = - MODE_ID_MAGIC_NUM; - - /* set the sys state */ - switch (state) { - case SYS_STATE_S0I0: - case SYS_STATE_S0I1: - case SYS_STATE_S0I3: - command->pmu2_params. - d_param.sys_state = state; - break; - default: - pr_alert("invalid state\n"); - return PMU_FAILED; - break; - } - } - - /* write the value of PM_CMD into particular PMU */ - dev_dbg(&pmu_dev->dev, "command being written %x\n", \ - command->pmu_pm_set_cfg_cmd_value); - - writel(command->pmu_pm_set_cfg_cmd_value, &pmu_reg->pm_cmd); - - return 0; -} - -/* return the last wake source id, and make statistics about wake sources */ -static int pmu_get_wake_source(void) -{ - u32 wake0, wake1; - int i; - int source = INVALID_WAKE_SRC; - - wake0 = readl(&pmu_reg->pm_wks[0]); - wake1 = readl(&pmu_reg->pm_wks[1]); - - while (wake0) { - i = fls(wake0) - 1; - source = i + pmu1_max_devs; - num_wakes[source]++; - trace_printk("wake_from_lss%d\n", source - pmu1_max_devs); - wake0 &= ~(1<pm_ics); - result.pmu_pm_ics_value = temp; - - /* return the pm interrupt status int pending bit info */ - return result.pmu_pm_ics_parts.int_pend; -} - -static inline void pmu_clear_interrupt_pending(int pmu_num) -{ - u32 temp; - - /* read the pm interrupt status register */ - temp = readl(&pmu_reg->pm_ics); - - /* write into the PM_ICS register */ - writel(temp, &pmu_reg->pm_ics); -} - -static inline void pmu_enable_interrupt_from_pmu(int pmu_num) -{ - u32 temp; - union pmu_pm_ics result; - - /* read the pm interrupt status register */ - temp = readl(&pmu_reg->pm_ics); - result = (union pmu_pm_ics)temp; - - result.pmu_pm_ics_parts.int_enable = 1; - - /* enable the interrupts */ - writel(result.pmu_pm_ics_value, &pmu_reg->pm_ics); -} - -static inline int pmu_read_interrupt_status(int pmu_num) -{ - u32 temp; - union pmu_pm_ics result; - - /* read the pm interrupt status register */ - temp = readl(&pmu_reg->pm_ics); - - result.pmu_pm_ics_value = temp; - - if (result.pmu_pm_ics_parts.int_status == 0) - return PMU_FAILED; - - /* return the pm interrupt status int pending bit info */ - return result.pmu_pm_ics_parts.int_status; -} - -/** - * This is a helper function used to program pm registers - * in SCU. We configure the wakeable devices & the - * wake sub system states on exit from S0ix state - */ -static inline int _mfld_s0ix_enter(u32 s0ix_value) -{ - struct pmu_ss_states cur_pmsss; - - /* If display status is 0 retry on next c6 */ - if (unlikely((display_off == 0) || (camera_off == 0))) { - up(&scu_ready_sem); - goto ret; - } - - /* If PMU is busy, we'll retry on next C6 */ - if (unlikely(_pmu_read_status(PMU_NUM_2, PMU_BUSY_STATUS))) { - up(&scu_ready_sem); - goto ret; - } - - /* setup the wake capable devices */ - writel(intel_mid_pmu_base.ss_config->wake_state.wake_enable[0], - &pmu_reg->pm_wkc[0]); - writel(intel_mid_pmu_base.ss_config->wake_state.wake_enable[1], - &pmu_reg->pm_wkc[1]); - - /* Re-program the sub systems state on wakeup as the current SSS*/ - pmu_read_sss(&cur_pmsss); - - writel(cur_pmsss.pmu2_states[0], &pmu_reg->pm_wssc[0]); - writel(cur_pmsss.pmu2_states[1], &pmu_reg->pm_wssc[1]); - writel(cur_pmsss.pmu2_states[2], &pmu_reg->pm_wssc[2]); - writel(cur_pmsss.pmu2_states[3], &pmu_reg->pm_wssc[3]); - - switch (s0ix_value) { - case S0I1_VALUE: - wrmsr(MSR_C6OFFLOAD_CTL_REG, - MSR_C6OFFLOAD_CLEAR_LOW, MSR_C6OFFLOAD_CLEAR_HIGH); - writel(s0i1_sss[0], &pmu_reg->pm_ssc[0]); - writel(s0i1_sss[1], &pmu_reg->pm_ssc[1]); - writel(s0i1_sss[2], &pmu_reg->pm_ssc[2]); - writel(s0i1_sss[3], &pmu_reg->pm_ssc[3]); - pmu_stat_start(SYS_STATE_S0I1); - break; - - case LPMP3_VALUE: - wrmsr(MSR_C6OFFLOAD_CTL_REG, - MSR_C6OFFLOAD_CLEAR_LOW, MSR_C6OFFLOAD_CLEAR_HIGH); - writel(lpmp3_sss[0], &pmu_reg->pm_ssc[0]); - writel(lpmp3_sss[1], &pmu_reg->pm_ssc[1]); - writel(lpmp3_sss[2], &pmu_reg->pm_ssc[2]); - writel(lpmp3_sss[3], &pmu_reg->pm_ssc[3]); - pmu_stat_start(SYS_STATE_S0I2); - break; - - case S0I3_VALUE: - writel(s0i3_sss[0], &pmu_reg->pm_ssc[0]); - writel(s0i3_sss[1], &pmu_reg->pm_ssc[1]); - writel(s0i3_sss[2], &pmu_reg->pm_ssc[2]); - writel(s0i3_sss[3], &pmu_reg->pm_ssc[3]); - pmu_stat_start(SYS_STATE_S0I3); - break; - } - - /* issue a command to SCU */ - writel(s0ix_value, &pmu_reg->pm_cmd); - return 1; - -ret: - return 0; -} - -int mfld_s0i1_enter(void) -{ - /* check if we can acquire scu_ready_sem - * if we are not able to then do a c6 */ - if (down_trylock(&scu_ready_sem)) - goto ret; - - if (!s0i1_possible && !lpmp3_possible) { - up(&scu_ready_sem); - goto ret; - } - - s0ix_entered = - _mfld_s0ix_enter(s0i1_possible ? S0I1_VALUE : LPMP3_VALUE); - -ret: - return s0ix_entered; -} -EXPORT_SYMBOL(mfld_s0i1_enter); - -int mfld_s0i3_enter(void) -{ - u32 ssw_val = 0; - int num_retry = 15000; - int status = 0; - - /* skip S0i3 if SCU is not okay */ - if (unlikely(!scu_comms_okay)) - goto ret; - - /* check if we can acquire scu_ready_sem - * if we are not able to then do a c6 */ - if (down_trylock(&scu_ready_sem)) - goto ret; - - if (!s0i3_possible) { - up(&scu_ready_sem); - goto ret; - } - - s0ix_entered = _mfld_s0ix_enter(S0I3_VALUE); - - /* If s0i3 command is issued - * then wait for c6 sram offload - * to complete */ - if (s0ix_entered) { - do { - ssw_val = readl(base_addr.offload_reg); - - if ((ssw_val & C6OFFLOAD_BIT_MASK) == C6OFFLOAD_BIT) - break; - - } while (num_retry--); - - /* enable c6Offload only if write access bit is set - * if not then we will demote c6 to a c4 */ - if (likely((ssw_val & C6OFFLOAD_BIT_MASK) == C6OFFLOAD_BIT)) { - wrmsr(MSR_C6OFFLOAD_CTL_REG, - MSR_C6OFFLOAD_SET_LOW, MSR_C6OFFLOAD_SET_HIGH); - status = 1; - } else { - pmu_stat_clear(); - WARN(1, "mid_pmu: error cpu offload bit not set.\n"); - } - } - -ret: - return status; -} -EXPORT_SYMBOL(mfld_s0i3_enter); - -/** - * pmu_sc_irq - pmu driver interrupt handler - * Context: interrupt context - * - * PMU interrupt handler based on the status of the interrupt - * will send net link event to PM Framework. - * - During inactivity interrupt it sends the information of inactivity - * counter that caused the interrupt as net link event. - * - During wake interrupt it sends the information of source of wake - * sub system that caused the wake interrupt as net link event. - */ -static irqreturn_t pmu_sc_irq(int irq, void *ignored) -{ - u8 status = IRQ_NONE; - - /* check if interrup pending bit is set, if not ignore interrupt */ - if (unlikely(!pmu_is_interrupt_pending(PMU_NUM_2))) - goto ret_no_clear; - - /* read the interrupt status */ - status = pmu_read_interrupt_status(PMU_NUM_2); - if (unlikely(status == PMU_FAILED)) - dev_dbg(&pmu_dev->dev, "Invalid interrupt source\n"); - - switch (status) { - case INVALID_INT: - status = IRQ_NONE; - goto ret_no_clear; - - case CMD_COMPLETE_INT: - break; - - case CMD_ERROR_INT: - cmd_error_int++; - break; - - case SUBSYS_POW_ERR_INT: - case NO_ACKC6_INT: - case S0ix_MISS_INT: - pmu_stat_error(status); - break; - - case WAKE_RECEIVED_INT: - (void)pmu_get_wake_source(); - break; - } - - if (status == WAKE_RECEIVED_INT) - pmu_stat_end(); - else - pmu_stat_clear(); - - wrmsr(MSR_C6OFFLOAD_CTL_REG, - MSR_C6OFFLOAD_CLEAR_LOW, MSR_C6OFFLOAD_CLEAR_HIGH); - - /* clear the interrupt pending bit */ - pmu_clear_interrupt_pending(PMU_NUM_2); - - /* - * In case of interactive command - * let the waiting set_power_state() - * release scu_ready_sem - */ - if (interactive_cmd_sent) { - interactive_cmd_sent = 0; - - /* unblock set_power_state() */ - up(&set_mode_complete_sem); - } else { - s0ix_entered = 0; - - /* S0ix case release it */ - up(&scu_ready_sem); - } - - status = IRQ_HANDLED; -ret_no_clear: - return status; -} - -void pmu_enable_forward_msi(void) -{ - writel(0, &pmu_reg->pm_msic); -} -EXPORT_SYMBOL(pmu_enable_forward_msi); - -unsigned long pmu_get_cstate(unsigned long eax) -{ - unsigned long state = eax; - - /* If we get C6 in between s0ix, it should - * be demoted to C4 */ - if ((s0ix_entered) && (eax == C6_HINT)) { - state = C4_HINT; - c6_demoted++; - } else if ((eax == C7_HINT) || (eax == C8_HINT)) { - /* for S0ix choose C6 */ - state = C6_HINT; - } - - return state; -} -EXPORT_SYMBOL(pmu_get_cstate); - -static inline u32 find_index_in_hash(struct pci_dev *pdev, int *found) -{ - u32 h_index; - int i; - - /* assuming pdev is not null */ - WARN_ON(pdev == NULL); - - h_index = jhash_1word(((pdev->vendor<<16)|pdev->device), - MID_PCI_INDEX_HASH_INITVALUE) & MID_PCI_INDEX_HASH_MASK; - - /* assume not found */ - *found = 0; - - for (i = 0; i < MID_PCI_INDEX_HASH_SIZE; i++) { - if (likely(pci_dev_hash[h_index].pdev == pdev)) { - *found = 1; - break; - } - - /* assume no deletions, hence there shouldn't be any - * gaps ie., NULL's */ - if (unlikely(pci_dev_hash[h_index].pdev == NULL)) { - /* found NULL, that means we wont have - * it in hash */ - break; - } - - h_index = (h_index+1)%MID_PCI_INDEX_HASH_SIZE; - } - - /* Assume hash table wont be full */ - WARN_ON(i == MID_PCI_INDEX_HASH_SIZE); - - return h_index; -} - -static int get_pci_to_pmu_index(struct pci_dev *pdev) -{ - int pm, type; - unsigned int base_class; - unsigned int sub_class; - u8 ss; - int index = PMU_FAILED; - u32 h_index; - int found; - - h_index = find_index_in_hash(pdev, &found); - - if (found) - return (int)pci_dev_hash[h_index].index; - - /* if not found, h_index would be where - * we can insert this */ - - base_class = pdev->class >> 16; - sub_class = (pdev->class & SUB_CLASS_MASK) >> 8; - pm = pci_find_capability(pdev, PCI_CAP_ID_VNDR); - - /* read the logical sub system id & cap if present */ - pci_read_config_byte(pdev, pm + 4, &ss); - - /*FIXME:: pci_table is wrong and put bad ss for HSU0 and HSU1 */ - if (pdev->device == 0x81c || pdev->device == 0x81b) - ss = (LOG_SS_MASK | PMU_UART2_LSS_41); - - /*FIXME:: HSI does not have an LSS listed in pci_table */ - if (pdev->device == 0x833) { - dev_warn(&pdev->dev, "HSI pci pm config = 0x%x\n", ss); - ss = (LOG_SS_MASK | PMU_HSI_LSS_03); - } - - type = ss & LOG_SS_MASK; - ss = ss & LOG_ID_MASK; - - /*FIXME:: remove this once IFWI fixes Audio DMA LSS to 9 */ - if (ss == PMU_SC_DMA_LSS_16) - ss = PMU_AUDIO_DMA_LSS_09; - - if ((base_class == PCI_BASE_CLASS_DISPLAY) && !sub_class) - index = 1; - else if ((__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) && - (base_class == PCI_BASE_CLASS_MULTIMEDIA) && - (sub_class == ISP_SUB_CLASS)) - index = MFLD_ISP_POS; - else if (type) - index = pmu1_max_devs + ss; - - if (index != PMU_FAILED) { - /* insert into hash table */ - pci_dev_hash[h_index].pdev = pdev; - - /* assume index never exceeds 0xff */ - WARN_ON(index > 0xFF); - - pci_dev_hash[h_index].index = (u8)index; - - if (index < pmu1_max_devs) { - intel_mid_pci_devices[index].ss_idx = 0; - intel_mid_pci_devices[index].ss_pos = index; - intel_mid_pci_devices[index].pmu_num = PMU_NUM_1; - } else if (index >= pmu1_max_devs && - index < (pmu1_max_devs + pmu2_max_devs)) { - intel_mid_pci_devices[index].ss_idx = ss / ss_per_reg; - intel_mid_pci_devices[index].ss_pos = ss % ss_per_reg; - intel_mid_pci_devices[index].pmu_num = PMU_NUM_2; - } else { - index = PMU_FAILED; - } - - WARN_ON(index == PMU_FAILED); - } - - return index; -} - -static void mid_pci_find_info(struct pci_dev *pdev) -{ - int index, pm; - unsigned int base_class; - unsigned int sub_class; - u8 ss, cap; - int i; - base_class = pdev->class >> 16; - sub_class = (pdev->class & SUB_CLASS_MASK) >> 8; - - pm = pci_find_capability(pdev, PCI_CAP_ID_VNDR); - - /* read the logical sub system id & cap if present */ - pci_read_config_byte(pdev, pm + 4, &ss); - pci_read_config_byte(pdev, pm + 5, &cap); - - /* get the index for the copying of ss info */ - index = get_pci_to_pmu_index(pdev); - - if (index == PMU_FAILED) - return; - - /* initialize gfx subsystem info */ - if ((base_class == PCI_BASE_CLASS_DISPLAY) && !sub_class) { - intel_mid_pci_devices[index].log_id = index; - intel_mid_pci_devices[index].cap = PM_SUPPORT; - } else if ((base_class == PCI_BASE_CLASS_MULTIMEDIA) && - (sub_class == ISP_SUB_CLASS)) { - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - intel_mid_pci_devices[index].log_id = index; - intel_mid_pci_devices[index].cap = PM_SUPPORT; - } else if (ss && cap) { - intel_mid_pci_devices[index].log_id = ss & LOG_ID_MASK; - intel_mid_pci_devices[index].cap = cap; - } - } else if (ss && cap) { - intel_mid_pci_devices[index].log_id = ss & LOG_ID_MASK; - intel_mid_pci_devices[index].cap = cap; - } - - for (i = 0; i < PMU_MAX_LSS_SHARE && - intel_mid_pci_devices[index].dev_driver[i]; i++) { - /* do nothing */ - } - - WARN_ON(i >= PMU_MAX_LSS_SHARE); - - if (i < PMU_MAX_LSS_SHARE) { - intel_mid_pci_devices[index].dev_driver[i] = pdev; - intel_mid_pci_devices[index].dev_power_state[i] = PCI_D0; - } -} - -static void pmu_enumerate(void) -{ - struct pci_dev *pdev = NULL; - unsigned int base_class; - - while ((pdev = pci_get_device(PCI_ID_ANY, PCI_ID_ANY, pdev)) != NULL) { - - /* find the base class info */ - base_class = pdev->class >> 16; - - if (base_class == PCI_BASE_CLASS_BRIDGE) - continue; - - mid_pci_find_info(pdev); - } -} - -static void pmu_read_sss(struct pmu_ss_states *pm_ssc) -{ - pm_ssc->pmu2_states[0] = readl(&pmu_reg->pm_sss[0]); - - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - pm_ssc->pmu2_states[1] = readl(&pmu_reg->pm_sss[1]); - pm_ssc->pmu2_states[2] = readl(&pmu_reg->pm_sss[2]); - pm_ssc->pmu2_states[3] = readl(&pmu_reg->pm_sss[3]); - } else { - pm_ssc->pmu2_states[1] = 0; - pm_ssc->pmu2_states[2] = 0; - pm_ssc->pmu2_states[3] = 0; - } -} - -static bool check_s0ix_possible(struct pmu_ss_states *pmsss) -{ - if (((pmsss->pmu2_states[0] & TARGET_CFG[0]) == - s0ix_target[0]) && - ((pmsss->pmu2_states[1] & TARGET_CFG[1]) == - s0ix_target[1]) && - ((pmsss->pmu2_states[2] & TARGET_CFG[2]) == - s0ix_target[2]) && - ((pmsss->pmu2_states[3] & TARGET_CFG[3]) == - s0ix_target[3])) - return true; - - return false; -} - -static bool check_lpmp3_possible(struct pmu_ss_states *pmsss) -{ - if (((pmsss->pmu2_states[0] & LPMP3_CFG[0]) == - lpmp3_target[0]) && - ((pmsss->pmu2_states[1] & LPMP3_CFG[1]) == - lpmp3_target[1]) && - ((pmsss->pmu2_states[2] & LPMP3_CFG[2]) == - lpmp3_target[2]) && - ((pmsss->pmu2_states[3] & LPMP3_CFG[3]) == - lpmp3_target[3])) - return true; - - return false; -} - -static void pmu_set_s0ix_possible(int state) -{ - /* assume S0ix not possible */ - s0i1_possible = lpmp3_possible = s0i3_possible = 0; - - if (state != PCI_D0) { - struct pmu_ss_states cur_pmsss; - - pmu_read_sss(&cur_pmsss); - - if (likely(check_s0ix_possible(&cur_pmsss))) - s0i1_possible = s0i3_possible = 1; - else if (check_lpmp3_possible(&cur_pmsss)) - lpmp3_possible = 1; - } - -#ifdef CONFIG_HAS_WAKELOCK -#ifdef S0I3_POSSIBLE_WAKELOCK - if (s0i3_possible && wake_lock_active(&pmu_wake_lock)) - wake_unlock(&pmu_wake_lock); - if (!s0i3_possible && !wake_lock_active(&pmu_wake_lock)) - wake_lock(&pmu_wake_lock); -#endif -#endif -} -/* - * For all devices in this lss, we check what is the weakest power state - * - * Thus we dont power down if another device needs more power - */ - -static pci_power_t pmu_pci_get_weakest_state_for_lss(int lss_index, - struct pci_dev *pdev, pci_power_t state) -{ - int i; - pci_power_t weakest = state; - - for (i = 0; i < PMU_MAX_LSS_SHARE; i++) { - if (intel_mid_pci_devices[lss_index].dev_driver[i] == pdev) - intel_mid_pci_devices[lss_index].dev_power_state[i] = - state; - - if (intel_mid_pci_devices[lss_index].dev_driver[i] && - (intel_mid_pci_devices[lss_index].dev_power_state[i] - < weakest)) { - dev_warn(&pdev->dev, "%s:%s prevented me to suspend...\n", - dev_name(&intel_mid_pci_devices[lss_index].dev_driver[i]->dev), - dev_driver_string(&intel_mid_pci_devices[lss_index].dev_driver[i]->dev)); - - weakest = intel_mid_pci_devices[lss_index]. - dev_power_state[i]; - } - } - return weakest; -} - -static int pmu_pci_to_indexes(struct pci_dev *pdev, int *index, - int *pmu_num, int *ss_idx, int *ss_pos) -{ - int i; - - i = get_pci_to_pmu_index(pdev); - if (i == PMU_FAILED) - return PMU_FAILED; - - *index = i; - *ss_pos = intel_mid_pci_devices[i].ss_pos; - *ss_idx = intel_mid_pci_devices[i].ss_idx; - *pmu_num = intel_mid_pci_devices[i].pmu_num; - - return PMU_SUCCESS; -} - -static int wait_for_nc_pmcmd_complete(int verify_mask, int state_type - , int reg_type) -{ - int pwr_sts; - int count = 0; - u32 addr; - - switch (reg_type) { - case APM_REG_TYPE: - addr = apm_base + APM_STS; - break; - case OSPM_REG_TYPE: - addr = ospm_base + OSPM_PM_SSS; - break; - default: - return -EINVAL; - } - - while (true) { - pwr_sts = inl(addr); - if (state_type == OSPM_ISLAND_DOWN) { - if ((pwr_sts & verify_mask) == verify_mask) - break; - else - udelay(10); - } else if (state_type == OSPM_ISLAND_UP) { - if (pwr_sts == verify_mask) - break; - else - udelay(10); - } - count++; - if (WARN_ONCE(count > 500000, "Timed out waiting for P-Unit")) - return -EBUSY; - } - return 0; -} - -/** - * pmu_nc_set_power_state - Callback function is used by all the devices - * in north complex for a platform specific device power on/shutdown. - * Following assumptions are made by this function - * - * Every new request starts from scratch with no assumptions - * on previous/pending request to Punit. - * Caller is responsible to retry if request fails. - * Avoids multiple requests to Punit if target state is - * already in the expected state. - * spin_locks guarantee serialized access to these registers - * and avoid concurrent access from 2d/3d, VED, VEC, ISP & IPH. - * - */ -int pmu_nc_set_power_state(int islands, int state_type, int reg_type) -{ - u32 pwr_cnt = 0; - u32 pwr_mask = 0; - unsigned long flags; - int i, lss, mask; - int ret = 0; - - spin_lock_irqsave(&nc_ready_lock, flags); - - switch (reg_type) { - case APM_REG_TYPE: - pwr_cnt = inl(apm_base + APM_STS); - break; - case OSPM_REG_TYPE: - pwr_cnt = inl(ospm_base + OSPM_PM_SSS); - break; - default: - ret = -EINVAL; - goto unlock; - } - - pwr_mask = pwr_cnt; - for (i = 0; i < OSPM_MAX_POWER_ISLANDS; i++) { - lss = islands & (0x1 << i); - if (lss) { - mask = 0x3 << (2 * i); - if (state_type == OSPM_ISLAND_DOWN) - pwr_mask |= mask; - else if (state_type == OSPM_ISLAND_UP) - pwr_mask &= ~mask; - } - } - - if (pwr_mask != pwr_cnt) { - switch (reg_type) { - case APM_REG_TYPE: - outl(pwr_mask, apm_base + APM_CMD); - break; - case OSPM_REG_TYPE: - outl(pwr_mask, (ospm_base + OSPM_PM_SSC)); - break; - } - - ret = - wait_for_nc_pmcmd_complete(pwr_mask, state_type, reg_type); - } - -unlock: - spin_unlock_irqrestore(&nc_ready_lock, flags); - return ret; -} -EXPORT_SYMBOL(pmu_nc_set_power_state); - -/** - * pmu_pci_set_power_state - Callback function is used by all the PCI devices - * for a platform specific device power on/shutdown. - * - */ -int __ref pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t state) -{ - int i; - u32 pm_cmd_val; - u32 new_value; - int sub_sys_pos, sub_sys_index; - int pmu_num; - struct pmu_ss_states cur_pmssc; - int status = 0; - - /* while booting just ignore this callback from devices */ - /* If SCU is not okay, nothing to do */ - if (unlikely((dev_init_state == 0) || !scu_comms_okay)) - return status; - - /* Try to acquire the scu_ready_sem, if not - * get blocked, until pmu_sc_irq() releases */ - down_scu_timed(&scu_ready_sem); - interactive_cmd_sent = 1; - - status = - pmu_pci_to_indexes(pdev, &i, &pmu_num, &sub_sys_index, &sub_sys_pos); - - if (status) - goto unlock; - - state = pmu_pci_get_weakest_state_for_lss(i, pdev, state); - - /* store the display status */ - if (i == GFX_LSS_INDEX) - display_off = (int)(state != PCI_D0); - - /*Update the Camera status per ISP Driver Suspended/Resumed */ - if (i == MFLD_ISP_POS) - camera_off = (int)(state != PCI_D0); - - if (pmu_num == PMU_NUM_2) { - - /* initialize the current pmssc states */ - memset(&cur_pmssc, 0, sizeof(cur_pmssc)); - - status = _pmu2_wait_not_busy(); - - if (status) - goto unlock; - - pmu_read_sss(&cur_pmssc); - - /* Add old s3_sss values, so we get complete list */ - if (unlikely(pmu_in_s3)) { - cur_pmssc.pmu2_states[0] |= s3_sss[0]; - cur_pmssc.pmu2_states[1] |= s3_sss[1]; - cur_pmssc.pmu2_states[2] |= s3_sss[2]; - cur_pmssc.pmu2_states[3] |= s3_sss[3]; - } - - /* Read the pm_cmd val & update the value */ - pm_cmd_val = - (D0I3_MASK << (sub_sys_pos * BITS_PER_LSS)); - - /* First clear the LSS bits */ - new_value = cur_pmssc.pmu2_states[sub_sys_index] & - (~pm_cmd_val); - - if (state != PCI_D0) { - pm_cmd_val = - (pci_2_mfld_state(state) << - (sub_sys_pos * BITS_PER_LSS)); - - new_value |= pm_cmd_val; - } - - /* nothing to do, so dont do it... */ - if (new_value == cur_pmssc.pmu2_states[sub_sys_index]) - goto unlock; - - cur_pmssc.pmu2_states[sub_sys_index] = new_value; - - /* set the lss positions that need - * to be ignored to D0i0 */ - for (i = 0; i < 4; i++) - cur_pmssc.pmu2_states[i] &= IGNORE_CFG[i]; - - /* no need to issue command if s3 is in progress */ - if (likely(!pmu_in_s3)) { - /* Issue the pmu command to PMU 2 - * flag is needed to distinguish between - * S0ix vs interactive command in pmu_sc_irq() - */ - status = - _pmu_issue_command(&cur_pmssc, SET_MODE, - 1, PMU_NUM_2); - - if (unlikely(status != PMU_SUCCESS)) { - dev_dbg(&pmu_dev->dev, - "Failed to Issue a PM command to PMU2\n"); - goto unlock; - } - - /* - * Wait for interactive command to complete. - * If we dont wait, there is a possibility that - * the driver may access the device before its - * powered on in SCU. - * - */ - down_scu_timed(&set_mode_complete_sem); - - pmu_set_s0ix_possible(state); - } else { - /* - * while s3 is in-progress we only - * store these values and use those - * to configure wakeup after s3 - */ - s3_sss[0] = cur_pmssc.pmu2_states[0]; - s3_sss[1] = cur_pmssc.pmu2_states[1]; - s3_sss[2] = cur_pmssc.pmu2_states[2]; - s3_sss[3] = cur_pmssc.pmu2_states[3]; - } - } - -unlock: - interactive_cmd_sent = 0; - up(&scu_ready_sem); - return status; -} - -static int _pmu_issue_command(struct pmu_ss_states *pm_ssc, int mode, int ioc, - int pmu_num) -{ - union pmu_pm_set_cfg_cmd_t command; - int sys_state = SYS_STATE_S0I0; - struct cfg_mode_params cfg_mode_param; - int status; - u32 tmp; - - /* pmu_issue_command for PMU1 is an NOP */ - if (pmu_num == PMU_NUM_1) - return 0; - - if (_pmu_read_status(PMU_NUM_2, PMU_BUSY_STATUS)) { - dev_dbg(&pmu_dev->dev, "PMU2 is busy, Operation not" - "permitted\n"); - return PMU_FAILED; - } - - - /* enable interrupts in PMU2 so that interrupts are - * propagated when ioc bit for a particular set - * command is set - */ - /* Enable the hardware interrupt */ - tmp = readl(&pmu_reg->pm_ics); - tmp |= 0x100;/* Enable interrupts */ - writel(tmp, &pmu_reg->pm_ics); - - switch (mode) { - case SET_MODE: - cfg_mode_param.cfg_mode = CM_IMMEDIATE; - cfg_mode_param.cfg_trigger = NO_TRIG; - cfg_mode_param.cfg_delay = 0; - cfg_mode_param.cfg_trig_val = 0; - cfg_mode_param.cfg_cmbi = 0; - sys_state = SYS_STATE_S0I0; - break; - case SET_AOAC_S0i1: - cfg_mode_param.cfg_mode = CM_TRIGGER; - cfg_mode_param.cfg_trigger = C_STATE_TRANS_TRIG; - cfg_mode_param.cfg_trig_val = ACK_C6_DMI_MSG; - cfg_mode_param.cfg_delay = 0; - cfg_mode_param.cfg_cmbi = 0; - sys_state = SYS_STATE_S0I1; - break; - case SET_AOAC_S0i2: - cfg_mode_param.cfg_mode = CM_TRIGGER; - cfg_mode_param.cfg_trigger = C_STATE_TRANS_TRIG; - cfg_mode_param.cfg_trig_val = ACK_C6_DMI_MSG; - cfg_mode_param.cfg_delay = 0; - cfg_mode_param.cfg_cmbi = 0; - sys_state = SYS_STATE_S0I2; - break; - case SET_AOAC_S0i3: - cfg_mode_param.cfg_mode = CM_TRIGGER; - cfg_mode_param.cfg_trigger = C_STATE_TRANS_TRIG; - cfg_mode_param.cfg_trig_val = ACK_C6_DMI_MSG; - cfg_mode_param.cfg_delay = 0; - cfg_mode_param.cfg_cmbi = 0; - sys_state = SYS_STATE_S0I3; - break; - case SET_LPAUDIO: - cfg_mode_param.cfg_mode = CM_TRIGGER; - cfg_mode_param.cfg_trigger = LPM_EVENT_TRIG; - cfg_mode_param.cfg_trig_val = PME_ID_USB; - cfg_mode_param.cfg_delay = 0; - cfg_mode_param.cfg_cmbi = 1; - sys_state = SYS_STATE_S0I3; - break; - default: - WARN_ON(1); - status = PMU_FAILED; - goto ret; - } - - /* Configure the sub systems for pmu2 */ - pmu_write_subsys_config(pm_ssc); - - /* Configre the parameters required for config mode */ - status = - pmu_set_cfg_mode_params(&cfg_mode_param, &command, PMU_NUM_2); - if (status != PMU_SUCCESS) - goto ret; - - /* Send the set config command for pmu1 its configured - * for mode CM_IMMEDIATE & hence with No Trigger - */ - status = - pmu_send_set_config_command(&command, ioc, sys_state, PMU_NUM_2); - -ret: - return status; -} - -#ifdef CONFIG_DEBUG_FS -static int pmu_devices_state_show(struct seq_file *s, void *unused) -{ - struct pci_dev *pdev = NULL; - int index, i, pmu_num, ss_idx, ss_pos; - unsigned int base_class; - u32 mask, val, needed; - struct pmu_ss_states cur_pmsss; - char *dstates[] = {"D0", "D0i1", "D0i2", "D0i3"}; - - /* Acquire the scu_ready_sem */ - down_scu_timed(&scu_ready_sem); - - if (_pmu2_wait_not_busy()) - goto unlock; - - pmu_read_sss(&cur_pmsss); - - seq_printf(s, "TARGET_CFG: "); - for (i = 0; i < 4; i++) - seq_printf(s, "%08X ", TARGET_CFG[i]); - - seq_printf(s, "\n"); - seq_printf(s, "SSS: "); - - for (i = 0; i < 4; i++) - seq_printf(s, "%08lX ", cur_pmsss.pmu2_states[i]); - - if (!display_off) - seq_printf(s, "display not suspended: blocking s0ix\n"); - else if (!camera_off) - seq_printf(s, "camera not suspended: blocking s0ix\n"); - else if (s0i3_possible) - seq_printf(s, "can enter s0i1 or s0i3\n"); - else if (lpmp3_possible) - seq_printf(s, "can enter lpmp3\n"); - else - seq_printf(s, "blocking s0ix\n"); - - seq_printf(s, "cmd_error_int count: %d\n", cmd_error_int); - seq_printf(s, "c6_demotion count: %d\n", c6_demoted); - - seq_printf(s, - "\tcount\tsybsys_pow\ts0ix_miss\tno_ack_c6\ttime (secs)\tlast_entry"); - seq_printf(s, "\tfirst_entry\tresidency(%%)\n"); - - pmu_stat_seq_printf(s, SYS_STATE_S0I1, "s0i1"); - pmu_stat_seq_printf(s, SYS_STATE_S0I2, "lpmp3"); - pmu_stat_seq_printf(s, SYS_STATE_S0I3, "s0i3"); - pmu_stat_seq_printf(s, SYS_STATE_S3, "s3"); - - while ((pdev = pci_get_device(PCI_ID_ANY, PCI_ID_ANY, pdev)) != NULL) { - - /* find the base class info */ - base_class = pdev->class >> 16; - - if (base_class == PCI_BASE_CLASS_BRIDGE) - continue; - - if (pmu_pci_to_indexes(pdev, &index, &pmu_num, &ss_idx, - &ss_pos)) - continue; - - if (pmu_num == PMU_NUM_1) - continue; - - mask = (D0I3_MASK << (ss_pos * BITS_PER_LSS)); - val = (cur_pmsss.pmu2_states[ss_idx] & mask) >> - (ss_pos * BITS_PER_LSS); - needed = ((TARGET_CFG[ss_idx] & mask) != 0); - - seq_printf(s, "pci %04x %04X %s %20s: lss:%02d reg:%d" - "mask:%08X wk:% 8d %s %s\n", - pdev->vendor, pdev->device, dev_name(&pdev->dev), - dev_driver_string(&pdev->dev), - index-pmu1_max_devs, ss_idx, mask, num_wakes[index], - dstates[val&3], - (needed && !val) ? "blocking s0ix" : ""); - - } - -unlock: - up(&scu_ready_sem); - return 0; -} - -static int devices_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, pmu_devices_state_show, NULL); -} - -static ssize_t devices_state_write(struct file *file, - const char __user *userbuf, size_t count, loff_t *ppos) -{ - char buf[32]; - int buf_size = min(count, sizeof(buf)-1); - - if (copy_from_user(buf, userbuf, buf_size)) - return -EFAULT; - - /* Acquire the scu_ready_sem */ - down_scu_timed(&scu_ready_sem); - - buf[buf_size] = 0; - - if (((strlen("clear")+1) == buf_size) && - !strncmp(buf, "clear", strlen("clear"))) { - memset(pmu_stats, 0, - (sizeof(struct mid_pmu_stats)*SYS_STATE_S5)); - memset(num_wakes, 0, sizeof(int)*MAX_DEVICES); - cmd_error_int = c6_demoted = 0; - pmu_current_state = SYS_STATE_S0I0; - pmu_init_time = - cpu_clock(raw_smp_processor_id()); - } - - up(&scu_ready_sem); - - return buf_size; -} - -static const struct file_operations devices_state_operations = { - .open = devices_state_open, - .read = seq_read, - .write = devices_state_write, - .llseek = seq_lseek, - .release = single_release, -}; - -static struct lss_definition { - char *lss_name; - char *block; - char *subsystem; -} medfield_lsses[] = { - {"Lss00", "Storage", "SDIO0 (HC2)"}, - {"Lss01", "Storage", "eMMC0 (HC0a)"}, - {"NA", "Storage", "ND_CTL (Note 5)"}, - {"Lss03", "H S I", "H S I DMA"}, - {"Lss04", "Security", "RNG"}, - {"Lss05", "Storage", "eMMC1 (HC0b)"}, - {"Lss06", "USB", "USB OTG (ULPI)"}, - {"NA", "USB", "USB HSIC (Host) (Note 5)"}, - {"Lss08", "Audio", ""}, - {"Lss09", "Audio", ""}, - {"Lss10", "SRAM", " SRAM CTL+SRAM_16KB"}, - {"Lss11", "SRAM", " SRAM CTL+SRAM_16KB"}, - {"Lss12", "SRAM", "SRAM BANK (16KB+3x32KBKB)"}, - {"Lss13", "SRAM", "SRAM BANK(4x32KB)"}, - {"Lss14", "SDIO COMMS", "SDIO2 (HC1b)"}, - {"Lss15", "PTI, DAFCA", " DFX Blocks"}, - {"Lss16", "SC", " DMA"}, - {"NA", "SC", "SPI0/MSIC"}, - {"Lss18", "GP", "SPI1"}, - {"Lss19", "GP", " SPI2"}, - {"Lss20", "GP", " I2C0"}, - {"Lss21", "GP", " I2C1"}, - {"NA", "Fabrics", " Main Fabric"}, - {"NA", "Fabrics", " Secondary Fabric"}, - {"NA", "SC", "SC Fabric"}, - {"Lss25", "Audio", " I-RAM BANK1 (32 + 256KB)"}, - {"NA", "SCU", " ROM BANK1 (18KB+18KB+18KB)"}, - {"Lss27", "GP", "I2C2"}, - {"NA", "SSC", "SSC (serial bus controller to FLIS)"}, - {"Lss29", "Security", "Chaabi AON Registers"}, - {"Lss30", "SDIO COMMS", "SDIO1 (HC1a)"}, - {"NA", "SCU", "I-RAM BANK0 (32KB)"}, - {"NA", "SCU", "I-RAM BANK1 (32KB)"}, - {"Lss33", "GP", "I2C3 (HDMI)"}, - {"Lss34", "GP", "I2C4"}, - {"Lss35", "GP", "I2C5"}, - {"Lss36", "GP", "SSP (SPI3)"}, - {"Lss37", "GP", "GPIO1"}, - {"NA", "GP", "GP Fabric"}, - {"Lss39", "SC", "GPIO0"}, - {"Lss40", "SC", "KBD"}, - {"Lss41", "SC", "UART2:0"}, - {"NA", "NA", "NA"}, - {"NA", "NA", "NA"}, - {"Lss44", "Security", " Security TAPC"}, - {"NA", "MISC", "AON Timers"}, - {"NA", "PLL", "LFHPLL and Spread Spectrum"}, - {"NA", "PLL", "USB PLL"}, - {"Lss48", "Audio", " SSP2 (I2S2)"}, - {"NA", "Audio", "SLIMBUS CTL 1 (note 5)"}, - {"NA", "Audio", "SLIMBUS CTL 2 (note 5)"}, - {"Lss51", "Audio", "SSP0"}, - {"Lss52", "Audio", "SSP1"}, - {"NA", "Bridge", "IOSF to OCP Bridge"}, - {"Lss54", "GP", "DMA"}, - {"NA", "SC", "SVID (Serial Voltage ID)"}, - {"NA", "SOC Fuse", "SoC Fuse Block (note 3)"}, - {"NA", "NA", "NA"}, -}; - -static int medfield_lsses_num = - sizeof(medfield_lsses)/sizeof(medfield_lsses[0]); - -static char *lss_device_status[4] = { "D0i0", "D0i1", "D0i2", "D0i3" }; - -static int show_pmu_lss_status(struct seq_file *s, void *unused) -{ - int sss_reg_index; - int offset; - int lss; - unsigned long status; - unsigned long sub_status; - unsigned long lss_status[4]; - struct lss_definition *entry; - - /* Acquire the scu_ready_sem */ - down_scu_timed(&scu_ready_sem); - - lss_status[0] = readl(&pmu_reg->pm_sss[0]); - lss_status[1] = readl(&pmu_reg->pm_sss[1]); - lss_status[2] = readl(&pmu_reg->pm_sss[2]); - lss_status[3] = readl(&pmu_reg->pm_sss[3]); - lss = 0; - seq_printf(s, "%5s\t%12s %35s %4s\n", - "lss", "block", "subsystem", "state"); - seq_printf(s, "==========================================================\n"); - for (sss_reg_index = 0; sss_reg_index < 4; sss_reg_index++) { - status = lss_status[sss_reg_index]; - for (offset = 0; offset < sizeof(unsigned long) * 8 / 2; - offset++) { - sub_status = status & 3; - if (lss >= medfield_lsses_num) - entry = &medfield_lsses[medfield_lsses_num - 1]; - else - entry = &medfield_lsses[lss]; - seq_printf(s, "%5s\t%12s %35s %4s\n", - entry->lss_name, entry->block, - entry->subsystem, - lss_device_status[sub_status]); - status >>= 2; - lss++; - } - } - - up(&scu_ready_sem); - - return 0; -} - -static int pmu_sss_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, show_pmu_lss_status, NULL); -} - -static const struct file_operations pmu_sss_state_operations = { - .open = pmu_sss_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* DEBUG_FS */ - -/* Reads the status of each driver and updates the LSS values. - * To be called with scu_ready_sem mutex held, and pmu_config - * initialized with '0's - */ -static void update_all_lss_states(struct pmu_ss_states *pmu_config) -{ - int i; - u32 PCIALLDEV_CFG[4] = {0, 0, 0, 0}; - - for (i = 0; i < MAX_DEVICES; i++) { - int pmu_num = - intel_mid_pci_devices[i].pmu_num; - struct pci_dev *pdev = - intel_mid_pci_devices[i].dev_driver[0]; - - if ((pmu_num == PMU_NUM_2) && pdev) { - int ss_idx, ss_pos; - pci_power_t state; - - ss_idx = intel_mid_pci_devices[i].ss_idx; - ss_pos = intel_mid_pci_devices[i].ss_pos; - - /* By default its set to '0' hence - * no need to update PCI_D0 state - */ - state = pmu_pci_get_weakest_state_for_lss - (i, pdev, pdev->current_state); - - pmu_config->pmu2_states[ss_idx] |= - (pci_2_mfld_state(state) << (ss_pos * BITS_PER_LSS)); - - PCIALLDEV_CFG[ss_idx] |= - (D0I3_MASK << (ss_pos * BITS_PER_LSS)); - } - } - - /* We shutdown devices that are in the target config, and that are - not in the pci table, some devices are indeed not advertised in pci - table for certain firmwares. This is the case for HSI firmwares, - SPI3 device is not advertised, and would then prevent s0i3. */ - for (i = 0; i < 4; i++) - pmu_config->pmu2_states[i] |= - TARGET_CFG[i] & (~PCIALLDEV_CFG[i]); -} - -static pci_power_t _pmu_choose_state(int device_lss) -{ - pci_power_t state; - - switch (device_lss) { - case PMU_SECURITY_LSS_04: - state = PCI_D2; - break; - - case PMU_USB_OTG_LSS_06: - case PMU_USB_HSIC_LSS_07: - case PMU_UART2_LSS_41: - state = PCI_D1; - break; - - default: - state = PCI_D3hot; - break; - } - - return state; -} - -static int pmu_init(void) -{ - int i, status; - struct pmu_ss_states pmu_config; - pci_power_t state; - struct pmu_suspend_config *ss_config; - - dev_dbg(&pmu_dev->dev, "PMU Driver loaded\n"); - spin_lock_init(&nc_ready_lock); - - /* initialise s0ix lss list */ - for (i = 0; i < (sizeof(s0ix_lss)/sizeof(u8)); i++) { - TARGET_CFG[s0ix_lss[i]/ss_per_reg] |= - (D0I3_MASK << (s0ix_lss[i]%ss_per_reg * BITS_PER_LSS)); - - state = _pmu_choose_state(s0ix_lss[i]); - s0ix_target[s0ix_lss[i]/ss_per_reg] |= - (pci_2_mfld_state(state) - << (s0ix_lss[i]%ss_per_reg * BITS_PER_LSS)); - } - - /* initialise lpmp3 lss list */ - for (i = 0; i < (sizeof(lpmp3_lss)/sizeof(u8)); i++) { - LPMP3_CFG[lpmp3_lss[i]/ss_per_reg] |= - (D0I3_MASK << (lpmp3_lss[i]%ss_per_reg * BITS_PER_LSS)); - - state = _pmu_choose_state(lpmp3_lss[i]); - lpmp3_target[lpmp3_lss[i]/ss_per_reg] |= - (pci_2_mfld_state(state) - << (lpmp3_lss[i]%ss_per_reg * BITS_PER_LSS)); - } - - /* initialise ignore lss list */ - for (i = 0; i < (sizeof(lss_to_ignore)/sizeof(u8)); i++) - IGNORE_CFG[lss_to_ignore[i]/ss_per_reg] |= - (D0I3_MASK << (lss_to_ignore[i]%ss_per_reg * BITS_PER_LSS)); - - /* All ignored lss should be in D0i0 */ - for (i = 0; i < 4; i++) - IGNORE_CFG[i] = ~IGNORE_CFG[i]; - - /* initialise ignore wkc lss list */ - for (i = 0; i < (sizeof(ignore_lss_in_wkc)/sizeof(u8)); i++) - IGNORE_WKC_S3_CFG[ignore_lss_in_wkc[i]/32] |= - (1 << (ignore_lss_in_wkc[i]%32)); - - /* All ignored lss should be in non wakable state */ - for (i = 0; i < 2; i++) - IGNORE_WKC_S3_CFG[i] = ~IGNORE_WKC_S3_CFG[i]; - - /* initialise s0i1 sss list */ - for (i = 0; i < (sizeof(s0i1_sss_lss)/sizeof(u8)); i++) { - state = _pmu_choose_state(s0i1_sss_lss[i]); - s0i1_sss[s0i1_sss_lss[i]/ss_per_reg] |= (pci_2_mfld_state(state) - << (s0i1_sss_lss[i]%ss_per_reg * BITS_PER_LSS)); - } - - /* initialise s0i3 sss list */ - for (i = 0; i < (sizeof(s0i3_sss_lss)/sizeof(u8)); i++) { - state = _pmu_choose_state(s0i3_sss_lss[i]); - s0i3_sss[s0i3_sss_lss[i]/ss_per_reg] |= (pci_2_mfld_state(state) - << (s0i3_sss_lss[i]%ss_per_reg * BITS_PER_LSS)); - } - - /* initialise lpmp3 sss list */ - for (i = 0; i < (sizeof(lpmp3_sss_lss)/sizeof(u8)); i++) { - state = _pmu_choose_state(lpmp3_sss_lss[i]); - lpmp3_sss[lpmp3_sss_lss[i]/ss_per_reg] |= - (pci_2_mfld_state(state) << - (lpmp3_sss_lss[i]%ss_per_reg * BITS_PER_LSS)); - } - - /* enumerate the PCI configuration space */ - pmu_enumerate(); - -#ifdef CONFIG_DEBUG_FS - /* /sys/kernel/debug/mid_pmu_states */ - (void) debugfs_create_file("mid_pmu_states", S_IFREG | S_IRUGO, - NULL, NULL, &devices_state_operations); - - /* /sys/kernel/debug/pmu_sss_states */ - (void) debugfs_create_file("pmu_sss_states", S_IFREG | S_IRUGO, - NULL, NULL, &pmu_sss_state_operations); -#endif - - /* initialize the state variables here */ - intel_mid_pmu_base.disable_cpu1 = false; - - intel_mid_pmu_base.ss_config = - kzalloc(sizeof(struct pmu_suspend_config), GFP_KERNEL); - - if (intel_mid_pmu_base.ss_config == NULL) { - dev_dbg(&pmu_dev->dev, "Allocation of memory" - "for ss_config has failed\n"); - status = PMU_FAILED; - goto out_err1; - } - - memset(&pmu_config, 0, sizeof(pmu_config)); - - intel_mid_pmu_base.ss_config->ss_state = pmu_config; - - /* initialize for the autonomous S0i3 */ - ss_config = intel_mid_pmu_base.ss_config; - - /* setup the wake capable devices */ - intel_mid_pmu_base.ss_config->wake_state.wake_enable[0] = - WAKE_ENABLE_0; - intel_mid_pmu_base.ss_config->wake_state.wake_enable[1] = - WAKE_ENABLE_1; - - /* Acquire the scu_ready_sem */ - down_scu_timed(&scu_ready_sem); - - /* Now we have initialized the driver - * Allow drivers to get blocked in - * pmu_pci_set_power_state(), until we finish - * first interactive command. - */ - dev_init_state = 1; - - /* get the current status of each of the driver - * and update it in SCU - */ - update_all_lss_states(&pmu_config); - - /* send a interactive command to fw */ - interactive_cmd_sent = 1; - status = _pmu_issue_command(&pmu_config, SET_MODE, 1, PMU_NUM_2); - if (status != PMU_SUCCESS) { - interactive_cmd_sent = 0; - dev_dbg(&pmu_dev->dev,\ - "Failure from pmu mode change to interactive." - " = %d\n", status); - status = PMU_FAILED; - up(&scu_ready_sem); - goto out_err1; - } - - /* - * Wait for interactive command to complete. - * If we dont wait, there is a possibility that - * the driver may access the device before its - * powered on in SCU. - * - */ - down_scu_timed(&set_mode_complete_sem); - - /* In cases were gfx is not enabled - * this will enable s0ix immediately - */ - pmu_set_s0ix_possible(PCI_D3hot); - - up(&scu_ready_sem); - -out_err1: - return status; -} - -/** - * mid_pmu_probe - This is the function where most of the PMU driver - * initialization happens. - */ -static int __devinit mid_pmu_probe(struct pci_dev *dev, - const struct pci_device_id *pci_id) -{ - int ret; - struct mrst_pmu_reg __iomem *pmu; - -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_init(&pmu_wake_lock, WAKE_LOCK_SUSPEND, "mid_pmu"); -#endif - - /* Init the device */ - ret = pci_enable_device(dev); - if (ret) { - pr_err("Mid PM device cant be enabled\n"); - goto out_err0; - } - - /* store the dev */ - pmu_dev = dev; - - ret = pci_request_regions(dev, PMU_DRV_NAME); - if (ret < 0) { - pr_err("pci request region has failed\n"); - goto out_err1; - } - - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - pmu1_max_devs = PMU1_MAX_PENWELL_DEVS; - pmu2_max_devs = PMU2_MAX_PENWELL_DEVS; - ss_per_reg = 16; - } else { - pmu1_max_devs = PMU1_MAX_MRST_DEVS; - pmu2_max_devs = PMU2_MAX_MRST_DEVS; - ss_per_reg = 8; - } - - /* Map the NC PM registers */ - apm_base = MDFLD_MSG_READ32(OSPM_PUNIT_PORT, OSPM_APMBA) & 0xffff; - ospm_base = MDFLD_MSG_READ32(OSPM_PUNIT_PORT, OSPM_OSPMBA) & 0xffff; - - /* Map the memory of pmu1 PMU reg base */ - pmu = pci_iomap(dev, 0, 0); - if (pmu == NULL) { - dev_dbg(&pmu_dev->dev, "Unable to map the PMU2 address" - "space\n"); - ret = PMU_FAILED; - goto out_err2; - } - - pmu_reg = pmu; - - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - /* Map the memory of offload_reg */ - base_addr.offload_reg = ioremap_nocache(0xffd01ffc, 4); - if (base_addr.offload_reg == NULL) { - dev_dbg(&pmu_dev->dev, - "Unable to map the offload_reg address space\n"); - ret = PMU_FAILED; - goto out_err3; - } - } - - if (request_irq(dev->irq, pmu_sc_irq, IRQF_NO_SUSPEND, PMU_DRV_NAME, - NULL)) { - dev_dbg(&pmu_dev->dev, "Registering isr has failed\n"); - ret = PMU_FAILED; - goto out_err3; - } - - /* call pmu init() for initialization of pmu interface */ - ret = pmu_init(); - if (ret != PMU_SUCCESS) { - dev_dbg(&pmu_dev->dev, "PMU initialization has failed\n"); - goto out_err4; - } - - pmu_init_time = - cpu_clock(raw_smp_processor_id()); - - return 0; - -out_err4: - free_irq(dev->irq, &pmu_sc_irq); -out_err3: - pci_iounmap(dev, base_addr.pmu2_base); - base_addr.pmu2_base = NULL; -out_err2: - base_addr.pmu1_base = NULL; -out_err1: - pci_release_region(dev, 0); - pci_disable_device(dev); -out_err0: -#ifdef CONFIG_HAS_WAKELOCK - wake_unlock(&pmu_wake_lock); -#endif - return ret; -} - -static void __devexit mid_pmu_remove(struct pci_dev *dev) -{ - dev_dbg(&pmu_dev->dev, "Mid PM mid_pmu_remove called\n"); - - /* Freeing up the irq */ - free_irq(dev->irq, &pmu_sc_irq); - - /* Freeing up memory allocated for PMU1 & PMU2 */ - if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { - iounmap(base_addr.offload_reg); - base_addr.offload_reg = NULL; - } - pci_iounmap(dev, pmu_reg); - base_addr.pmu1_base = NULL; - base_addr.pmu2_base = NULL; - - /* disable the current PCI device */ - pci_release_region(dev, 0); - pci_disable_device(dev); -} - -static struct pci_driver driver = { - .name = PMU_DRV_NAME, - .id_table = mid_pm_ids, - .probe = mid_pmu_probe, - .remove = __devexit_p(mid_pmu_remove), -}; - -/* return platform specific deepest states that the device can enter */ -pci_power_t pmu_pci_choose_state(struct pci_dev *pdev) -{ - int i; - int sub_sys_pos, sub_sys_index; - int status; - int device_lss; - int pmu_num; - - pci_power_t state = PCI_D3hot; - - if (dev_init_state) { - status = - pmu_pci_to_indexes(pdev, &i, &pmu_num, - &sub_sys_index, &sub_sys_pos); - - if ((status == PMU_SUCCESS) && - (pmu_num == PMU_NUM_2)) { - - device_lss = (sub_sys_index * ss_per_reg) + sub_sys_pos; - - state = _pmu_choose_state(device_lss); - } - } - - return state; -} -EXPORT_SYMBOL(pmu_pci_choose_state); - -bool pmu_pci_power_manageable(struct pci_dev *dev) -{ - return true; -} -EXPORT_SYMBOL(pmu_pci_power_manageable); - -/* At this point of time we expect all devices to be - * wake capable will be modified in future - */ -bool pmu_pci_can_wakeup(struct pci_dev *dev) -{ - return true; -} -EXPORT_SYMBOL(pmu_pci_can_wakeup); - -int pmu_pci_sleep_wake(struct pci_dev *dev, bool enable) -{ - return 0; -} -EXPORT_SYMBOL(pmu_pci_sleep_wake); - -static int mfld_s3_enter(void) -{ - u32 ssw_val = 0; - int num_retry = 15000; - int status = 0; - - /* check if we can acquire scu_ready_sem - * if we are not able to then do a c6 */ - if (down_trylock(&scu_ready_sem)) { - status = -EINVAL; - goto ret; - } - - /* If PMU is busy, we'll retry on next C6 */ - if (unlikely(_pmu_read_status(PMU_NUM_2, PMU_BUSY_STATUS))) { - up(&scu_ready_sem); - status = -EINVAL; - goto ret; - } - - /* setup the wake capable devices */ - writel(IGNORE_WKC_S3_CFG[0], &pmu_reg->pm_wkc[0]); - writel(IGNORE_WKC_S3_CFG[1], &pmu_reg->pm_wkc[1]); - - /* Re-program the sub systems state on wakeup as the current SSS*/ - writel(s3_sss[0], &pmu_reg->pm_wssc[0]); - writel(s3_sss[1], &pmu_reg->pm_wssc[1]); - writel(s3_sss[2], &pmu_reg->pm_wssc[2]); - writel(s3_sss[3], &pmu_reg->pm_wssc[3]); - - /* program pm ssc registers */ - writel(s0i3_sss[0], &pmu_reg->pm_ssc[0]); - writel(s0i3_sss[1], &pmu_reg->pm_ssc[1]); - writel(s0i3_sss[2], &pmu_reg->pm_ssc[2]); - writel(s0i3_sss[3], &pmu_reg->pm_ssc[3]); - - /* issue a command to SCU */ - writel(S0I3_VALUE, &pmu_reg->pm_cmd); - - /* If s0i3 command is issued - * then wait for c6 sram offload - * to complete */ - do { - ssw_val = readl(base_addr.offload_reg); - - if ((ssw_val & C6OFFLOAD_BIT_MASK) == C6OFFLOAD_BIT) - break; - - } while (num_retry--); - - if (unlikely((ssw_val & C6OFFLOAD_BIT_MASK) != C6OFFLOAD_BIT)) { - status = -EINVAL; - pmu_stat_clear(); - WARN(1, "mid_pmu: error cpu offload bit not set.\n"); - } else { - unsigned long ecx = 1; /* break on interrupt flag */ - unsigned long eax = C6_HINT; - u32 temp = 0; - pmu_stat_start(SYS_STATE_S3); - - /* issue c6 offload */ - wrmsr(MSR_C6OFFLOAD_CTL_REG, - MSR_C6OFFLOAD_SET_LOW, MSR_C6OFFLOAD_SET_HIGH); - - __monitor((void *) &temp, 0, 0); - smp_mb(); - - s0ix_entered = 1; - __mwait(eax, ecx); - pmu_enable_forward_msi(); - } - -ret: - return status; -} - -static int mid_valid(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_ON: - case PM_SUSPEND_MEM: - return 1; - default: - return 0; - } -} - -static int mid_prepare(void) -{ - memset(s3_sss, 0, sizeof(s3_sss)); - pmu_in_s3 = 1; - return 0; -} - -static int mid_prepare_late(void) -{ - return 0; -} - -static int mid_suspend(suspend_state_t state) -{ - int ret; - - if (state != PM_SUSPEND_MEM) - ret = -EINVAL; - - trace_printk("s3_entry\n"); - ret = mfld_s3_enter(); - trace_printk("s3_exit %d\n", ret); - if (ret != 0) - dev_dbg(&pmu_dev->dev, "Failed to enter S3 status: %d\n", ret); - - return ret; -} - -static void mid_wake(void) -{ - pmu_in_s3 = 0; -} - -static void mid_finish(void) -{ - pmu_in_s3 = 0; -} - -static void mid_end(void) -{ -#ifdef CONFIG_HAS_WAKELOCK - /* Prime the wakelock system to re-suspend after giving other - * threads a chance to wake up and acquire wake lock - * this avoids to put wake lock in other things like pwrbutton - */ - long timeout = HZ; - wake_lock_timeout(&pmu_wake_lock, timeout); -#endif -} - -static struct platform_suspend_ops mid_suspend_ops = { - .valid = mid_valid, - .prepare = mid_prepare, - .prepare_late = mid_prepare_late, - .enter = mid_suspend, - .wake = mid_wake, - .finish = mid_finish, - .end = mid_end, -}; - -/** - * mid_pci_register_init - register the PMU driver as PCI device - */ -static int __init mid_pci_register_init(void) -{ - int ret; - - /* registering PCI device */ - ret = pci_register_driver(&driver); - suspend_set_ops(&mid_suspend_ops); - - return ret; -} -device_initcall(mid_pci_register_init); - -static void __exit mid_pci_cleanup(void) -{ - suspend_set_ops(NULL); - /* registering PCI device */ - pci_unregister_driver(&driver); -} -module_exit(mid_pci_cleanup); diff --git a/arch/x86/platform/mdfld/pmu.h b/arch/x86/platform/mdfld/pmu.h deleted file mode 100644 index e259c4c..0000000 --- a/arch/x86/platform/mdfld/pmu.h +++ /dev/null @@ -1,536 +0,0 @@ -/* - * mid_pmu.h - * Copyright (c) 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _MID_PMU_H_ -#define _MID_PMU_H_ - -#include - -#define PCI_ID_ANY (~0) - -/* P Unit Memory Map */ - -/* PMU1 Register */ -#define PMU1_PMU_BASE_ADDR 0x940 -#define PMU2_PMU_BASE_ADDR 0xFF11D000 - -/* PMU register memory map */ - -/* PMU1/PMU2 PM Status Reg */ -#define PMU_PM_STS_REG 0x00 -/* PMU1/PMU2 PM Command Reg */ -#define PMU_PM_CMD_REG 0x04 -/* PMU1/PMU2 PM Interrupt Control and Status Reg */ -#define PMU_PM_ICS_REG 0x08 -/* PMU1/PMU2 PM subsystem configuration register */ -#define PMU_PM_SSC_REG0 0x20 -#define PMU_PM_SSC_REG1 0x24 -#define PMU_PM_SSC_REG2 0x28 -#define PMU_PM_SSC_REG3 0x2C -/* PMU1/PMU2 PM Subsystem status Reg */ -#define PMU_PM_SSS_REG0 0x30 -#define PMU_PM_SSS_REG1 0x34 -#define PMU_PM_SSS_REG2 0x38 -#define PMU_PM_SSS_REG3 0x3C -/* PMU2 PM Wake Control */ -#define PMU_PM_WKC_REG0 0x10 -#define PMU_PM_WKC_REG1 0x14 -/* PMU2 PM Wake Status Reg */ -#define PMU_PM_WKS_REG0 0x18 -#define PMU_PM_WKS_REG1 0x1C -/* PMU2 PM Wake Status Reg */ -#define PMU_PM_WSSC_REG0 0x40 -#define PMU_PM_WSSC_REG1 0x44 -#define PMU_PM_WSSC_REG2 0x48 -#define PMU_PM_WSSC_REG3 0x4C -/* PMU2 PM Subsystem status Reg */ -#define PMU_PM_C3C4_REG 0x50 -/* PMU2 PM Subsystem status Reg */ -#define PMU_PM_C5C6_REG 0x54 -/* PMU2 PM Subsystem status Reg */ -#define PMU_PM_MSIC_REG 0x58 - -#define ACK_C6_DMI_MSG 0xC2 -#define MODE_ID_MAGIC_NUM 1 -#define PMU1_END_ADDRESS 0x34 -#define PMU2_END_ADDRESS 0x3B8 - -#define PMU2_SS_CFG_MASK 0x00FFFFFF -#define PMU2_WAKE_CFG_MASK 0x00000FFF -#define WAKE_CTRL_DEFAULT 0x1C2 - -/* PM table definitions */ -#define PM_TABLE_BASE 0x1D000 -#define PM_TABLE_PMU1_OFFSET 0x0 -#define PM_TABLE_PMU2_OFFSET 0x0 -#define PM_TABLE_PMU2_LOG_TO_PHY_MAP 0x0 -#define PM_TABLE_MAX 0xF0 -#define PM_TABLE_THRESH_MASK 0xFFFF - -/* Inactivity register definitions */ -#define PMU_INA_INT_STS_REG 0x220 -#define PMU_INA_THRESH_BASE 0x240 -#define PMU_INA_CTR_BASE 0x340 -#define PMU_INA_STS_REG 0x210 -#define PMU_INA_INVALID_SRC 0xFF -#define PMU_INA_CTR_MAX 32 -#define SINGLE_BIT_MASK 0x1 - -/* External timers register definitions */ -#define PMU2_EXT_TIMERS_BASE 0xff11B800 -#define PMU2_EXT_TIMERS_BASE_MAX 0xB0 -#define PMU2_EXT_TIMERS_MAX 8 -#define PMU2_EXT_TIMERS_0_OFFSET 0x14 -#define PMU2_EXT_TIMERS_LOAD_COUNT_REG 0x0 -#define PMU2_EXT_TIMERS_CUR_VAL_REG 0x4 -#define PMU2_EXT_TIMERS_CTRL_REG 0x8 -#define PMU2_EXT_TIMERS_EOI_REG 0xC -#define PMU2_EXT_TIMERS_INT_STATUS_REG 0x10 -#define PMU2_EXT_TIMERS_GLB_INT_STATUS_REG 0xa0 -#define PMU2_EXT_TIMERS_GLB_EOI_REG 0xa4 -#define PMU2_EXT_TIMERS_RAW_INT_STATUS_REG 0xa8 -#define PMU2_EXT_TIMERS_COMP_VER 0xac -#define TIMER_COUNT_ALL_ONES 0xFFFFFFFF -#define TIMER_IS_MASKED 0x4 -#define TIMER_IS_NOT_MASKED 0x3 -#define TIMER_FREE_RUNNING_MODE 0x5 -#define TIMER_USER_DEFINED_MODE 0x2 -#define TIMER_EN_VAL 0x1 - -/* Definitions used for Enumeration */ -#define SFI_PCI_CFG_START 0x80000000 -#define SFI_PCI_CFG_SIZE 256 -#define PMU1_DEV_MASK 0x3FFF -#define PMU2_DEV_MASK 0x3FFFFFFF -#define PM_SUPPORT 0x21 -#define LOG_ID_MASK 0x7F -#define SUB_CLASS_MASK 0xFF00 - -/* Definitions for Message Bus Interface */ -#define MSG_CMD_REG 0xD0 -#define MSG_DATA_REG 0xD4 - -/* Definition for C6 Offload MSR Address */ -#define MSR_C6OFFLOAD_CTL_REG 0x120 - -#define MSR_C6OFFLOAD_SET_LOW 1 -#define MSR_C6OFFLOAD_SET_HIGH 0 - -#define MSR_C6OFFLOAD_CLEAR_LOW 0 -#define MSR_C6OFFLOAD_CLEAR_HIGH 0 - -#define C6OFFLOAD_BIT_MASK 0x2 -#define C6OFFLOAD_BIT 0x2 - -/* Need to be changed after PMU driver is added as PCI device */ -#define MID_PMU_MRST_DRV_DEV_ID 0x0810 -#define MID_PMU_MFLD_DRV_DEV_ID 0x0828 - -#define PMU_DRV_NAME "intel_pmu_driver" - -#define MID_PCI_INDEX_HASH_BITS 7 /*size 128*/ -#define MID_PCI_INDEX_HASH_SIZE (1< LNG PMU1 --> LNC */ -union pmu_pm_ss_cfg { - struct { - u32 ss_0:2; /* cDmi / L1 power domain */ - u32 ss_1:2; /* SD HC0 / Display */ - u32 ss_2:2; /* SD HC1 / GFX */ - u32 ss_3:2; /* Nand / Ved */ - u32 ss_4:2; /* ISP Imaging / Vec */ - u32 ss_5:2; /* Security / Mipi */ - u32 ss_6:2; /* Display / LVDS */ - u32 ss_7:2; /* USB Host */ - u32 ss_8:2; /* USB OTG */ - u32 ss_9:2; /* Audio */ - u32 ss_10:2; /* Gpio */ - u32 ss_11:2; /* Shared SRAM */ - u32 ss_12:2; /* rsvd */ - u32 ss_13:2; /* rsvd */ - u32 ss_14:2; /* rsvd */ - u32 ss_15:2; /* rsvd */ - } pmu_pm_ss_cfg_parts; - u32 pmu_pm_ss_cfg_value; -}; - -union pmu_pm_ss_status { - struct { - u32 ss_0:2; /* cDmi / L1 power domain */ - u32 ss_1:2; /* SD HC0 / Display */ - u32 ss_2:2; /* SD HC1 / GFX */ - u32 ss_3:2; /* Nand / Ved */ - u32 ss_4:2; /* ISP Imaging / Vec */ - u32 ss_5:2; /* Security / Mipi */ - u32 ss_6:2; /* Display / LVDS */ - u32 ss_7:2; /* USB Host */ - u32 ss_8:2; /* USB OTG */ - u32 ss_9:2; /* Audio */ - u32 ss_10:2; /* Gpio */ - u32 ss_11:2; /* Shared SRAM */ - u32 ss_12:2; /* rsvd */ - u32 ss_13:2; /* rsvd */ - u32 ss_14:2; /* rsvd */ - u32 ss_15:2; /* rsvd */ - } pmu_pm_ss_status_parts; - u32 pmu_pm_ss_status_value; -}; - -union pmu_pm_status { - struct { - u32 pmu_rev:8; - u32 pmu_busy:1; - u32 mode_id:4; - u32 Reserved:19; - } pmu_status_parts; - u32 pmu_status_value; -}; - -union pmu_pm_cmd { - struct { - u32 cmd:8; - u32 ioc:1; - u32 pmu_cmd_param:23; - } pmu_pm_cmd_parts; - u32 pmu_pm_cmd_value; -}; - -struct cfg_mode_params { - u32 cfg_mode; - u32 cfg_trigger; - u32 cfg_trig_val; - u32 cfg_delay; - u32 cfg_cmbi; -}; - -/* pmu 1 pm set config parameters */ -struct pmu1_pm_set_cfg_cmd_parts { - u32 cmd:8; - u32 ioc:1; - u32 cfg_mode:4; - u32 cfg_delay:4; - u32 cfg_trigger:4; - u32 mode_id:4; - u32 rsvd:7; -}; - -/* pmu 2 pm set config parameters */ -struct cfg_delay_param_t { - u32 cmd:8; - u32 ioc:1; - u32 cfg_mode:4; - u32 mode_id:3; - u32 sys_state:3; - u32 cfg_delay:8; - u32 rsvd:5; -}; - - -struct cfg_trig_param_t { - u32 cmd:8; - u32 ioc:1; - u32 cfg_mode:4; - u32 mode_id:3; - u32 sys_state:3; - u32 cfg_trig_type:3; - u32 cfg_trig_val:8; - u32 cmbi:1; - u32 rsvd1:1; -}; - -union pmu_pm_set_cfg_cmd_t { - struct pmu1_pm_set_cfg_cmd_parts pmu1_params; - union { - struct cfg_delay_param_t d_param; - struct cfg_trig_param_t t_param; - } pmu2_params; - u32 pmu_pm_set_cfg_cmd_value; -}; - -union pmu_pm_ics { - struct { - u32 int_status:8; - u32 int_enable:1; - u32 int_pend:1; - u32 reserved:22; - } pmu_pm_ics_parts; - u32 pmu_pm_ics_value; -}; - -struct pmu_ospm_reg { - union pmu_pm_status *pm_status; - union pmu_pm_cmd *pm_cmd; - union pmu_pm_ics *pm_ics; - u32 pm_wkc; - u32 rsvd1; - u32 pm_wks; - u32 rsvd2; - union pmu_pm_ss_cfg *pm_ss_cfg; - u32 rsvd3[3]; - union pmu_pm_ss_status *pm_ss_status; - u32 rsvd4[3]; - u32 pm_wssc; - u32 rsvd5[3]; - u32 pm_c3c4_ctr; - u32 pm_c5c6_ctr; - u32 pm_msic; -}; - -struct intel_mid_base_addr { - u32 *pmu1_base; - void __iomem *pmu2_base; - u32 *pm_table_base; - u32 __iomem *offload_reg; -}; - -/*APIs to get the APM base address */ -static inline u32 MDFLD_MSG_READ32(uint port, uint offset) -{ - int mcr = (0x10<<24) | (port << 16) | (offset << 8); - uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_read_config_dword(pci_root, 0xD4, &ret_val); - pci_dev_put(pci_root); - return ret_val; -} -static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) -{ - int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD4, value); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_dev_put(pci_root); -} - -/* API used to change the platform mode */ -extern int pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t state); -extern pci_power_t pmu_pci_choose_state(struct pci_dev *pdev); -extern bool pmu_pci_power_manageable(struct pci_dev *pdev); -extern bool pmu_pci_can_wakeup(struct pci_dev *pdev); -extern int pmu_pci_sleep_wake(struct pci_dev *pdev, bool enable); -#endif diff --git a/arch/x86/platform/mdfld/vrtc.c b/arch/x86/platform/mdfld/vrtc.c deleted file mode 100644 index 34d6055..0000000 --- a/arch/x86/platform/mdfld/vrtc.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * vrtc.c: Driver for virtual RTC device on Intel MID platform - * - * (C) Copyright 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 - * of the License. - * - * Note: - * VRTC is emulated by system controller firmware, the real HW - * RTC is located in the PMIC device. SCU FW shadows PMIC RTC - * in a memory mapped IO space that is visible to the host IA - * processor. - * - * This driver is based on RTC CMOS driver. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -static unsigned char __iomem *vrtc_virt_base; - -unsigned char vrtc_cmos_read(unsigned char reg) -{ - unsigned char retval; - - /* vRTC's registers range from 0x0 to 0xD */ - if (reg > 0xd || !vrtc_virt_base) - return 0xff; - - lock_cmos_prefix(reg); - retval = __raw_readb(vrtc_virt_base + (reg << 2)); - lock_cmos_suffix(reg); - return retval; -} -EXPORT_SYMBOL_GPL(vrtc_cmos_read); - -void vrtc_cmos_write(unsigned char val, unsigned char reg) -{ - if (reg > 0xd || !vrtc_virt_base) - return; - - lock_cmos_prefix(reg); - __raw_writeb(val, vrtc_virt_base + (reg << 2)); - lock_cmos_suffix(reg); -} -EXPORT_SYMBOL_GPL(vrtc_cmos_write); - -unsigned long vrtc_get_time(void) -{ - u8 sec, min, hour, mday, mon; - u32 year; - - while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) - cpu_relax(); - - sec = vrtc_cmos_read(RTC_SECONDS); - min = vrtc_cmos_read(RTC_MINUTES); - hour = vrtc_cmos_read(RTC_HOURS); - mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); - mon = vrtc_cmos_read(RTC_MONTH); - year = vrtc_cmos_read(RTC_YEAR); - - /* vRTC YEAR reg contains the offset to 1972 */ - year += 1972; - - printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " - "mon: %d year: %d\n", sec, min, hour, mday, mon, year); - - return mktime(year, mon, mday, hour, min, sec); -} - -/* Only care about the minutes and seconds */ -int vrtc_set_mmss(unsigned long nowtime) -{ - int real_sec, real_min; - int vrtc_min; - - vrtc_min = vrtc_cmos_read(RTC_MINUTES); - - real_sec = nowtime % 60; - real_min = nowtime / 60; - if (((abs(real_min - vrtc_min) + 15)/30) & 1) - real_min += 30; - real_min %= 60; - - vrtc_cmos_write(real_sec, RTC_SECONDS); - vrtc_cmos_write(real_min, RTC_MINUTES); - return 0; -} - -void __init mrst_rtc_init(void) -{ - unsigned long vrtc_paddr; - - sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); - - vrtc_paddr = sfi_mrtc_array[0].phys_addr; - if (!sfi_mrtc_num || !vrtc_paddr) - return; - - vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC, - vrtc_paddr); - x86_platform.get_wallclock = vrtc_get_time; - x86_platform.set_wallclock = vrtc_set_mmss; -} - -/* - * The Moorestown platform has a memory mapped virtual RTC device that emulates - * the programming interface of the RTC. - */ - -static struct resource vrtc_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device vrtc_device = { - .name = "rtc_mrst", - .id = -1, - .resource = vrtc_resources, - .num_resources = ARRAY_SIZE(vrtc_resources), -}; - -/* Register the RTC device if appropriate */ -static int __init mrst_device_create(void) -{ - /* No Moorestown, no device */ - if (!mrst_identify_cpu()) - return -ENODEV; - /* No timer, no device */ - if (!sfi_mrtc_num) - return -ENODEV; - - /* iomem resource */ - vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr; - vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr + - MRST_VRTC_MAP_SZ; - /* irq resource */ - vrtc_resources[1].start = sfi_mrtc_array[0].irq; - vrtc_resources[1].end = sfi_mrtc_array[0].irq; - - return platform_device_register(&vrtc_device); -} - -module_init(mrst_device_create); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 502dd09..81bd9a3 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -64,9 +64,6 @@ #include #include #include -#ifdef CONFIG_X86_MDFLD -#include -#endif #define INTEL_IDLE_VERSION "0.4" #define PREFIX "intel_idle: " @@ -359,14 +356,9 @@ int intel_mid_idle(struct cpuidle_device *dev, struct cpuidle_state *state) if (!need_resched()) { #ifdef CONFIG_X86_MRST if (eax == -1UL) { - do_s0i3(); - } else -#elseif CONFIG_X86_MDFLD - if (eax == -1UL) { - mfld_s0i3_enter(); - pmu_enable_forward_msi(); + ;//do_s0i3(); } else -#endif +#endif { /* Conventional MWAIT */ diff --git a/include/linux/intel_mid_pm.h b/include/linux/intel_mid_pm.h deleted file mode 100644 index a1a45be..0000000 --- a/include/linux/intel_mid_pm.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * intel_mid_pm.h - * Copyright (c) 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef INTEL_MID_PM_H -#define INTEL_MID_PM_H - -#include -#include -#include - -/* Register Type definitions */ -#define OSPM_REG_TYPE 0x0 -#define APM_REG_TYPE 0x1 -#define OSPM_MAX_POWER_ISLANDS 16 -#define OSPM_ISLAND_UP 0x0 -#define OSPM_ISLAND_DOWN 0x1 - -/* North complex power islands definitions for APM block*/ -#define APM_GRAPHICS_ISLAND 0x1 -#define APM_VIDEO_DEC_ISLAND 0x2 -#define APM_VIDEO_ENC_ISLAND 0x4 -#define APM_GL3_CACHE_ISLAND 0x8 -#define APM_ISP_ISLAND 0x10 -#define APM_IPH_ISLAND 0x20 - -/* North complex power islands definitions for OSPM block*/ -#define OSPM_DISPLAY_A_ISLAND 0x2 -#define OSPM_DISPLAY_B_ISLAND 0x80 -#define OSPM_DISPLAY_C_ISLAND 0x100 -#define OSPM_MIPI_ISLAND 0x200 - -#define C4_HINT (0x30) -#define C6_HINT (0x52) - -#define PMU1_MAX_PENWELL_DEVS 8 -#define PMU2_MAX_PENWELL_DEVS 55 -#define PMU1_MAX_MRST_DEVS 2 -#define PMU2_MAX_MRST_DEVS 15 -#define MAX_DEVICES (PMU1_MAX_PENWELL_DEVS + PMU2_MAX_PENWELL_DEVS) -#define WAKE_CAPABLE 0x80000000 -#define PMU_MAX_LSS_SHARE 4 -#define AUTO_CLK_GATE_VALUE 0x555551 -#define SUB_SYS_D0I2_VALUE 0xaaaaaa -#define WAKE_ENABLE_VALUE 0x4786 -#define SUSPEND_GFX 0xc - -/* Error codes for pmu */ -#define PMU_SUCCESS 0 -#define PMU_FAILED -1 -#define PMU_BUSY_STATUS 0 -#define PMU_MODE_ID 1 -#define SET_MODE 1 -#define SET_AOAC_S0i1 2 -#define SET_AOAC_S0i3 3 -#define SET_LPAUDIO 4 -#define SET_AOAC_S0i2 7 - -struct pci_dev_info { - u8 ss_pos; - u8 ss_idx; - u8 pmu_num; - - u32 log_id; - u32 cap; - struct pci_dev *dev_driver[PMU_MAX_LSS_SHARE]; - pci_power_t dev_power_state[PMU_MAX_LSS_SHARE]; -}; - -struct wk_data { - u32 word0; - u32 word1; -}; - -union wake_config { - struct wk_data data; - u64 long_word; -}; - -struct pmu_wake_ss_states { - unsigned long wake_enable[2]; - unsigned long pmu1_wake_states; - unsigned long pmu2_wake_states[4]; -}; - -struct pmu_ss_states { - unsigned long pmu1_states; - unsigned long pmu2_states[4]; -}; - -struct pmu_suspend_config { - struct pmu_ss_states ss_state; - struct pmu_wake_ss_states wake_state; -}; - -enum pmu_number { - PMU_NUM_1, - PMU_NUM_2, - PMU_MAX_DEVS -}; - -enum pmu_ss_state { - SS_STATE_D0I0 = 0, - SS_STATE_D0I1 = 1, - SS_STATE_D0I2 = 2, - SS_STATE_D0I3 = 3 -}; - -/* PMU event */ -#define PMU_SUBSYS_WAKE 0 -#define PMU_CMD_SUCCESS 1 -#define PMU_CMD_ERROR 2 -#define PMU_CMD_NO_C6_ERROR 3 - -#define EVENT_HANDLER_PATH "/etc/pmu/pmu_event_handler" - -#define C7_HINT (0x200) -#define C8_HINT (0x201) - -#define MID_S0I1_STATE 1 -#define MID_S0I3_STATE 3 -#define MID_S0IX_STATE 4 - -extern int mfld_s0i1_enter(void); -extern int mfld_s0i3_enter(void); -extern int get_target_platform_state(void); -extern void pmu_enable_forward_msi(void); -extern unsigned long pmu_get_cstate(unsigned long eax); -extern int pmu_nc_set_power_state - (int islands, int state_type, int reg_type); - -#endif /* #ifndef INTEL_MID_PM_H */ -- 2.7.4