diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch | 173 |
1 files changed, 168 insertions, 5 deletions
diff --git a/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch b/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch index 2bc0f24f72..2da45b6cf0 100644 --- a/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch @@ -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,7 +11,9 @@ 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 @@ -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); |