aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amdfalconx86/recipes-kernel/linux/files/0005-yocto-amd-i2c-driver_support_ACPI2Platform-1.0.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/0005-yocto-amd-i2c-driver_support_ACPI2Platform-1.0.patch')
-rw-r--r--meta-amdfalconx86/recipes-kernel/linux/files/0005-yocto-amd-i2c-driver_support_ACPI2Platform-1.0.patch317
1 files changed, 317 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/0005-yocto-amd-i2c-driver_support_ACPI2Platform-1.0.patch b/meta-amdfalconx86/recipes-kernel/linux/files/0005-yocto-amd-i2c-driver_support_ACPI2Platform-1.0.patch
new file mode 100644
index 00000000..992a54f8
--- /dev/null
+++ b/meta-amdfalconx86/recipes-kernel/linux/files/0005-yocto-amd-i2c-driver_support_ACPI2Platform-1.0.patch
@@ -0,0 +1,317 @@
+From a29dd45173a7e20e5e3f29fb8d71222b80fb0c12 Mon Sep 17 00:00:00 2001
+From: Ken Xue <Ken.Xue@amd.com>
+Date: Thu, 6 Nov 2014 08:21:37 +0800
+Subject: [PATCH 1/6] [CZ][FCH]support ACPI2Platform device for x86 system.
+
+This new feature is to interpret AMD specific ACPI device to platform device
+such as I2C, UART found on AMD CZ and later chipsets. It is based on example
+INTEL LPSS. Now, it just supports AMD I2C.
+
+Signed-off-by: Ken Xue <Ken.Xue@amd.com>
+Signed-off-by: Jeff Wu <Jeff.Wu@amd.com>
+Signed-off-by: Awais Belal <awais_belal@mentor.com>
+---
+ arch/x86/Kconfig | 11 +++
+ drivers/acpi/Makefile | 1 +
+ drivers/acpi/acpi_apd.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/acpi/internal.h | 6 ++
+ drivers/acpi/scan.c | 1 +
+ 5 files changed, 253 insertions(+)
+ create mode 100644 drivers/acpi/acpi_apd.c
+diff -Naur a/arch/x86/Kconfig b/arch/x86/Kconfig
+--- a/arch/x86/Kconfig 2015-03-25 14:39:54.676737984 +0530
++++ b/arch/x86/Kconfig 2015-03-25 14:51:42.084751856 +0530
+@@ -474,6 +474,17 @@
+ 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 pincontrol.
++
+ config X86_RDC321X
+ bool "RDC R-321x SoC"
+ depends on X86_32
+diff -Naur a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
+--- a/drivers/acpi/acpi_apd.c 1970-01-01 05:30:00.000000000 +0530
++++ b/drivers/acpi/acpi_apd.c 2015-03-25 14:51:42.084751856 +0530
+@@ -0,0 +1,234 @@
++/*
++ * AMD ACPI support for ACPI2platform device.
++ *
++ * Copyright (c) 2014, AMD Corporation.
++ * Authors: Ken Xue <Ken.Xue@amd.com>
++ * Peng, Carl <Carl.Peng@amd.com>
++ * Wu, Jeff <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 fix_rate_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,
++ .fix_rate_root_clock = true,
++ .clk_name = "i2c_clk",
++ .rate = 136192000, /*(133 * 1024 * 1000)*/
++};
++
++static const struct acpi_device_id acpi_apd_device_ids[] = {
++ /* Generic apd devices */
++ { "AMD0010", (unsigned long)&amd_i2c_desc },
++ /*{ "UART0000, (unsigned long)&amur_uart_dev_desc },*/
++ /*{"AMD0030", (unsigned long)&amur_gpio_dev_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->fix_rate_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;
++ int ret;
++
++ dev_desc = (struct apd_device_desc *)id->driver_data;
++ if (!dev_desc)
++ return acpi_create_platform_device(adev, id);
++
++ 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;
++ ret = acpi_create_platform_device(adev, id);
++ if (ret > 0)
++ return ret;
++
++ 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->fix_rate_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 -Naur a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+--- a/drivers/acpi/internal.h 2015-03-25 14:39:54.684737985 +0530
++++ b/drivers/acpi/internal.h 2015-03-25 14:51:42.084751856 +0530
+@@ -72,6 +72,12 @@
+ static inline void acpi_lpss_init(void) {}
+ #endif
+
++#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
++void acpi_apd_init(void);
++#else
++static inline void acpi_apd_init(void) {}
++#endif
++
+ bool acpi_queue_hotplug_work(struct work_struct *work);
+ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
+
+diff -Naur a/drivers/acpi/Makefile b/drivers/acpi/Makefile
+--- a/drivers/acpi/Makefile 2015-03-25 14:39:54.684737985 +0530
++++ b/drivers/acpi/Makefile 2015-03-25 14:51:42.084751856 +0530
+@@ -40,6 +40,7 @@
+ acpi-$(CONFIG_ACPI_DOCK) += dock.o
+ acpi-y += pci_root.o pci_link.o pci_irq.o
+ acpi-$(CONFIG_X86_INTEL_LPSS) += acpi_lpss.o
++acpi-$(CONFIG_X86_AMD_PLATFORM_DEVICE) += acpi_apd.o
+ acpi-y += acpi_platform.o
+ acpi-y += power.o
+ acpi-y += event.o
+diff -Naur a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+--- a/drivers/acpi/scan.c 2015-03-25 14:39:54.688737985 +0530
++++ b/drivers/acpi/scan.c 2015-03-25 14:51:42.084751856 +0530
+@@ -2191,6 +2191,7 @@
+ acpi_processor_init();
+ acpi_platform_init();
+ acpi_lpss_init();
++ acpi_apd_init();
+ acpi_cmos_rtc_init();
+ acpi_container_init();
+ acpi_memory_hotplug_init();