diff options
| -rw-r--r-- | arch/x86/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/acpi/Makefile | 2 | ||||
| -rw-r--r-- | drivers/acpi/acpi_apd.c | 150 | ||||
| -rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 1 |
5 files changed, 165 insertions, 1 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0dc9d0144a27..3e15cee34aee 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -496,6 +496,17 @@ config X86_INTEL_LPSS | |||
| 496 | things like clock tree (common clock framework) and pincontrol | 496 | things like clock tree (common clock framework) and pincontrol |
| 497 | which are needed by the LPSS peripheral drivers. | 497 | which are needed by the LPSS peripheral drivers. |
| 498 | 498 | ||
| 499 | config X86_AMD_PLATFORM_DEVICE | ||
| 500 | bool "AMD ACPI2Platform devices support" | ||
| 501 | depends on ACPI | ||
| 502 | select COMMON_CLK | ||
| 503 | select PINCTRL | ||
| 504 | ---help--- | ||
| 505 | Select to interpret AMD specific ACPI device to platform device | ||
| 506 | such as I2C, UART, GPIO found on AMD Carrizo and later chipsets. | ||
| 507 | I2C and UART depend on COMMON_CLK to set clock. GPIO driver is | ||
| 508 | implemented under PINCTRL subsystem. | ||
| 509 | |||
| 499 | config IOSF_MBI | 510 | config IOSF_MBI |
| 500 | tristate "Intel SoC IOSF Sideband support for SoC platforms" | 511 | tristate "Intel SoC IOSF Sideband support for SoC platforms" |
| 501 | depends on PCI | 512 | depends on PCI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index f74317cc1ca9..0071141b6bbc 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
| @@ -40,7 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o | |||
| 40 | acpi-y += ec.o | 40 | acpi-y += ec.o |
| 41 | acpi-$(CONFIG_ACPI_DOCK) += dock.o | 41 | acpi-$(CONFIG_ACPI_DOCK) += dock.o |
| 42 | acpi-y += pci_root.o pci_link.o pci_irq.o | 42 | acpi-y += pci_root.o pci_link.o pci_irq.o |
| 43 | acpi-y += acpi_lpss.o | 43 | acpi-y += acpi_lpss.o acpi_apd.o |
| 44 | acpi-y += acpi_platform.o | 44 | acpi-y += acpi_platform.o |
| 45 | acpi-y += acpi_pnp.o | 45 | acpi-y += acpi_pnp.o |
| 46 | acpi-y += int340x_thermal.o | 46 | acpi-y += int340x_thermal.o |
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c new file mode 100644 index 000000000000..3984ea96e5f7 --- /dev/null +++ b/drivers/acpi/acpi_apd.c | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * AMD ACPI support for ACPI2platform device. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2014,2015 AMD Corporation. | ||
| 5 | * Authors: Ken Xue <Ken.Xue@amd.com> | ||
| 6 | * Wu, Jeff <Jeff.Wu@amd.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/clk-provider.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/pm_domain.h> | ||
| 16 | #include <linux/clkdev.h> | ||
| 17 | #include <linux/acpi.h> | ||
| 18 | #include <linux/err.h> | ||
| 19 | #include <linux/clk.h> | ||
| 20 | #include <linux/pm.h> | ||
| 21 | |||
| 22 | #include "internal.h" | ||
| 23 | |||
| 24 | ACPI_MODULE_NAME("acpi_apd"); | ||
| 25 | struct apd_private_data; | ||
| 26 | |||
| 27 | /** | ||
| 28 | * ACPI_APD_SYSFS : add device attributes in sysfs | ||
| 29 | * ACPI_APD_PM : attach power domain to device | ||
| 30 | */ | ||
| 31 | #define ACPI_APD_SYSFS BIT(0) | ||
| 32 | #define ACPI_APD_PM BIT(1) | ||
| 33 | |||
| 34 | /** | ||
| 35 | * struct apd_device_desc - a descriptor for apd device | ||
| 36 | * @flags: device flags like %ACPI_APD_SYSFS, %ACPI_APD_PM | ||
| 37 | * @fixed_clk_rate: fixed rate input clock source for acpi device; | ||
| 38 | * 0 means no fixed rate input clock source | ||
| 39 | * @setup: a hook routine to set device resource during create platform device | ||
| 40 | * | ||
| 41 | * Device description defined as acpi_device_id.driver_data | ||
| 42 | */ | ||
| 43 | struct apd_device_desc { | ||
| 44 | unsigned int flags; | ||
| 45 | unsigned int fixed_clk_rate; | ||
| 46 | int (*setup)(struct apd_private_data *pdata); | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct apd_private_data { | ||
| 50 | struct clk *clk; | ||
| 51 | struct acpi_device *adev; | ||
| 52 | const struct apd_device_desc *dev_desc; | ||
| 53 | }; | ||
| 54 | |||
| 55 | #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE | ||
| 56 | #define APD_ADDR(desc) ((unsigned long)&desc) | ||
| 57 | |||
| 58 | static int acpi_apd_setup(struct apd_private_data *pdata) | ||
| 59 | { | ||
| 60 | const struct apd_device_desc *dev_desc = pdata->dev_desc; | ||
| 61 | struct clk *clk = ERR_PTR(-ENODEV); | ||
| 62 | |||
| 63 | if (dev_desc->fixed_clk_rate) { | ||
| 64 | clk = clk_register_fixed_rate(&pdata->adev->dev, | ||
| 65 | dev_name(&pdata->adev->dev), | ||
| 66 | NULL, CLK_IS_ROOT, | ||
| 67 | dev_desc->fixed_clk_rate); | ||
| 68 | clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev)); | ||
| 69 | pdata->clk = clk; | ||
| 70 | } | ||
| 71 | |||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | static struct apd_device_desc cz_i2c_desc = { | ||
| 76 | .setup = acpi_apd_setup, | ||
| 77 | .fixed_clk_rate = 133000000, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static struct apd_device_desc cz_uart_desc = { | ||
| 81 | .setup = acpi_apd_setup, | ||
| 82 | .fixed_clk_rate = 48000000, | ||
| 83 | }; | ||
| 84 | |||
| 85 | #else | ||
| 86 | |||
| 87 | #define APD_ADDR(desc) (0UL) | ||
| 88 | |||
| 89 | #endif /* CONFIG_X86_AMD_PLATFORM_DEVICE */ | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Create platform device during acpi scan attach handle. | ||
| 93 | * Return value > 0 on success of creating device. | ||
| 94 | */ | ||
| 95 | static int acpi_apd_create_device(struct acpi_device *adev, | ||
| 96 | const struct acpi_device_id *id) | ||
| 97 | { | ||
| 98 | const struct apd_device_desc *dev_desc = (void *)id->driver_data; | ||
| 99 | struct apd_private_data *pdata; | ||
| 100 | struct platform_device *pdev; | ||
| 101 | int ret; | ||
| 102 | |||
| 103 | if (!dev_desc) { | ||
| 104 | pdev = acpi_create_platform_device(adev); | ||
| 105 | return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
| 109 | if (!pdata) | ||
| 110 | return -ENOMEM; | ||
| 111 | |||
| 112 | pdata->adev = adev; | ||
| 113 | pdata->dev_desc = dev_desc; | ||
| 114 | |||
| 115 | if (dev_desc->setup) { | ||
| 116 | ret = dev_desc->setup(pdata); | ||
| 117 | if (ret) | ||
| 118 | goto err_out; | ||
| 119 | } | ||
| 120 | |||
| 121 | adev->driver_data = pdata; | ||
| 122 | pdev = acpi_create_platform_device(adev); | ||
| 123 | if (!IS_ERR_OR_NULL(pdev)) | ||
| 124 | return 1; | ||
| 125 | |||
| 126 | ret = PTR_ERR(pdev); | ||
| 127 | adev->driver_data = NULL; | ||
| 128 | |||
| 129 | err_out: | ||
| 130 | kfree(pdata); | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static const struct acpi_device_id acpi_apd_device_ids[] = { | ||
| 135 | /* Generic apd devices */ | ||
| 136 | { "AMD0010", APD_ADDR(cz_i2c_desc) }, | ||
| 137 | { "AMD0020", APD_ADDR(cz_uart_desc) }, | ||
| 138 | { "AMD0030", }, | ||
| 139 | { } | ||
| 140 | }; | ||
| 141 | |||
| 142 | static struct acpi_scan_handler apd_handler = { | ||
| 143 | .ids = acpi_apd_device_ids, | ||
| 144 | .attach = acpi_apd_create_device, | ||
| 145 | }; | ||
| 146 | |||
| 147 | void __init acpi_apd_init(void) | ||
| 148 | { | ||
| 149 | acpi_scan_add_handler(&apd_handler); | ||
| 150 | } | ||
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 163e82f536fa..c24ae9d7fdcb 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
| @@ -68,6 +68,8 @@ static inline void acpi_debugfs_init(void) { return; } | |||
| 68 | #endif | 68 | #endif |
| 69 | void acpi_lpss_init(void); | 69 | void acpi_lpss_init(void); |
| 70 | 70 | ||
| 71 | void acpi_apd_init(void); | ||
| 72 | |||
| 71 | acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src); | 73 | acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src); |
| 72 | bool acpi_queue_hotplug_work(struct work_struct *work); | 74 | bool acpi_queue_hotplug_work(struct work_struct *work); |
| 73 | void acpi_device_hotplug(struct acpi_device *adev, u32 src); | 75 | void acpi_device_hotplug(struct acpi_device *adev, u32 src); |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index dc4d8960684a..bbca7830e18a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -2544,6 +2544,7 @@ int __init acpi_scan_init(void) | |||
| 2544 | acpi_pci_link_init(); | 2544 | acpi_pci_link_init(); |
| 2545 | acpi_processor_init(); | 2545 | acpi_processor_init(); |
| 2546 | acpi_lpss_init(); | 2546 | acpi_lpss_init(); |
| 2547 | acpi_apd_init(); | ||
| 2547 | acpi_cmos_rtc_init(); | 2548 | acpi_cmos_rtc_init(); |
| 2548 | acpi_container_init(); | 2549 | acpi_container_init(); |
| 2549 | acpi_memory_hotplug_init(); | 2550 | acpi_memory_hotplug_init(); |
