aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi, Aubrey <aubrey.li@linux.intel.com>2014-06-30 02:08:42 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2014-07-25 17:11:29 -0400
commit93e5eadd1f6e7f45c31aa327c42ac52e4df5ff6f (patch)
treed72d68d835dc4bf65dea67893cc701c78c31b0d2
parent832fcc899a90cce54eb5e47c7fd099eacc0130da (diff)
x86/platform: New Intel Atom SOC power management controller driver
The Power Management Controller (PMC) controls many of the power management features present in the Atom SoC. This driver provides a native power off function via PMC PCI IO port. On some ACPI hardware-reduced platforms(e.g. ASUS-T100), ACPI sleep registers are not valid so that (*pm_power_off)() is not hooked by acpi_power_off(). The power off function in this driver is installed only when pm_power_off is NULL. Signed-off-by: Aubrey Li <aubrey.li@linux.intel.com> Link: http://lkml.kernel.org/r/53B0FEEA.3010805@linux.intel.com Signed-off-by: Lejun Zhu <lejun.zhu@linux.intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/Kconfig4
-rw-r--r--arch/x86/include/asm/pmc_atom.h31
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/pmc_atom.c104
4 files changed, 140 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index a8f749ef0fdc..6295a2182a76 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2403,6 +2403,10 @@ config IOSF_MBI
2403 default m 2403 default m
2404 depends on PCI 2404 depends on PCI
2405 2405
2406config PMC_ATOM
2407 def_bool y
2408 depends on PCI
2409
2406source "net/Kconfig" 2410source "net/Kconfig"
2407 2411
2408source "drivers/Kconfig" 2412source "drivers/Kconfig"
diff --git a/arch/x86/include/asm/pmc_atom.h b/arch/x86/include/asm/pmc_atom.h
new file mode 100644
index 000000000000..03a2769f2d7f
--- /dev/null
+++ b/arch/x86/include/asm/pmc_atom.h
@@ -0,0 +1,31 @@
1/*
2 * Intel Atom SOC Power Management Controller Header File
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef PMC_ATOM_H
17#define PMC_ATOM_H
18
19/* ValleyView Power Control Unit PCI Device ID */
20#define PCI_DEVICE_ID_VLV_PMC 0x0F1C
21
22/* PMC I/O Registers */
23#define ACPI_BASE_ADDR_OFFSET 0x40
24#define ACPI_BASE_ADDR_MASK 0xFFFFFE00
25#define ACPI_MMIO_REG_LEN 0x100
26
27#define PM1_CNT 0x4
28#define SLEEP_TYPE_MASK 0xFFFFECFF
29#define SLEEP_TYPE_S5 0x1C00
30#define SLEEP_ENABLE 0x2000
31#endif /* PMC_ATOM_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 047f9ff2e36c..bde3993624f1 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_EFI) += sysfb_efi.o
106obj-$(CONFIG_PERF_EVENTS) += perf_regs.o 106obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
107obj-$(CONFIG_TRACING) += tracepoint.o 107obj-$(CONFIG_TRACING) += tracepoint.o
108obj-$(CONFIG_IOSF_MBI) += iosf_mbi.o 108obj-$(CONFIG_IOSF_MBI) += iosf_mbi.o
109obj-$(CONFIG_PMC_ATOM) += pmc_atom.o
109 110
110### 111###
111# 64 bit specific files 112# 64 bit specific files
diff --git a/arch/x86/kernel/pmc_atom.c b/arch/x86/kernel/pmc_atom.c
new file mode 100644
index 000000000000..9eb79f6fc512
--- /dev/null
+++ b/arch/x86/kernel/pmc_atom.c
@@ -0,0 +1,104 @@
1/*
2 * Intel Atom SOC Power Management Controller Driver
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/pci.h>
21#include <linux/device.h>
22#include <linux/io.h>
23
24#include <asm/pmc_atom.h>
25
26static u32 acpi_base_addr;
27
28static void pmc_power_off(void)
29{
30 u16 pm1_cnt_port;
31 u32 pm1_cnt_value;
32
33 pr_info("Preparing to enter system sleep state S5\n");
34
35 pm1_cnt_port = acpi_base_addr + PM1_CNT;
36
37 pm1_cnt_value = inl(pm1_cnt_port);
38 pm1_cnt_value &= SLEEP_TYPE_MASK;
39 pm1_cnt_value |= SLEEP_TYPE_S5;
40 pm1_cnt_value |= SLEEP_ENABLE;
41
42 outl(pm1_cnt_value, pm1_cnt_port);
43}
44
45static int pmc_setup_dev(struct pci_dev *pdev)
46{
47 /* Obtain ACPI base address */
48 pci_read_config_dword(pdev, ACPI_BASE_ADDR_OFFSET, &acpi_base_addr);
49 acpi_base_addr &= ACPI_BASE_ADDR_MASK;
50
51 /* Install power off function */
52 if (acpi_base_addr != 0 && pm_power_off == NULL)
53 pm_power_off = pmc_power_off;
54
55 return 0;
56}
57
58/*
59 * Data for PCI driver interface
60 *
61 * This data only exists for exporting the supported
62 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
63 * register a pci_driver, because lpc_ich will register
64 * a driver on the same PCI id.
65 */
66static const struct pci_device_id pmc_pci_ids[] = {
67 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VLV_PMC) },
68 { 0, },
69};
70
71MODULE_DEVICE_TABLE(pci, pmc_pci_ids);
72
73static int __init pmc_atom_init(void)
74{
75 int err = -ENODEV;
76 struct pci_dev *pdev = NULL;
77 const struct pci_device_id *ent;
78
79 /* We look for our device - PCU PMC
80 * we assume that there is max. one device.
81 *
82 * We can't use plain pci_driver mechanism,
83 * as the device is really a multiple function device,
84 * main driver that binds to the pci_device is lpc_ich
85 * and have to find & bind to the device this way.
86 */
87 for_each_pci_dev(pdev) {
88 ent = pci_match_id(pmc_pci_ids, pdev);
89 if (ent) {
90 err = pmc_setup_dev(pdev);
91 goto out;
92 }
93 }
94 /* Device not found. */
95out:
96 return err;
97}
98
99module_init(pmc_atom_init);
100/* no module_exit, this driver shouldn't be unloaded */
101
102MODULE_AUTHOR("Aubrey Li <aubrey.li@linux.intel.com>");
103MODULE_DESCRIPTION("Intel Atom SOC Power Management Controller Interface");
104MODULE_LICENSE("GPL v2");