aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2016-06-14 14:29:45 -0400
committerIngo Molnar <mingo@kernel.org>2016-06-15 04:10:49 -0400
commit5823d0893ec284f37902e2ecd332dbb396a143d1 (patch)
tree34c7bce671c38381612f3899adfae2863160822f
parent9485f8b6a75921e1b9e94b001cdb45872a598534 (diff)
x86/platform/intel-mid: Add Power Management Unit driver
Add Power Management Unit driver to handle power states of South Complex devices on Intel Tangier. In the future it might be expanded to cover North Complex devices as well. With this driver the power state of the host controllers such as SPI, I2C, UART, eMMC, and DMA would be managed. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: David Cohen <david.a.cohen@linux.intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mika Westerberg <mika.westerberg@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-pci@vger.kernel.org Link: http://lkml.kernel.org/r/1465928985-12113-1-git-send-email-andriy.shevchenko@linux.intel.com [ Minor readability edits. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/intel-mid.h8
-rw-r--r--arch/x86/pci/intel_mid_pci.c40
-rw-r--r--arch/x86/platform/intel-mid/Makefile2
-rw-r--r--arch/x86/platform/intel-mid/pwr.c416
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/pci/pci-mid.c77
6 files changed, 540 insertions, 6 deletions
diff --git a/arch/x86/include/asm/intel-mid.h b/arch/x86/include/asm/intel-mid.h
index 7c5af123bdbd..38498a4fb44f 100644
--- a/arch/x86/include/asm/intel-mid.h
+++ b/arch/x86/include/asm/intel-mid.h
@@ -12,9 +12,17 @@
12#define _ASM_X86_INTEL_MID_H 12#define _ASM_X86_INTEL_MID_H
13 13
14#include <linux/sfi.h> 14#include <linux/sfi.h>
15#include <linux/pci.h>
15#include <linux/platform_device.h> 16#include <linux/platform_device.h>
16 17
17extern int intel_mid_pci_init(void); 18extern int intel_mid_pci_init(void);
19extern int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
20
21#define INTEL_MID_PWR_LSS_OFFSET 4
22#define INTEL_MID_PWR_LSS_TYPE (1 << 7)
23
24extern int intel_mid_pwr_get_lss_id(struct pci_dev *pdev);
25
18extern int get_gpio_by_name(const char *name); 26extern int get_gpio_by_name(const char *name);
19extern void intel_scu_device_register(struct platform_device *pdev); 27extern void intel_scu_device_register(struct platform_device *pdev);
20extern int __init sfi_parse_mrtc(struct sfi_table_header *table); 28extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index ae97f24a4371..a9710433be4d 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -316,14 +316,44 @@ static void pci_d3delay_fixup(struct pci_dev *dev)
316} 316}
317DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup); 317DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup);
318 318
319static void mrst_power_off_unused_dev(struct pci_dev *dev) 319static void mid_power_off_dev(struct pci_dev *dev)
320{ 320{
321 u16 pmcsr;
322
323 /*
324 * Update current state first, otherwise PCI core enforces PCI_D0 in
325 * pci_set_power_state() for devices which status was PCI_UNKNOWN.
326 */
327 pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
328 dev->current_state = (pci_power_t __force)(pmcsr & PCI_PM_CTRL_STATE_MASK);
329
321 pci_set_power_state(dev, PCI_D3hot); 330 pci_set_power_state(dev, PCI_D3hot);
322} 331}
323DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mrst_power_off_unused_dev); 332
324DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mrst_power_off_unused_dev); 333DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mid_power_off_dev);
325DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x080C, mrst_power_off_unused_dev); 334DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mid_power_off_dev);
326DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0815, mrst_power_off_unused_dev); 335DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x080C, mid_power_off_dev);
336DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0815, mid_power_off_dev);
337
338static void mrfld_power_off_dev(struct pci_dev *dev)
339{
340 int id;
341
342 if (!pci_soc_mode)
343 return;
344
345 id = intel_mid_pwr_get_lss_id(dev);
346 if (id < 0)
347 return;
348
349 /*
350 * This sets only PMCSR bits. The actual power off will happen in
351 * arch/x86/platform/intel-mid/pwr.c.
352 */
353 mid_power_off_dev(dev);
354}
355
356DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, mrfld_power_off_dev);
327 357
328/* 358/*
329 * Langwell devices reside at fixed offsets, don't try to move them. 359 * Langwell devices reside at fixed offsets, don't try to move them.
diff --git a/arch/x86/platform/intel-mid/Makefile b/arch/x86/platform/intel-mid/Makefile
index 0ce1b1913673..aebb5b9ea80a 100644
--- a/arch/x86/platform/intel-mid/Makefile
+++ b/arch/x86/platform/intel-mid/Makefile
@@ -1,4 +1,4 @@
1obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o 1obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o pwr.o
2 2
3# SFI specific code 3# SFI specific code
4ifdef CONFIG_X86_INTEL_MID 4ifdef CONFIG_X86_INTEL_MID
diff --git a/arch/x86/platform/intel-mid/pwr.c b/arch/x86/platform/intel-mid/pwr.c
new file mode 100644
index 000000000000..59faf05d23f5
--- /dev/null
+++ b/arch/x86/platform/intel-mid/pwr.c
@@ -0,0 +1,416 @@
1/*
2 * Intel MID Power Management Unit (PWRMU) device driver
3 *
4 * Copyright (C) 2016, Intel Corporation
5 *
6 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * Intel MID Power Management Unit device driver handles the South Complex PCI
13 * devices such as GPDMA, SPI, I2C, PWM, and so on. By default PCI core
14 * modifies bits in PMCSR register in the PCI configuration space. This is not
15 * enough on some SoCs like Intel Tangier. In such case PCI core sets a new
16 * power state of the device in question through a PM hook registered in struct
17 * pci_platform_pm_ops (see drivers/pci/pci-mid.c).
18 */
19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
22#include <linux/delay.h>
23#include <linux/errno.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/mutex.h>
29#include <linux/pci.h>
30
31#include <asm/intel-mid.h>
32
33/* Registers */
34#define PM_STS 0x00
35#define PM_CMD 0x04
36#define PM_ICS 0x08
37#define PM_WKC(x) (0x10 + (x) * 4)
38#define PM_WKS(x) (0x18 + (x) * 4)
39#define PM_SSC(x) (0x20 + (x) * 4)
40#define PM_SSS(x) (0x30 + (x) * 4)
41
42/* Bits in PM_STS */
43#define PM_STS_BUSY (1 << 8)
44
45/* Bits in PM_CMD */
46#define PM_CMD_CMD(x) ((x) << 0)
47#define PM_CMD_IOC (1 << 8)
48#define PM_CMD_D3cold (1 << 21)
49
50/* List of commands */
51#define CMD_SET_CFG 0x01
52
53/* Bits in PM_ICS */
54#define PM_ICS_INT_STATUS(x) ((x) & 0xff)
55#define PM_ICS_IE (1 << 8)
56#define PM_ICS_IP (1 << 9)
57#define PM_ICS_SW_INT_STS (1 << 10)
58
59/* List of interrupts */
60#define INT_INVALID 0
61#define INT_CMD_COMPLETE 1
62#define INT_CMD_ERR 2
63#define INT_WAKE_EVENT 3
64#define INT_LSS_POWER_ERR 4
65#define INT_S0iX_MSG_ERR 5
66#define INT_NO_C6 6
67#define INT_TRIGGER_ERR 7
68#define INT_INACTIVITY 8
69
70/* South Complex devices */
71#define LSS_MAX_SHARED_DEVS 4
72#define LSS_MAX_DEVS 64
73
74#define LSS_WS_BITS 1 /* wake state width */
75#define LSS_PWS_BITS 2 /* power state width */
76
77/* Supported device IDs */
78#define PCI_DEVICE_ID_TANGIER 0x11a1
79
80struct mid_pwr_dev {
81 struct pci_dev *pdev;
82 pci_power_t state;
83};
84
85struct mid_pwr {
86 struct device *dev;
87 void __iomem *regs;
88 int irq;
89 bool available;
90
91 struct mutex lock;
92 struct mid_pwr_dev lss[LSS_MAX_DEVS][LSS_MAX_SHARED_DEVS];
93};
94
95static struct mid_pwr *midpwr;
96
97static u32 mid_pwr_get_state(struct mid_pwr *pwr, int reg)
98{
99 return readl(pwr->regs + PM_SSS(reg));
100}
101
102static void mid_pwr_set_state(struct mid_pwr *pwr, int reg, u32 value)
103{
104 writel(value, pwr->regs + PM_SSC(reg));
105}
106
107static void mid_pwr_set_wake(struct mid_pwr *pwr, int reg, u32 value)
108{
109 writel(value, pwr->regs + PM_WKC(reg));
110}
111
112static void mid_pwr_interrupt_disable(struct mid_pwr *pwr)
113{
114 writel(~PM_ICS_IE, pwr->regs + PM_ICS);
115}
116
117static bool mid_pwr_is_busy(struct mid_pwr *pwr)
118{
119 return !!(readl(pwr->regs + PM_STS) & PM_STS_BUSY);
120}
121
122/* Wait 500ms that the latest PWRMU command finished */
123static int mid_pwr_wait(struct mid_pwr *pwr)
124{
125 unsigned int count = 500000;
126 bool busy;
127
128 do {
129 busy = mid_pwr_is_busy(pwr);
130 if (!busy)
131 return 0;
132 udelay(1);
133 } while (--count);
134
135 return -EBUSY;
136}
137
138static int mid_pwr_wait_for_cmd(struct mid_pwr *pwr, u8 cmd)
139{
140 writel(PM_CMD_CMD(cmd), pwr->regs + PM_CMD);
141 return mid_pwr_wait(pwr);
142}
143
144static int __update_power_state(struct mid_pwr *pwr, int reg, int bit, int new)
145{
146 int curstate;
147 u32 power;
148 int ret;
149
150 /* Check if the device is already in desired state */
151 power = mid_pwr_get_state(pwr, reg);
152 curstate = (power >> bit) & 3;
153 if (curstate == new)
154 return 0;
155
156 /* Update the power state */
157 mid_pwr_set_state(pwr, reg, (power & ~(3 << bit)) | (new << bit));
158
159 /* Send command to SCU */
160 ret = mid_pwr_wait_for_cmd(pwr, CMD_SET_CFG);
161 if (ret)
162 return ret;
163
164 /* Check if the device is already in desired state */
165 power = mid_pwr_get_state(pwr, reg);
166 curstate = (power >> bit) & 3;
167 if (curstate != new)
168 return -EAGAIN;
169
170 return 0;
171}
172
173static pci_power_t __find_weakest_power_state(struct mid_pwr_dev *lss,
174 struct pci_dev *pdev,
175 pci_power_t state)
176{
177 pci_power_t weakest = PCI_D3hot;
178 unsigned int j;
179
180 /* Find device in cache or first free cell */
181 for (j = 0; j < LSS_MAX_SHARED_DEVS; j++) {
182 if (lss[j].pdev == pdev || !lss[j].pdev)
183 break;
184 }
185
186 /* Store the desired state in cache */
187 if (j < LSS_MAX_SHARED_DEVS) {
188 lss[j].pdev = pdev;
189 lss[j].state = state;
190 } else {
191 dev_WARN(&pdev->dev, "No room for device in PWRMU LSS cache\n");
192 weakest = state;
193 }
194
195 /* Find the power state we may use */
196 for (j = 0; j < LSS_MAX_SHARED_DEVS; j++) {
197 if (lss[j].state < weakest)
198 weakest = lss[j].state;
199 }
200
201 return weakest;
202}
203
204static int __set_power_state(struct mid_pwr *pwr, struct pci_dev *pdev,
205 pci_power_t state, int id, int reg, int bit)
206{
207 const char *name;
208 int ret;
209
210 state = __find_weakest_power_state(pwr->lss[id], pdev, state);
211 name = pci_power_name(state);
212
213 ret = __update_power_state(pwr, reg, bit, (__force int)state);
214 if (ret) {
215 dev_warn(&pdev->dev, "Can't set power state %s: %d\n", name, ret);
216 return ret;
217 }
218
219 dev_vdbg(&pdev->dev, "Set power state %s\n", name);
220 return 0;
221}
222
223static int mid_pwr_set_power_state(struct mid_pwr *pwr, struct pci_dev *pdev,
224 pci_power_t state)
225{
226 int id, reg, bit;
227 int ret;
228
229 id = intel_mid_pwr_get_lss_id(pdev);
230 if (id < 0)
231 return id;
232
233 reg = (id * LSS_PWS_BITS) / 32;
234 bit = (id * LSS_PWS_BITS) % 32;
235
236 /* We support states between PCI_D0 and PCI_D3hot */
237 if (state < PCI_D0)
238 state = PCI_D0;
239 if (state > PCI_D3hot)
240 state = PCI_D3hot;
241
242 mutex_lock(&pwr->lock);
243 ret = __set_power_state(pwr, pdev, state, id, reg, bit);
244 mutex_unlock(&pwr->lock);
245 return ret;
246}
247
248int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
249{
250 struct mid_pwr *pwr = midpwr;
251 int ret = 0;
252
253 might_sleep();
254
255 if (pwr && pwr->available)
256 ret = mid_pwr_set_power_state(pwr, pdev, state);
257 dev_vdbg(&pdev->dev, "set_power_state() returns %d\n", ret);
258
259 return 0;
260}
261EXPORT_SYMBOL_GPL(intel_mid_pci_set_power_state);
262
263int intel_mid_pwr_get_lss_id(struct pci_dev *pdev)
264{
265 int vndr;
266 u8 id;
267
268 /*
269 * Mapping to PWRMU index is kept in the Logical SubSystem ID byte of
270 * Vendor capability.
271 */
272 vndr = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
273 if (!vndr)
274 return -EINVAL;
275
276 /* Read the Logical SubSystem ID byte */
277 pci_read_config_byte(pdev, vndr + INTEL_MID_PWR_LSS_OFFSET, &id);
278 if (!(id & INTEL_MID_PWR_LSS_TYPE))
279 return -ENODEV;
280
281 id &= ~INTEL_MID_PWR_LSS_TYPE;
282 if (id >= LSS_MAX_DEVS)
283 return -ERANGE;
284
285 return id;
286}
287
288static irqreturn_t mid_pwr_irq_handler(int irq, void *dev_id)
289{
290 struct mid_pwr *pwr = dev_id;
291 u32 ics;
292
293 ics = readl(pwr->regs + PM_ICS);
294 if (!(ics & PM_ICS_IP))
295 return IRQ_NONE;
296
297 writel(ics | PM_ICS_IP, pwr->regs + PM_ICS);
298
299 dev_warn(pwr->dev, "Unexpected IRQ: %#x\n", PM_ICS_INT_STATUS(ics));
300 return IRQ_HANDLED;
301}
302
303struct mid_pwr_device_info {
304 int (*set_initial_state)(struct mid_pwr *pwr);
305};
306
307static int mid_pwr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
308{
309 struct mid_pwr_device_info *info = (void *)id->driver_data;
310 struct device *dev = &pdev->dev;
311 struct mid_pwr *pwr;
312 int ret;
313
314 ret = pcim_enable_device(pdev);
315 if (ret < 0) {
316 dev_err(&pdev->dev, "error: could not enable device\n");
317 return ret;
318 }
319
320 ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
321 if (ret) {
322 dev_err(&pdev->dev, "I/O memory remapping failed\n");
323 return ret;
324 }
325
326 pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL);
327 if (!pwr)
328 return -ENOMEM;
329
330 pwr->dev = dev;
331 pwr->regs = pcim_iomap_table(pdev)[0];
332 pwr->irq = pdev->irq;
333
334 mutex_init(&pwr->lock);
335
336 /* Disable interrupts */
337 mid_pwr_interrupt_disable(pwr);
338
339 if (info && info->set_initial_state) {
340 ret = info->set_initial_state(pwr);
341 if (ret)
342 dev_warn(dev, "Can't set initial state: %d\n", ret);
343 }
344
345 ret = devm_request_irq(dev, pdev->irq, mid_pwr_irq_handler,
346 IRQF_NO_SUSPEND, pci_name(pdev), pwr);
347 if (ret)
348 return ret;
349
350 pwr->available = true;
351 midpwr = pwr;
352
353 pci_set_drvdata(pdev, pwr);
354 return 0;
355}
356
357static int tng_set_initial_state(struct mid_pwr *pwr)
358{
359 unsigned int i, j;
360 int ret;
361
362 /*
363 * Enable wake events.
364 *
365 * PWRMU supports up to 32 sources for wake up the system. Ungate them
366 * all here.
367 */
368 mid_pwr_set_wake(pwr, 0, 0xffffffff);
369 mid_pwr_set_wake(pwr, 1, 0xffffffff);
370
371 /*
372 * Power off South Complex devices.
373 *
374 * There is a map (see a note below) of 64 devices with 2 bits per each
375 * on 32-bit HW registers. The following calls set all devices to one
376 * known initial state, i.e. PCI_D3hot. This is done in conjunction
377 * with PMCSR setting in arch/x86/pci/intel_mid_pci.c.
378 *
379 * NOTE: The actual device mapping is provided by a platform at run
380 * time using vendor capability of PCI configuration space.
381 */
382 mid_pwr_set_state(pwr, 0, 0xffffffff);
383 mid_pwr_set_state(pwr, 1, 0xffffffff);
384 mid_pwr_set_state(pwr, 2, 0xffffffff);
385 mid_pwr_set_state(pwr, 3, 0xffffffff);
386
387 /* Send command to SCU */
388 ret = mid_pwr_wait_for_cmd(pwr, CMD_SET_CFG);
389 if (ret)
390 return ret;
391
392 for (i = 0; i < LSS_MAX_DEVS; i++) {
393 for (j = 0; j < LSS_MAX_SHARED_DEVS; j++)
394 pwr->lss[i][j].state = PCI_D3hot;
395 }
396
397 return 0;
398}
399
400static const struct mid_pwr_device_info tng_info = {
401 .set_initial_state = tng_set_initial_state,
402};
403
404static const struct pci_device_id mid_pwr_pci_ids[] = {
405 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER), (kernel_ulong_t)&tng_info },
406 {}
407};
408MODULE_DEVICE_TABLE(pci, mid_pwr_pci_ids);
409
410static struct pci_driver mid_pwr_pci_driver = {
411 .name = "intel_mid_pwr",
412 .probe = mid_pwr_probe,
413 .id_table = mid_pwr_pci_ids,
414};
415
416builtin_pci_driver(mid_pwr_pci_driver);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 1fa6925733d3..8db5079f09a7 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -51,6 +51,9 @@ obj-$(CONFIG_ACPI) += pci-acpi.o
51# SMBIOS provided firmware instance and labels 51# SMBIOS provided firmware instance and labels
52obj-$(CONFIG_PCI_LABEL) += pci-label.o 52obj-$(CONFIG_PCI_LABEL) += pci-label.o
53 53
54# Intel MID platform PM support
55obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o
56
54obj-$(CONFIG_PCI_SYSCALL) += syscall.o 57obj-$(CONFIG_PCI_SYSCALL) += syscall.o
55 58
56obj-$(CONFIG_PCI_STUB) += pci-stub.o 59obj-$(CONFIG_PCI_STUB) += pci-stub.o
diff --git a/drivers/pci/pci-mid.c b/drivers/pci/pci-mid.c
new file mode 100644
index 000000000000..c878aa71173b
--- /dev/null
+++ b/drivers/pci/pci-mid.c
@@ -0,0 +1,77 @@
1/*
2 * Intel MID platform PM support
3 *
4 * Copyright (C) 2016, Intel Corporation
5 *
6 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/pci.h>
15
16#include <asm/cpu_device_id.h>
17#include <asm/intel-family.h>
18#include <asm/intel-mid.h>
19
20#include "pci.h"
21
22static bool mid_pci_power_manageable(struct pci_dev *dev)
23{
24 return true;
25}
26
27static int mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
28{
29 return intel_mid_pci_set_power_state(pdev, state);
30}
31
32static pci_power_t mid_pci_choose_state(struct pci_dev *pdev)
33{
34 return PCI_D3hot;
35}
36
37static int mid_pci_sleep_wake(struct pci_dev *dev, bool enable)
38{
39 return 0;
40}
41
42static int mid_pci_run_wake(struct pci_dev *dev, bool enable)
43{
44 return 0;
45}
46
47static bool mid_pci_need_resume(struct pci_dev *dev)
48{
49 return false;
50}
51
52static struct pci_platform_pm_ops mid_pci_platform_pm = {
53 .is_manageable = mid_pci_power_manageable,
54 .set_state = mid_pci_set_power_state,
55 .choose_state = mid_pci_choose_state,
56 .sleep_wake = mid_pci_sleep_wake,
57 .run_wake = mid_pci_run_wake,
58 .need_resume = mid_pci_need_resume,
59};
60
61#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
62
63static const struct x86_cpu_id lpss_cpu_ids[] = {
64 ICPU(INTEL_FAM6_ATOM_MERRIFIELD1),
65 {}
66};
67
68static int __init mid_pci_init(void)
69{
70 const struct x86_cpu_id *id;
71
72 id = x86_match_cpu(lpss_cpu_ids);
73 if (id)
74 pci_set_platform_pm(&mid_pci_platform_pm);
75 return 0;
76}
77arch_initcall(mid_pci_init);