From: "Chang, Rebecca Swee Fun" <rebecca.swee.fun.ch...@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.ch...@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.ch...@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.westerb...@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.westerb...@linux.intel.com>
++ *        Heikki Krogerus <heikki.kroge...@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.westerb...@linux.intel.com>
++ *        Heikki Krogerus <heikki.kroge...@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.westerb...@linux.intel.com>
++ *        Heikki Krogerus <heikki.kroge...@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

_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to