kernel: bump 4.9 to 4.9.166
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.9 / 803-cpufreq-support-layerscape.patch
index 2bc0f24f720f3e0352c6b04b29f0d1c3b19f8373..ac9b4b068a707a04268d4312c3b88691a5a28f6a 100644 (file)
@@ -1,9 +1,9 @@
-From a9ebdf9fa18fd317a4e97f46e8c5263898094864 Mon Sep 17 00:00:00 2001
+From b018e44a68dc2f4df819ae194e39e07313841dad Mon Sep 17 00:00:00 2001
 From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 25 Sep 2017 12:20:10 +0800
-Subject: [PATCH] cpufreq: support layerscape
+Date: Wed, 17 Jan 2018 15:27:58 +0800
+Subject: [PATCH 15/30] cpufreq: support layerscape
 
-This is a integrated patch for layerscape pm support.
+This is an integrated patch for layerscape pm support.
 
 Signed-off-by: Tang Yuantian <Yuantian.Tang@nxp.com>
 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
@@ -11,11 +11,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
  drivers/cpufreq/Kconfig         |   2 +-
  drivers/cpufreq/qoriq-cpufreq.c | 176 +++++++++++++++-------------------------
  drivers/firmware/psci.c         |  12 ++-
- 3 files changed, 77 insertions(+), 113 deletions(-)
+ drivers/soc/fsl/rcpm.c          | 158 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 235 insertions(+), 113 deletions(-)
+ create mode 100644 drivers/soc/fsl/rcpm.c
 
 --- a/drivers/cpufreq/Kconfig
 +++ b/drivers/cpufreq/Kconfig
-@@ -332,7 +332,7 @@ endif
+@@ -334,7 +334,7 @@ endif
  
  config QORIQ_CPUFREQ
        tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
@@ -326,7 +328,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
                pr_info("Freescale QorIQ CPU frequency scaling driver\n");
 --- a/drivers/firmware/psci.c
 +++ b/drivers/firmware/psci.c
-@@ -418,8 +418,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
+@@ -437,8 +437,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
  
  static int psci_system_suspend(unsigned long unused)
  {
@@ -341,7 +343,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
  }
  
  static int psci_system_suspend_enter(suspend_state_t state)
-@@ -439,6 +443,8 @@ static void __init psci_init_system_susp
+@@ -458,6 +462,8 @@ static void __init psci_init_system_susp
        if (!IS_ENABLED(CONFIG_SUSPEND))
                return;
  
@@ -350,7 +352,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
        ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
  
        if (ret != PSCI_RET_NOT_SUPPORTED)
-@@ -516,6 +522,8 @@ static void __init psci_0_2_set_function
+@@ -562,6 +568,8 @@ static void __init psci_0_2_set_function
        arm_pm_restart = psci_sys_reset;
  
        pm_power_off = psci_sys_poweroff;
@@ -359,3 +361,164 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
  }
  
  /*
+--- /dev/null
++++ b/drivers/soc/fsl/rcpm.c
+@@ -0,0 +1,158 @@
++/*
++ * Run Control and Power Management (RCPM) driver
++ *
++ * Copyright 2016 NXP
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ */
++#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/of_platform.h>
++#include <linux/of_address.h>
++#include <linux/suspend.h>
++
++/* RCPM register offset */
++#define RCPM_IPPDEXPCR0                       0x140
++
++#define RCPM_WAKEUP_CELL_SIZE 2
++
++struct rcpm_config {
++      int ipp_num;
++      int ippdexpcr_offset;
++      u32 ippdexpcr[2];
++      void *rcpm_reg_base;
++};
++
++static struct rcpm_config *rcpm;
++
++static inline void rcpm_reg_write(u32 offset, u32 value)
++{
++      iowrite32be(value, rcpm->rcpm_reg_base + offset);
++}
++
++static inline u32 rcpm_reg_read(u32 offset)
++{
++      return ioread32be(rcpm->rcpm_reg_base + offset);
++}
++
++static void rcpm_wakeup_fixup(struct device *dev, void *data)
++{
++      struct device_node *node = dev ? dev->of_node : NULL;
++      u32 value[RCPM_WAKEUP_CELL_SIZE];
++      int ret, i;
++
++      if (!dev || !node || !device_may_wakeup(dev))
++              return;
++
++      /*
++       * Get the values in the "rcpm-wakeup" property.
++       * Three values are:
++       * The first is a pointer to the RCPM node.
++       * The second is the value of the ippdexpcr0 register.
++       * The third is the value of the ippdexpcr1 register.
++       */
++      ret = of_property_read_u32_array(node, "fsl,rcpm-wakeup",
++                                       value, RCPM_WAKEUP_CELL_SIZE);
++      if (ret)
++              return;
++
++      pr_debug("wakeup source: the device %s\n", node->full_name);
++
++      for (i = 0; i < rcpm->ipp_num; i++)
++              rcpm->ippdexpcr[i] |= value[i + 1];
++}
++
++static int rcpm_suspend_prepare(void)
++{
++      int i;
++      u32 val;
++
++      BUG_ON(!rcpm);
++
++      for (i = 0; i < rcpm->ipp_num; i++)
++              rcpm->ippdexpcr[i] = 0;
++
++      dpm_for_each_dev(NULL, rcpm_wakeup_fixup);
++
++      for (i = 0; i < rcpm->ipp_num; i++) {
++              if (rcpm->ippdexpcr[i]) {
++                      val = rcpm_reg_read(rcpm->ippdexpcr_offset + 4 * i);
++                      rcpm_reg_write(rcpm->ippdexpcr_offset + 4 * i,
++                                             val | rcpm->ippdexpcr[i]);
++                      pr_debug("ippdexpcr%d = 0x%x\n", i, rcpm->ippdexpcr[i]);
++              }
++      }
++
++      return 0;
++}
++
++static int rcpm_suspend_notifier_call(struct notifier_block *bl,
++                                    unsigned long state,
++                                    void *unused)
++{
++      switch (state) {
++      case PM_SUSPEND_PREPARE:
++              rcpm_suspend_prepare();
++              break;
++      }
++
++      return NOTIFY_DONE;
++}
++
++static struct rcpm_config rcpm_default_config = {
++      .ipp_num = 1,
++      .ippdexpcr_offset = RCPM_IPPDEXPCR0,
++};
++
++static const struct of_device_id rcpm_matches[] = {
++      {
++              .compatible = "fsl,qoriq-rcpm-2.1",
++              .data = &rcpm_default_config,
++      },
++      {}
++};
++
++static struct notifier_block rcpm_suspend_notifier = {
++      .notifier_call = rcpm_suspend_notifier_call,
++};
++
++static int __init layerscape_rcpm_init(void)
++{
++      const struct of_device_id *match;
++      struct device_node *np;
++
++      np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
++      if (!np) {
++              pr_err("Can't find the RCPM node.\n");
++              return -EINVAL;
++      }
++
++      if (match->data)
++              rcpm = (struct rcpm_config *)match->data;
++      else
++              return -EINVAL;
++
++      rcpm->rcpm_reg_base = of_iomap(np, 0);
++      of_node_put(np);
++      if (!rcpm->rcpm_reg_base)
++              return -ENOMEM;
++
++      register_pm_notifier(&rcpm_suspend_notifier);
++
++      pr_info("The RCPM driver initialized.\n");
++
++      return 0;
++}
++
++subsys_initcall(layerscape_rcpm_init);