1 | /* |
2 | * Intel Merrifield power button support |
3 | * |
4 | * (C) Copyright 2017 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 |
9 | * modify it under the terms of the GNU General Public License |
10 | * as published by the Free Software Foundation; version 2 |
11 | * of the License. |
12 | */ |
13 | |
14 | #include <linux/init.h> |
15 | #include <linux/ioport.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/sfi.h> |
18 | |
19 | #include <asm/intel-mid.h> |
20 | #include <asm/intel_scu_ipc.h> |
21 | |
22 | static struct resource mrfld_power_btn_resources[] = { |
23 | { |
24 | .flags = IORESOURCE_IRQ, |
25 | }, |
26 | }; |
27 | |
28 | static struct platform_device mrfld_power_btn_dev = { |
29 | .name = "msic_power_btn" , |
30 | .id = PLATFORM_DEVID_NONE, |
31 | .num_resources = ARRAY_SIZE(mrfld_power_btn_resources), |
32 | .resource = mrfld_power_btn_resources, |
33 | }; |
34 | |
35 | static int mrfld_power_btn_scu_status_change(struct notifier_block *nb, |
36 | unsigned long code, void *data) |
37 | { |
38 | if (code == SCU_DOWN) { |
39 | platform_device_unregister(&mrfld_power_btn_dev); |
40 | return 0; |
41 | } |
42 | |
43 | return platform_device_register(&mrfld_power_btn_dev); |
44 | } |
45 | |
46 | static struct notifier_block mrfld_power_btn_scu_notifier = { |
47 | .notifier_call = mrfld_power_btn_scu_status_change, |
48 | }; |
49 | |
50 | static int __init register_mrfld_power_btn(void) |
51 | { |
52 | if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER) |
53 | return -ENODEV; |
54 | |
55 | /* |
56 | * We need to be sure that the SCU IPC is ready before |
57 | * PMIC power button device can be registered: |
58 | */ |
59 | intel_scu_notifier_add(&mrfld_power_btn_scu_notifier); |
60 | |
61 | return 0; |
62 | } |
63 | arch_initcall(register_mrfld_power_btn); |
64 | |
65 | static void __init *mrfld_power_btn_platform_data(void *info) |
66 | { |
67 | struct resource *res = mrfld_power_btn_resources; |
68 | struct sfi_device_table_entry *pentry = info; |
69 | |
70 | res->start = res->end = pentry->irq; |
71 | return NULL; |
72 | } |
73 | |
74 | static const struct devs_id mrfld_power_btn_dev_id __initconst = { |
75 | .name = "bcove_power_btn" , |
76 | .type = SFI_DEV_TYPE_IPC, |
77 | .delay = 1, |
78 | .msic = 1, |
79 | .get_platform_data = &mrfld_power_btn_platform_data, |
80 | }; |
81 | |
82 | sfi_device(mrfld_power_btn_dev_id); |
83 | |