diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ded8a67..6402c79f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -495,6 +495,17 @@ config X86_INTEL_LPSS
 	  things like clock tree (common clock framework) and pincontrol
 	  which are needed by the LPSS peripheral drivers.
 
+config X86_AMD_PLATFORM_DEVICE
+	bool "AMD ACPI2Platform devices support"
+	depends on ACPI
+	select COMMON_CLK
+	select PINCTRL
+	---help---
+	  Select to interpret AMD specific ACPI device to platform device
+	  such as I2C, UART found on AMD CARRIZO and later chipset. Selecting
+	  this option enables things like clock tree (common clock framework)
+	  and pinctrl.
+
 config IOSF_MBI
 	tristate "Intel SoC IOSF Sideband support for SoC platforms"
 	depends on PCI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c3b2fcb..91fc1c2 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -41,6 +41,7 @@ acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o
 acpi-y				+= acpi_lpss.o
+acpi-$(CONFIG_X86_AMD_PLATFORM_DEVICE)	+= acpi_apd.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= acpi_pnp.o
 acpi-y				+= int340x_thermal.o
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c new file mode 100644 index 0000000..994b7db
--- /dev/null
+++ b/drivers/acpi/acpi_apd.c
@@ -0,0 +1,245 @@
+/*
+ * AMD ACPI support for ACPI2platform device.
+ *
+ * Copyright (c) 2014, AMD Corporation.
+ * Authors: Ken Xue <Ken.Xue@amd.com>
+ *	Jeff Wu <Jeff.Wu@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include "internal.h"
+
+ACPI_MODULE_NAME("acpi_apd");
+struct apd_private_data;
+
+struct apd_device_desc {
+	bool clk_required;
+	bool fixed_root_clock;
+	const char *clk_name;
+	unsigned long	rate;
+	size_t prv_size_override;
+	void (*setup)(struct apd_private_data *pdata); };
+
+struct apd_private_data {
+	void __iomem *mmio_base;
+	resource_size_t mmio_size;
+	struct clk *clk;
+	const struct apd_device_desc *dev_desc; };
+
+static struct apd_device_desc amd_i2c_desc = {
+	.clk_required = true,
+	.fixed_root_clock = true,
+	.clk_name = "i2c_clk",
+	.rate = 133000000, /*(133 * 1000 * 1000)*/ };
+
+static struct apd_device_desc amd_uart_desc = {
+	.clk_required = true,
+	.fixed_root_clock = true,
+	.clk_name = "uart_clk",
+	.rate = 48000000,
+};
+
+static const struct acpi_device_id acpi_apd_device_ids[] = {
+	/* Generic apd devices */
+	{ "AMD0010", (unsigned long)&amd_i2c_desc },
+	{ "AMD0020", (unsigned long)&amd_uart_desc },
+	{ }
+};
+
+static int is_memory(struct acpi_resource *res, void *not_used) {
+	struct resource r;
+
+	return !acpi_dev_resource_memory(res, &r); }
+
+static int register_device_clock(struct acpi_device *adev,
+				 struct apd_private_data *pdata)
+{
+	const struct apd_device_desc *dev_desc = pdata->dev_desc;
+	struct clk *clk = ERR_PTR(-ENODEV);
+
+	clk = pdata->clk;
+	if (!clk && dev_desc->fixed_root_clock) {
+		clk = clk_register_fixed_rate(&adev->dev, dev_name(&adev->dev),
+				      NULL, CLK_IS_ROOT, dev_desc->rate);
+		pdata->clk = clk;
+		clk_register_clkdev(clk, NULL, dev_name(&adev->dev));
+	}
+
+	return 0;
+}
+
+static int acpi_apd_create_device(struct acpi_device *adev,
+				   const struct acpi_device_id *id) {
+	struct apd_device_desc *dev_desc;
+	struct apd_private_data *pdata;
+	struct resource_list_entry *rentry;
+	struct list_head resource_list;
+	struct platform_device *pdev;
+	int ret;
+
+	dev_desc = (struct apd_device_desc *)id->driver_data;
+	if (!dev_desc) {
+		pdev = acpi_create_platform_device(adev);
+		return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1;
+	}
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
+	if (ret < 0)
+		goto err_out;
+
+	list_for_each_entry(rentry, &resource_list, node)
+		if (resource_type(&rentry->res) == IORESOURCE_MEM) {
+			if (dev_desc->prv_size_override)
+				pdata->mmio_size = dev_desc->prv_size_override;
+			else
+				pdata->mmio_size = resource_size(&rentry->res);
+			pdata->mmio_base = ioremap(rentry->res.start,
+						   pdata->mmio_size);
+			break;
+		}
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	pdata->dev_desc = dev_desc;
+
+	if (dev_desc->clk_required) {
+		ret = register_device_clock(adev, pdata);
+		if (ret) {
+			/* Skip the device, but continue the namespace scan. */
+			ret = 0;
+			goto err_out;
+		}
+	}
+
+	/*
+	 * This works around a known issue in ACPI tables where apd devices
+	 * have _PS0 and _PS3 without _PSC (and no power resources), so
+	 * acpi_bus_init_power() will assume that the BIOS has put them into D0.
+	 */
+	ret = acpi_device_fix_up_power(adev);
+	if (ret) {
+		/* Skip the device, but continue the namespace scan. */
+		ret = 0;
+		goto err_out;
+	}
+
+	if (dev_desc->setup)
+		dev_desc->setup(pdata);
+
+	adev->driver_data = pdata;
+	pdev = acpi_create_platform_device(adev);
+	if (!IS_ERR_OR_NULL(pdev)) {
+		device_enable_async_suspend(&pdev->dev);
+		return ret;
+	}
+
+	ret = PTR_ERR(pdev);
+	adev->driver_data = NULL;
+
+ err_out:
+	kfree(pdata);
+	return ret;
+}
+
+static ssize_t apd_device_desc_show(struct device *dev,
+				struct device_attribute *attr, char *buf) {
+	int ret;
+	struct acpi_device *adev;
+	struct apd_private_data *pdata;
+
+	ret = acpi_bus_get_device(ACPI_HANDLE(dev), &adev);
+	if (WARN_ON(ret))
+		return ret;
+
+	pdata = acpi_driver_data(adev);
+	if (WARN_ON(!pdata || !pdata->dev_desc))
+		return -ENODEV;
+
+	if (pdata->dev_desc->clk_required)
+		return sprintf(buf, "Required clk: %s %s %ld\n",
+			pdata->dev_desc->clk_name,
+			pdata->dev_desc->fixed_root_clock ?
+			"fix rate" : "no fix rate",
+			pdata->dev_desc->rate);
+	else
+		return sprintf(buf, "No need clk\n"); }
+
+static DEVICE_ATTR(device_desc, S_IRUSR, apd_device_desc_show, NULL);
+
+static struct attribute *apd_attrs[] = {
+	&dev_attr_device_desc.attr,
+	NULL,
+};
+
+static struct attribute_group apd_attr_group = {
+	.attrs = apd_attrs,
+	.name = "apd_ltr",
+};
+
+static int acpi_apd_platform_notify(struct notifier_block *nb,
+				     unsigned long action, void *data) {
+	struct platform_device *pdev = to_platform_device(data);
+	struct apd_private_data *pdata;
+	struct acpi_device *adev;
+	const struct acpi_device_id *id;
+	int ret = 0;
+
+	id = acpi_match_device(acpi_apd_device_ids, &pdev->dev);
+	if (!id || !id->driver_data)
+		return 0;
+
+	if (acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
+		return 0;
+
+	pdata = acpi_driver_data(adev);
+	if (!pdata || !pdata->mmio_base)
+		return 0;
+
+	if (action == BUS_NOTIFY_ADD_DEVICE)
+		ret = sysfs_create_group(&pdev->dev.kobj, &apd_attr_group);
+	else if (action == BUS_NOTIFY_DEL_DEVICE)
+		sysfs_remove_group(&pdev->dev.kobj, &apd_attr_group);
+
+	return ret;
+}
+
+static struct notifier_block acpi_apd_nb = {
+	.notifier_call = acpi_apd_platform_notify, };
+
+static struct acpi_scan_handler apd_handler = {
+	.ids = acpi_apd_device_ids,
+	.attach = acpi_apd_create_device,
+};
+
+void __init acpi_apd_init(void)
+{
+	bus_register_notifier(&platform_bus_type, &acpi_apd_nb);
+	acpi_scan_add_handler(&apd_handler);
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 447f6d6..c8a0e8e 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -68,6 +68,12 @@ static inline void acpi_debugfs_init(void) { return; }  #endif  void acpi_lpss_init(void);
 
+#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
+void acpi_apd_init(void);
+#else
+static inline void acpi_apd_init(void) {} #endif
+
 acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src);  bool acpi_queue_hotplug_work(struct work_struct *work);  void acpi_device_hotplug(struct acpi_device *adev, u32 src); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0476e90..24fef2b 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2349,6 +2349,7 @@ int __init acpi_scan_init(void)
 	acpi_pci_link_init();
 	acpi_processor_init();
 	acpi_lpss_init();
+	acpi_apd_init();
 	acpi_cmos_rtc_init();
 	acpi_container_init();
 	acpi_memory_hotplug_init();
