[PATCH v2 4/4] powerpc/85xx: add support to JOG feature using cpufreq interface

2012-08-10 Thread Zhao Chenhui
Some 85xx silicons like MPC8536 and P1022 have a JOG feature, which provides
a dynamic mechanism to lower or raise the CPU core clock at runtime.

This patch adds the support to change CPU frequency using the standard
cpufreq interface. The ratio CORE to CCB can be 1:1(except MPC8536), 3:2,
2:1, 5:2, 3:1, 7:2 and 4:1.

Two CPU cores on P1022 must not in the low power state during the frequency
transition. The driver uses a atomic counter to meet the requirement.

The jog mode frequency transition process on the MPC8536 is similar to
the deep sleep process. The driver need save the CPU state and restore
it after CPU warm reset.

Note:
 * The I/O peripherals such as PCIe and eTSEC may lose packets during
   the jog mode frequency transition.
 * The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
   Subsequent revisions of MPC8536 have corrected the erratum.

Signed-off-by: Dave Liu 
Signed-off-by: Li Yang 
Signed-off-by: Jerry Huang 
Signed-off-by: Zhao Chenhui 
CC: Scott Wood 
---
v2:
* use get/put_online_cpus() to disable/enable cpu hotplug.

 arch/powerpc/platforms/85xx/Makefile  |1 +
 arch/powerpc/platforms/85xx/cpufreq-jog.c |  388 +
 arch/powerpc/platforms/Kconfig|   11 +
 arch/powerpc/sysdev/fsl_pmc.c |3 +
 arch/powerpc/sysdev/fsl_soc.h |2 +
 5 files changed, 405 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/cpufreq-jog.c

diff --git a/arch/powerpc/platforms/85xx/Makefile 
b/arch/powerpc/platforms/85xx/Makefile
index 8a030a1..6156849 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SMP) += smp.o
 
 obj-y += common.o
 obj-$(CONFIG_FSL_PMC) += sleep.o
+obj-$(CONFIG_MPC85xx_CPUFREQ) += cpufreq-jog.o
 
 obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/cpufreq-jog.c 
