diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c46ca31..8c3cc9e 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -120,6 +120,8 @@ config DRM_RADEON
 
 source "drivers/gpu/drm/radeon/Kconfig"
 
+source "drivers/gpu/drm/amd/bus/Kconfig"
+
 config DRM_AMDGPU
 	tristate "AMD GPU"
 	depends on DRM && PCI
@@ -134,6 +136,7 @@ config DRM_AMDGPU
 	select HWMON
 	select BACKLIGHT_CLASS_DEVICE
 	select INTERVAL_TREE
+	select DRM_AMD_GNB_BUS
 	help
 	  Choose this option if you have a recent AMD Radeon graphics card.
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 5713d05..5380477 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_DRM_TDFX)	+= tdfx/
 obj-$(CONFIG_DRM_R128)	+= r128/
 obj-$(CONFIG_HSA_AMD) += amd/amdkfd/
 obj-$(CONFIG_DRM_RADEON)+= radeon/
+obj-$(CONFIG_DRM_AMD_GNB_BUS)   += amd/bus/
 obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
 obj-$(CONFIG_DRM_MGA)	+= mga/
 obj-$(CONFIG_DRM_I810)	+= i810/
diff --git a/drivers/gpu/drm/amd/bus/Kconfig b/drivers/gpu/drm/amd/bus/Kconfig
new file mode 100644
index 0000000..f101dd8
--- /dev/null
+++ b/drivers/gpu/drm/amd/bus/Kconfig
@@ -0,0 +1,7 @@
+menu "AMD GNB BUS"
+	visible if 0
+
+config DRM_AMD_GNB_BUS
+	tristate "AMD GNB bus - used for GNB IPs such as ACP and ISP"
+
+endmenu
diff --git a/drivers/gpu/drm/amd/bus/Makefile b/drivers/gpu/drm/amd/bus/Makefile
new file mode 100644
index 0000000..c41ffc9
--- /dev/null
+++ b/drivers/gpu/drm/amd/bus/Makefile
@@ -0,0 +1,4 @@
+#
+ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/amd/include/bus/
+
+obj-$(CONFIG_DRM_AMD_GNB_BUS) := amd_gnb_bus.o
diff --git a/drivers/gpu/drm/amd/bus/amd_gnb_bus.c b/drivers/gpu/drm/amd/bus/amd_gnb_bus.c
new file mode 100644
index 0000000..071b16c
--- /dev/null
+++ b/drivers/gpu/drm/amd/bus/amd_gnb_bus.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+#include "amd_gnb_bus.h"
+
+#define to_amd_gnb_bus_device(x) container_of((x), struct amd_gnb_bus_dev, dev)
+#define to_amd_gnb_bus_driver(drv) (container_of((drv),			\
+						struct amd_gnb_bus_driver, \
+						driver))
+
+static int amd_gnb_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct amd_gnb_bus_dev *amd_gnb_bus_dev = to_amd_gnb_bus_device(dev);
+	struct amd_gnb_bus_driver *amd_gnb_bus_driver =
+		to_amd_gnb_bus_driver(drv);
+
+	return amd_gnb_bus_dev->ip == amd_gnb_bus_driver->ip ? 1 : 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int amd_gnb_bus_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct amd_gnb_bus_dev *amd_gnb_bus_dev = to_amd_gnb_bus_device(dev);
+	struct amd_gnb_bus_driver *driver;
+
+	if (!amd_gnb_bus_dev || !dev->driver)
+		return 0;
+	driver = to_amd_gnb_bus_driver(dev->driver);
+	if (!driver->suspend)
+		return 0;
+	return driver->suspend(amd_gnb_bus_dev, mesg);
+}
+
+static int amd_gnb_bus_legacy_resume(struct device *dev)
+{
+	struct amd_gnb_bus_dev *amd_gnb_bus_dev = to_amd_gnb_bus_device(dev);
+	struct amd_gnb_bus_driver *driver;
+
+	if (!amd_gnb_bus_dev || !dev->driver)
+		return 0;
+	driver = to_amd_gnb_bus_driver(dev->driver);
+	if (!driver->resume)
+		return 0;
+	return driver->resume(amd_gnb_bus_dev);
+}
+
+static int amd_gnb_bus_device_pm_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_suspend(dev);
+	else
+		return amd_gnb_bus_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int amd_gnb_bus_device_pm_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_resume(dev);
+	else
+		return amd_gnb_bus_legacy_resume(dev);
+}
+
+static int amd_gnb_bus_device_pm_freeze(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_freeze(dev);
+	else
+		return amd_gnb_bus_legacy_suspend(dev, PMSG_FREEZE);
+}
+
+static int amd_gnb_bus_device_pm_thaw(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_thaw(dev);
+	else
+		return amd_gnb_bus_legacy_resume(dev);
+}
+
+static int amd_gnb_bus_device_pm_poweroff(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_poweroff(dev);
+	else
+		return amd_gnb_bus_legacy_suspend(dev, PMSG_HIBERNATE);
+}
+
+static int amd_gnb_bus_device_pm_restore(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_restore(dev);
+	else
+		return amd_gnb_bus_legacy_resume(dev);
+}
+#else /* !CONFIG_PM_SLEEP */
+#define amd_gnb_bus_device_pm_suspend	NULL
+#define amd_gnb_bus_device_pm_resume	NULL
+#define amd_gnb_bus_device_pm_freeze	NULL
+#define amd_gnb_bus_device_pm_thaw	NULL
+#define amd_gnb_bus_device_pm_poweroff	NULL
+#define amd_gnb_bus_device_pm_restore	NULL
+#endif /* !CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops amd_gnb_bus_device_pm_ops = {
+	.suspend = amd_gnb_bus_device_pm_suspend,
+	.resume = amd_gnb_bus_device_pm_resume,
+	.freeze = amd_gnb_bus_device_pm_freeze,
+	.thaw = amd_gnb_bus_device_pm_thaw,
+	.poweroff = amd_gnb_bus_device_pm_poweroff,
+	.restore = amd_gnb_bus_device_pm_restore,
+	SET_RUNTIME_PM_OPS(
+		pm_generic_runtime_suspend,
+		pm_generic_runtime_resume,
+		pm_runtime_idle
+	)
+};
+
+/* The bus should only be registered by the first amd_gnb, but further
+ * socs can add devices to the bus. */
+struct bus_type amd_gnb_bus_type = {
+	.name  = "amd_gnb",
+	.match = amd_gnb_bus_match,
+	.pm    = &amd_gnb_bus_device_pm_ops,
+};
+EXPORT_SYMBOL(amd_gnb_bus_type);
+
+static int amd_gnb_bus_drv_probe(struct device *_dev)
+{
+	struct amd_gnb_bus_driver *drv = to_amd_gnb_bus_driver(_dev->driver);
+	struct amd_gnb_bus_dev *dev = to_amd_gnb_bus_device(_dev);
+
+	return drv->probe(dev);
+}
+
+static int amd_gnb_bus_drv_remove(struct device *_dev)
+{
+	struct amd_gnb_bus_driver *drv = to_amd_gnb_bus_driver(_dev->driver);
+	struct amd_gnb_bus_dev *dev = to_amd_gnb_bus_device(_dev);
+
+	return drv->remove(dev);
+}
+
+static void amd_gnb_bus_drv_shutdown(struct device *_dev)
+{
+	struct amd_gnb_bus_driver *drv = to_amd_gnb_bus_driver(_dev->driver);
+	struct amd_gnb_bus_dev *dev = to_amd_gnb_bus_device(_dev);
+
+	drv->shutdown(dev);
+}
+
+int amd_gnb_bus_register_driver(struct amd_gnb_bus_driver *drv,
+			       struct module *owner,
+			       const char *mod_name)
+{
+	/* initialize common driver fields */
+	drv->driver.name = drv->name;
+	drv->driver.bus = &amd_gnb_bus_type;
+	drv->driver.owner = owner;
+	drv->driver.mod_name = mod_name;
+
+	if (drv->probe)
+		drv->driver.probe = amd_gnb_bus_drv_probe;
+	if (drv->remove)
+		drv->driver.remove = amd_gnb_bus_drv_remove;
+	if (drv->shutdown)
+		drv->driver.shutdown = amd_gnb_bus_drv_shutdown;
+
+	/* register with core */
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(amd_gnb_bus_register_driver);
+
+void amd_gnb_bus_unregister_driver(struct amd_gnb_bus_driver *drv)
+{
+	/* register with core */
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(amd_gnb_bus_unregister_driver);
+
+int amd_gnb_bus_register_device(struct amd_gnb_bus_dev *dev)
+{
+	dev->dev.bus = &amd_gnb_bus_type;
+	return device_add(&dev->dev);
+}
+EXPORT_SYMBOL(amd_gnb_bus_register_device);
+
+void amd_gnb_bus_unregister_device(struct amd_gnb_bus_dev *dev)
+{
+	if (dev)
+		device_del(&dev->dev);
+}
+EXPORT_SYMBOL(amd_gnb_bus_unregister_device);
+
+int amd_gnb_bus_device_init(struct amd_gnb_bus_dev *bus_dev,
+			    enum amd_gnb_bus_ip ip,
+			    char *dev_name,
+			    void *handle,
+			    struct device *parent)
+{
+	device_initialize(&bus_dev->dev);
+	bus_dev->dev.init_name = dev_name;
+	bus_dev->ip = ip;
+	bus_dev->private_data = handle;
+	bus_dev->dev.parent = parent;
+	return amd_gnb_bus_register_device(bus_dev);
+}
+EXPORT_SYMBOL(amd_gnb_bus_device_init);
+
+static int __init amd_gnb_bus_init(void)
+{
+	int ret = 0;
+	/* does this need to be thread safe? */
+	ret = bus_register(&amd_gnb_bus_type);
+	if (ret)
+		pr_err("%s: bus register failed\n", __func__);
+	else
+		pr_info("%s: initialization is successful\n", __func__);
+
+	return ret;
+}
+
+static void __exit amd_gnb_bus_exit(void)
+{
+	bus_unregister(&amd_gnb_bus_type);
+}
+
+module_init(amd_gnb_bus_init);
+module_exit(amd_gnb_bus_exit);
+
+MODULE_AUTHOR("AMD");
+MODULE_DESCRIPTION("AMD GPU bus");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/amd/include/bus/amd_gnb_bus.h b/drivers/gpu/drm/amd/include/bus/amd_gnb_bus.h
new file mode 100644
index 0000000..3e90077
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/bus/amd_gnb_bus.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ */
+
+#ifndef __AMD_GNB_BUS_H__
+#define __AMD_GNB_BUS_H__
+
+#include <linux/types.h>
+
+enum amd_gnb_bus_ip {
+	AMD_GNB_IP_ACP_DMA,
+	AMD_GNB_IP_ACP_I2S,
+	AMD_GNB_IP_ACP_PCM,
+	AMD_GNB_IP_ISP,
+	AMD_GNB_IP_NUM
+};
+
+struct amd_gnb_bus_dev {
+	struct device dev; /* generic device interface */
+	enum amd_gnb_bus_ip ip;
+	/* private data can be acp_handle/isp_handle etc.*/
+	void *private_data;
+};
+
+struct amd_gnb_bus_driver {
+	const char *name;
+	enum amd_gnb_bus_ip ip;
+	int (*probe)(struct amd_gnb_bus_dev *dev); /* New device inserted */
+	int (*remove)(struct amd_gnb_bus_dev *dev); /* Device removed */
+	int (*suspend)(struct amd_gnb_bus_dev *dev, pm_message_t state);
+	int (*resume)(struct amd_gnb_bus_dev *dev);
+	void (*shutdown)(struct amd_gnb_bus_dev *dev);
+	struct device_driver driver;  /* generic device driver interface */
+};
+
+#define amd_gnb_to_acp_device(x) container_of((x), \
+					     struct amd_gnb_bus_dev_acp, \
+					     base)
+#define amd_gnb_to_isp_device(x) container_of((x), \
+					     struct amd_gnb_bus_dev_isp, \
+					     base)
+#define amd_gnb_parent_to_pci_device(x) container_of((x)->dev.parent, \
+						     struct pci_dev,  \
+						     dev)
+
+int amd_gnb_bus_register_device(struct amd_gnb_bus_dev *dev);
+void amd_gnb_bus_unregister_device(struct amd_gnb_bus_dev *dev);
+int amd_gnb_bus_device_init(struct amd_gnb_bus_dev *bus_dev,
+			    enum amd_gnb_bus_ip ip,
+			    char *dev_name,
+			    void *handle,
+			    struct device *parent);
+int amd_gnb_bus_register_driver(struct amd_gnb_bus_driver *drv,
+			       struct module *owner,
+			       const char *mod_name);
+void amd_gnb_bus_unregister_driver(struct amd_gnb_bus_driver *drv);
+
+#endif
