[linux-yocto] [PATCH 2/2] valleyisland-io: add patch to enable clock framework support on Baytrail
rebecca.swee.fun.chang at intel.com
rebecca.swee.fun.chang at intel.com
Sun Dec 8 19:09:55 PST 2013
From: "Chang, Rebecca Swee Fun" <rebecca.swee.fun.chang at intel.com>
clk/x86: Add clock framework support for Baytrail ACPI mode LPIO devices.
The ACPI mode LPIO devices inclusive of SPI, HSUART, I2C and DMA.
Signed-off-by: Chang, Rebecca Swee Fun <rebecca.swee.fun.chang at intel.com>
---
...-clock-framework-support-for-Intel-Baytra.patch | 465 ++++++++++++++++++++
1 file changed, 465 insertions(+)
create mode 100644 meta/cfg/kernel-cache/features/valleyisland-io/0012-clk-x86-Add-clock-framework-support-for-Intel-Baytra.patch
diff --git a/meta/cfg/kernel-cache/features/valleyisland-io/0012-clk-x86-Add-clock-framework-support-for-Intel-Baytra.patch b/meta/cfg/kernel-cache/features/valleyisland-io/0012-clk-x86-Add-clock-framework-support-for-Intel-Baytra.patch
new file mode 100644
index 0000000..c52ba78
--- /dev/null
+++ b/meta/cfg/kernel-cache/features/valleyisland-io/0012-clk-x86-Add-clock-framework-support-for-Intel-Baytra.patch
@@ -0,0 +1,465 @@
+clk/x86: Add clock framework support for Valley Island ACPI mode LPIO devices.
+
+The ACPI mode LPIO devices inclusive of SPI, HSUART, I2C and DMA.
+
+Signed-off-by: Chang, Rebecca Swee Fun <rebecca.swee.fun.chang at intel.com>
+---
+ drivers/clk/Makefile | 3 +
+ drivers/clk/x86/Makefile | 2 +
+ drivers/clk/x86/clk-byt.c | 94 ++++++++++++++++++++++++
+ drivers/clk/x86/clk-lpss.c | 170 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/clk/x86/clk-lpss.h | 47 ++++++++++++
+ drivers/clk/x86/clk-lpt.c | 86 ++++++++++++++++++++++
+ 6 files changed, 402 insertions(+)
+ create mode 100644 drivers/clk/x86/Makefile
+ create mode 100644 drivers/clk/x86/clk-byt.c
+ create mode 100644 drivers/clk/x86/clk-lpss.c
+ create mode 100644 drivers/clk/x86/clk-lpss.h
+ create mode 100644 drivers/clk/x86/clk-lpt.c
+
+diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
+index ee90e87..cb7e4ed 100644
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -22,6 +22,9 @@ obj-$(CONFIG_ARCH_U8500) += ux500/
+ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
+ obj-$(CONFIG_ARCH_SUNXI) += clk-sunxi.o
+ obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o
++ifeq ($(CONFIG_ACPI),y)
++obj-$(CONFIG_X86) += x86/
++endif
+
+ # Chip specific
+ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
+diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
+new file mode 100644
+index 0000000..4deed96
+--- /dev/null
++++ b/drivers/clk/x86/Makefile
+@@ -0,0 +1,2 @@
++clk-x86-lpss-objs := clk-lpss.o clk-lpt.o clk-byt.o
++obj-$(CONFIG_X86_INTEL_LPSS) += clk-x86-lpss.o
+diff --git a/drivers/clk/x86/clk-byt.c b/drivers/clk/x86/clk-byt.c
+new file mode 100644
+index 0000000..209c1cb
+--- /dev/null
++++ b/drivers/clk/x86/clk-byt.c
+@@ -0,0 +1,94 @@
++/*
++ * Intel BayTrail LPSS clocks.
++ *
++ * Copyright (C) 2013, Intel Corporation
++ * Author: Mika Westerberg <mika.westerberg at linux.intel.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/clk.h>
++#include <linux/clkdev.h>
++#include <linux/clk-provider.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <asm/processor.h>
++
++#include "clk-lpss.h"
++
++#define PRV_CLOCK_PARAMS_SPI 0x400
++#define PRV_CLOCK_PARAMS 0x800
++
++static int byt_clk_probe(struct platform_device *pdev)
++{
++ struct clk *clk;
++
++ /* SCC / LPSS free running clock */
++ clk = clk_register_fixed_rate(NULL, "lpss_clk", NULL, CLK_IS_ROOT,
++ 100000000);
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ /* Shared DMA controllers */
++ clk_register_clkdev(clk, "hclk", "INTL9C60.0.auto");
++ clk_register_clkdev(clk, "hclk", "INTL9C60.1.auto");
++
++ /* SPI clock */
++ clk = clk_register_fixed_rate(NULL, "spi_clk", "lpss_clk", 0, 50000000);
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ clk = clk_register_lpss_gate("spi0_clk", "spi_clk", "80860F0E", NULL,
++ PRV_CLOCK_PARAMS_SPI);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "80860F0E:00");
++
++ /* UART clock */
++ clk = clk_register_fixed_rate(NULL, "uart_clk", "lpss_clk", 0, 44236800);
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ clk = clk_register_lpss_gate("uart0_clk", "uart_clk", "80860F0A", "1",
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "80860F0A:00");
++
++ clk = clk_register_lpss_gate("uart1_clk", "uart_clk", "80860F0A", "2",
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "80860F0A:01");
++
++ /* I2C clocks */
++ clk = clk_register_fixed_rate(NULL, "i2c_100_clk", "lpss_clk", 0,
++ 100000000);
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ clk_register_clkdev(clk, NULL, "80860F41:00");
++ clk_register_clkdev(clk, NULL, "80860F41:01");
++ clk_register_clkdev(clk, NULL, "80860F41:02");
++ clk_register_clkdev(clk, NULL, "80860F41:03");
++ clk_register_clkdev(clk, NULL, "80860F41:04");
++ clk_register_clkdev(clk, NULL, "80860F41:05");
++ clk_register_clkdev(clk, NULL, "80860F41:06");
++
++ return 0;
++}
++
++static struct platform_driver byt_clk_driver = {
++ .driver = {
++ .name = "clk-byt",
++ .owner = THIS_MODULE,
++ },
++ .probe = byt_clk_probe,
++};
++
++static int __init byt_clk_init(void)
++{
++ return platform_driver_register(&byt_clk_driver);
++}
++arch_initcall(byt_clk_init);
+diff --git a/drivers/clk/x86/clk-lpss.c b/drivers/clk/x86/clk-lpss.c
+new file mode 100644
+index 0000000..9a8a939
+--- /dev/null
++++ b/drivers/clk/x86/clk-lpss.c
+@@ -0,0 +1,170 @@
++/*
++ * Intel Low Power Subsystem clocks.
++ *
++ * Copyright (C) 2013, Intel Corporation
++ * Authors: Mika Westerberg <mika.westerberg at linux.intel.com>
++ * Heikki Krogerus <heikki.krogerus at linux.intel.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/clk-provider.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/module.h>
++
++static int clk_lpss_is_mmio_resource(struct acpi_resource *res, void *data)
++{
++ struct resource r;
++ return !acpi_dev_resource_memory(res, &r);
++}
++
++static acpi_status clk_lpss_find_mmio(acpi_handle handle, u32 level,
++ void *data, void **retval)
++{
++ struct resource_list_entry *rentry;
++ struct list_head resource_list;
++ struct acpi_device *adev;
++ const char *uid = data;
++ int ret;
++
++ if (acpi_bus_get_device(handle, &adev))
++ return AE_OK;
++
++ if (uid) {
++ if (!adev->pnp.unique_id)
++ return AE_OK;
++ if (strcmp(uid, adev->pnp.unique_id))
++ return AE_OK;
++ }
++
++ INIT_LIST_HEAD(&resource_list);
++ ret = acpi_dev_get_resources(adev, &resource_list,
++ clk_lpss_is_mmio_resource, NULL);
++ if (ret < 0)
++ return AE_NO_MEMORY;
++
++ list_for_each_entry(rentry, &resource_list, node)
++ if (resource_type(&rentry->res) == IORESOURCE_MEM) {
++ *(struct resource *)retval = rentry->res;
++ break;
++ }
++
++ acpi_dev_free_resource_list(&resource_list);
++ return AE_OK;
++}
++
++/**
++ * clk_register_lpss_gate - register LPSS clock gate
++ * @name: name of this clock gate
++ * @parent_name: parent clock name
++ * @hid: ACPI _HID of the device
++ * @uid: ACPI _UID of the device (optional)
++ * @offset: LPSS PRV_CLOCK_PARAMS offset
++ *
++ * Creates and registers LPSS clock gate.
++ */
++struct clk *clk_register_lpss_gate(const char *name, const char *parent_name,
++ const char *hid, const char *uid,
++ unsigned offset)
++{
++ struct resource res = { };
++ void __iomem *mmio_base;
++ acpi_status status;
++ struct clk *clk;
++
++ /*
++ * First try to look the device and its mmio resource from the
++ * ACPI namespace.
++ */
++ status = acpi_get_devices(hid, clk_lpss_find_mmio, (void *)uid,
++ (void **)&res);
++ if (ACPI_FAILURE(status) || !res.start)
++ return ERR_PTR(-ENODEV);
++
++ mmio_base = ioremap(res.start, resource_size(&res));
++ if (!mmio_base)
++ return ERR_PTR(-ENOMEM);
++
++ clk = clk_register_gate(NULL, name, parent_name, 0, mmio_base + offset,
++ 0, 0, NULL);
++ if (IS_ERR(clk))
++ iounmap(mmio_base);
++
++ return clk;
++}
++
++static u8 clk_lpss_mux_get_parent(struct clk_hw *hw)
++{
++ struct clk_mux *mux = container_of(hw, struct clk_mux, hw);
++ return readl(mux->reg) & BIT(0);
++}
++
++static const struct clk_ops clk_lpss_mux_ops = {
++ .get_parent = clk_lpss_mux_get_parent,
++};
++
++/**
++ * clk_register_lpss_mux - register LPSS mux clock
++ * @name: name of this mux
++ * @parent_names: array of parent names for this clock
++ * @num_parents: number of parents in the array (max 2)
++ * @hid: ACPI _HID of the device
++ * @offset: LPSS PRV_CLOCK_PARAMS offset
++ *
++ * Creates a binary clock mux that selects between two parents. Most useful
++ * with the I2C clock. You cannot change the parent, only read it.
++ */
++struct clk *clk_register_lpss_mux(const char *name, const char **parent_names,
++ u8 num_parents, const char *hid,
++ unsigned offset)
++{
++ struct clk_init_data init = { };
++ struct resource res = { };
++ void __iomem *mmio_base;
++ struct clk_mux *mux;
++ acpi_status status;
++ struct clk *clk;
++
++ if (num_parents > 2)
++ return ERR_PTR(-EINVAL);
++
++ status = acpi_get_devices(hid, clk_lpss_find_mmio, NULL, (void **)&res);
++ if (ACPI_FAILURE(status) || !res.start)
++ return ERR_PTR(-ENODEV);
++
++ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
++ if (!mux)
++ return ERR_PTR(-ENOMEM);
++
++ init.name = name;
++ init.ops = &clk_lpss_mux_ops;
++ init.parent_names = parent_names;
++ init.num_parents = num_parents;
++
++ mmio_base = ioremap(res.start, resource_size(&res));
++ if (!mmio_base) {
++ clk = ERR_PTR(-ENOMEM);
++ goto fail_free;
++ }
++
++ mux->reg = mmio_base + offset;
++ mux->hw.init = &init;
++
++ clk = clk_register(NULL, &mux->hw);
++ if (IS_ERR(clk))
++ goto fail_unmap;
++
++ return clk;
++
++fail_unmap:
++ iounmap(mmio_base);
++fail_free:
++ kfree(mux);
++
++ return clk;
++}
+diff --git a/drivers/clk/x86/clk-lpss.h b/drivers/clk/x86/clk-lpss.h
+new file mode 100644
+index 0000000..bdddeb5f
+--- /dev/null
++++ b/drivers/clk/x86/clk-lpss.h
+@@ -0,0 +1,47 @@
++/*
++ * Intel Low Power Subsystem clock.
++ *
++ * Copyright (C) 2013, Intel Corporation
++ * Authors: Mika Westerberg <mika.westerberg at linux.intel.com>
++ * Heikki Krogerus <heikki.krogerus at linux.intel.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.
++ */
++
++#ifndef __CLK_LPSS_H
++#define __CLK_LPSS_H
++
++#include <linux/err.h>
++#include <linux/errno.h>
++#include <linux/clk.h>
++
++#ifdef CONFIG_ACPI
++extern struct clk *clk_register_lpss_gate(const char *name,
++ const char *parent_name,
++ const char *hid, const char *uid,
++ unsigned offset);
++extern struct clk *clk_register_lpss_mux(const char *name,
++ const char **parent_names,
++ u8 num_parents, const char *hid,
++ unsigned offset);
++#else
++static inline struct clk *clk_register_lpss_gate(const char *name,
++ const char *parent_name,
++ const char *hid,
++ const char *uid,
++ unsigned offset)
++{
++ return ERR_PTR(-ENODEV);
++}
++static inline struct clk *clk_register_lpss_mux(const char *name,
++ const char **parent_names,
++ u8 num_parents, const char *hid,
++ unsigned offset)
++{
++ return ERR_PTR(-ENODEV);
++}
++#endif
++
++#endif /* __CLK_LPSS_H */
+diff --git a/drivers/clk/x86/clk-lpt.c b/drivers/clk/x86/clk-lpt.c
+new file mode 100644
+index 0000000..81298ae
+--- /dev/null
++++ b/drivers/clk/x86/clk-lpt.c
+@@ -0,0 +1,86 @@
++/*
++ * Intel Lynxpoint LPSS clocks.
++ *
++ * Copyright (C) 2013, Intel Corporation
++ * Authors: Mika Westerberg <mika.westerberg at linux.intel.com>
++ * Heikki Krogerus <heikki.krogerus at linux.intel.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/module.h>
++#include <linux/platform_device.h>
++
++#include "clk-lpss.h"
++
++#define PRV_CLOCK_PARAMS 0x800
++
++static int lpt_clk_probe(struct platform_device *pdev)
++{
++ struct clk *clk;
++
++ /* LPSS free running clock */
++ clk = clk_register_fixed_rate(&pdev->dev, "lpss_clk", NULL, CLK_IS_ROOT,
++ 100000000);
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ /* Shared DMA clock */
++ clk_register_clkdev(clk, "hclk", "INTL9C60.0.auto");
++
++ /* SPI clocks */
++ clk = clk_register_lpss_gate("spi0_clk", "lpss_clk", "INT33C0", NULL,
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "INT33C0:00");
++
++ clk = clk_register_lpss_gate("spi1_clk", "lpss_clk", "INT33C1", NULL,
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "INT33C1:00");
++
++ /* I2C clocks */
++ clk = clk_register_lpss_gate("i2c0_clk", "lpss_clk", "INT33C2", NULL,
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "INT33C2:00");
++
++ clk = clk_register_lpss_gate("i2c1_clk", "lpss_clk", "INT33C3", NULL,
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "INT33C3:00");
++
++ /* UART clocks */
++ clk = clk_register_lpss_gate("uart0_clk", "lpss_clk", "INT33C4", NULL,
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "INT33C4:00");
++
++ clk = clk_register_lpss_gate("uart1_clk", "lpss_clk", "INT33C5", NULL,
++ PRV_CLOCK_PARAMS);
++ if (!IS_ERR(clk))
++ clk_register_clkdev(clk, NULL, "INT33C5:00");
++
++ return 0;
++}
++
++static struct platform_driver lpt_clk_driver = {
++ .driver = {
++ .name = "clk-lpt",
++ .owner = THIS_MODULE,
++ },
++ .probe = lpt_clk_probe,
++};
++
++static int __init lpt_clk_init(void)
++{
++ return platform_driver_register(&lpt_clk_driver);
++}
++arch_initcall(lpt_clk_init);
+--
+1.7.10.4
+
--
1.7.10.4
More information about the linux-yocto
mailing list