b/arch/powerpc/platforms/85xx/cpufreq-jog.c
new file mode 100644
index 000..287987b
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/cpufreq-jog.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Author: Dave Liu 
+ * Modifier: Chenhui Zhao 
+ *
+ * The cpufreq driver is for Freescale 85xx processor,
+ * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ * Christian Krafft 
+ *
+ * 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, 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+
+static u32 sysfreq;
+static unsigned int max_pll[2];
+static atomic_t in_jog_process;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+static int (*set_pll)(unsigned int cpu, unsigned int pll);
+
+static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
+   {3, 0},
+   {4, 0},
+   {5, 0},
+   {6, 0},
+   {7, 0},
+   {8, 0},
+   {0, CPUFREQ_TABLE_END},
+};
+
+static struct cpufreq_frequency_table p1022_freqs_table[] = {
+   {2, 0},
+   {3, 0},
+   {4, 0},
+   {5, 0},
+   {6, 0},
+   {7, 0},
+   {8, 0},
+   {0, CPUFREQ_TABLE_END},
+};
+
+#define FREQ_500MHz5
+#define FREQ_800MHz8
+
+#define CORE_RATIO_STRIDE  8
+#define CORE_RATIO_MASK0x3f
+#define CORE_RATIO_SHIFT   16
+
+#define PORPLLSR   0x0 /* Power-On Reset PLL ratio status register */
+
+#define PMJCR  0x7c/* Power Management Jog Control Register */
+#define PMJCR_CORE0_SPD0x1000
+#define PMJCR_CORE_SPD 0x2000
+
+#define POWMGTCSR  0x80 /* Power management control and status register */
+#define POWMGTCSR_JOG  0x0020
+#define POWMGTCSR_INT_MASK 0x0f00
+
+static void spin_while_jogging(void *dummy)
+{
+   unsigned long flags;
+
+   local_irq_save(flags);
+
+   atomic_inc(_jog_process);
+
+   while (atomic_read(_jog_process) != 0)
+   barrier();
+
+   local_irq_restore(flags);
+}
+
+static int get_pll(int hw_cpu)
+{
+   int shift;
+   u32 val = in_be32(guts + 

[PATCH v2 4/4] powerpc/85xx: add support to JOG feature using cpufreq interface

2012-08-10 Thread Zhao Chenhui
Some 85xx silicons like MPC8536 and P1022 have a JOG feature, which provides
a dynamic mechanism to lower or raise the CPU core clock at runtime.

This patch adds the support to change CPU frequency using the standard
cpufreq interface. The ratio CORE to CCB can be 1:1(except MPC8536), 3:2,
2:1, 5:2, 3:1, 7:2 and 4:1.

Two CPU cores on P1022 must not in the low power state during the frequency
transition. The driver uses a atomic counter to meet the requirement.

The jog mode frequency transition process on the MPC8536 is similar to
the deep sleep process. The driver need save the CPU state and restore
it after CPU warm reset.

Note:
 * The I/O peripherals such as PCIe and eTSEC may lose packets during
   the jog mode frequency transition.
 * The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
   Subsequent revisions of MPC8536 have corrected the erratum.

Signed-off-by: Dave Liu dave...@freescale.com
Signed-off-by: Li Yang le...@freescale.com
Signed-off-by: Jerry Huang chang-ming.hu...@freescale.com
Signed-off-by: Zhao Chenhui chenhui.z...@freescale.com
CC: Scott Wood scottw...@freescale.com
---
v2:
* use get/put_online_cpus() to disable/enable cpu hotplug.

 arch/powerpc/platforms/85xx/Makefile  |1 +
 arch/powerpc/platforms/85xx/cpufreq-jog.c |  388 +
 arch/powerpc/platforms/Kconfig|   11 +
 arch/powerpc/sysdev/fsl_pmc.c |3 +
 arch/powerpc/sysdev/fsl_soc.h |2 +
 5 files changed, 405 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/cpufreq-jog.c

diff --git a/arch/powerpc/platforms/85xx/Makefile 
b/arch/powerpc/platforms/85xx/Makefile
index 8a030a1..6156849 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SMP) += smp.o
 
 obj-y += common.o
 obj-$(CONFIG_FSL_PMC) += sleep.o
+obj-$(CONFIG_MPC85xx_CPUFREQ) += cpufreq-jog.o
 
 obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/cpufreq-jog.c 
b/arch/powerpc/platforms/85xx/cpufreq-jog.c
new file mode 100644
index 000..287987b
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/cpufreq-jog.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Author: Dave Liu dave...@freescale.com
+ * Modifier: Chenhui Zhao chenhui.z...@freescale.com
+ *
+ * The cpufreq driver is for Freescale 85xx processor,
+ * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ * Christian Krafft kra...@de.ibm.com
+ *
+ * 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, 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include linux/module.h
+#include linux/cpufreq.h
+#include linux/of_platform.h
+#include linux/suspend.h
+#include linux/cpu.h
+
+#include asm/prom.h
+#include asm/time.h
+#include asm/reg.h
+#include asm/io.h
+#include asm/machdep.h
+#include asm/smp.h
+
+#include sysdev/fsl_soc.h
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+
+static u32 sysfreq;
+static unsigned int max_pll[2];
+static atomic_t in_jog_process;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+static int (*set_pll)(unsigned int cpu, unsigned int pll);
+
+static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
+   {3, 0},
+   {4, 0},
+   {5, 0},
+   {6, 0},
+   {7, 0},
+   {8, 0},
+   {0, CPUFREQ_TABLE_END},
+};
+
+static struct cpufreq_frequency_table p1022_freqs_table[] = {
+   {2, 0},
+   {3, 0},
+   {4, 0},
+   {5, 0},
+   {6, 0},
+   {7, 0},
+   {8, 0},
+   {0, CPUFREQ_TABLE_END},
+};
+
+#define FREQ_500MHz5
+#define FREQ_800MHz8
+
+#define CORE_RATIO_STRIDE  8
+#define CORE_RATIO_MASK0x3f
+#define CORE_RATIO_SHIFT   16
+
+#define PORPLLSR   0x0 /* Power-On Reset PLL ratio status register */
+
+#define PMJCR  0x7c/* Power Management Jog Control Register */
+#define PMJCR_CORE0_SPD0x1000
+#define PMJCR_CORE_SPD 0x2000
+
+#define POWMGTCSR  0x80 /* Power management control and status register */
+#define POWMGTCSR_JOG  0x0020
+#define POWMGTCSR_INT_MASK 0x0f00
+
+static void