All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-09-20  4:29 ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

The existing device tree bindings are error-prone and inflexible. 
Correct the mistake by moving the knowledge into the driver, which has
more flexibility in describing the quirks of each chip.  This leaves the
device tree to its proper role of identifying a programming interface
rather than describing its individual registers.

For more detail, see the commit message of patch 2.

As there are both ARM and PPC patches that depend on this patchset, I'm
requesting ACKs from clk and cpufreq in order to put this into a topic
branch that both ARM and PPC can pull.

Scott Wood (5):
  powerpc/fsl: Move fsl_guts.h out of arch/powerpc
  clk: qoriq: Move chip-specific knowledge into driver
  clk: qoriq: Add ls2080a support.
  clk: Add consumer APIs for discovering possible parent clocks
  cpufreq: qoriq: Don't look at clock implementation details

 .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
 arch/powerpc/include/asm/fsl_guts.h                |  192 ---
 arch/powerpc/platforms/85xx/mpc85xx_mds.c          |    2 +-
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c          |    2 +-
 arch/powerpc/platforms/85xx/p1022_ds.c             |    2 +-
 arch/powerpc/platforms/85xx/p1022_rdk.c            |    2 +-
 arch/powerpc/platforms/85xx/smp.c                  |    2 +-
 arch/powerpc/platforms/85xx/twr_p102x.c            |    2 +-
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c         |    2 +-
 drivers/clk/Kconfig                                |    2 +-
 drivers/clk/clk-qoriq.c                            | 1316 ++++++++++++++++----
 drivers/clk/clk.c                                  |   19 +
 drivers/cpufreq/qoriq-cpufreq.c                    |  137 +-
 drivers/iommu/fsl_pamu.c                           |    2 +-
 include/linux/clk.h                                |   31 +
 include/linux/fsl/guts.h                           |  192 +++
 sound/soc/fsl/mpc8610_hpcd.c                       |    2 +-
 sound/soc/fsl/p1022_ds.c                           |    2 +-
 sound/soc/fsl/p1022_rdk.c                          |    2 +-
 19 files changed, 1441 insertions(+), 531 deletions(-)
 delete mode 100644 arch/powerpc/include/asm/fsl_guts.h
 create mode 100644 include/linux/fsl/guts.h

-- 
2.1.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-09-20  4:29 ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

The existing device tree bindings are error-prone and inflexible. 
Correct the mistake by moving the knowledge into the driver, which has
more flexibility in describing the quirks of each chip.  This leaves the
device tree to its proper role of identifying a programming interface
rather than describing its individual registers.

For more detail, see the commit message of patch 2.

As there are both ARM and PPC patches that depend on this patchset, I'm
requesting ACKs from clk and cpufreq in order to put this into a topic
branch that both ARM and PPC can pull.

Scott Wood (5):
  powerpc/fsl: Move fsl_guts.h out of arch/powerpc
  clk: qoriq: Move chip-specific knowledge into driver
  clk: qoriq: Add ls2080a support.
  clk: Add consumer APIs for discovering possible parent clocks
  cpufreq: qoriq: Don't look at clock implementation details

 .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
 arch/powerpc/include/asm/fsl_guts.h                |  192 ---
 arch/powerpc/platforms/85xx/mpc85xx_mds.c          |    2 +-
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c          |    2 +-
 arch/powerpc/platforms/85xx/p1022_ds.c             |    2 +-
 arch/powerpc/platforms/85xx/p1022_rdk.c            |    2 +-
 arch/powerpc/platforms/85xx/smp.c                  |    2 +-
 arch/powerpc/platforms/85xx/twr_p102x.c            |    2 +-
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c         |    2 +-
 drivers/clk/Kconfig                                |    2 +-
 drivers/clk/clk-qoriq.c                            | 1316 ++++++++++++++++----
 drivers/clk/clk.c                                  |   19 +
 drivers/cpufreq/qoriq-cpufreq.c                    |  137 +-
 drivers/iommu/fsl_pamu.c                           |    2 +-
 include/linux/clk.h                                |   31 +
 include/linux/fsl/guts.h                           |  192 +++
 sound/soc/fsl/mpc8610_hpcd.c                       |    2 +-
 sound/soc/fsl/p1022_ds.c                           |    2 +-
 sound/soc/fsl/p1022_rdk.c                          |    2 +-
 19 files changed, 1441 insertions(+), 531 deletions(-)
 delete mode 100644 arch/powerpc/include/asm/fsl_guts.h
 create mode 100644 include/linux/fsl/guts.h

-- 
2.1.4


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-09-20  4:29 ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

The existing device tree bindings are error-prone and inflexible. 
Correct the mistake by moving the knowledge into the driver, which has
more flexibility in describing the quirks of each chip.  This leaves the
device tree to its proper role of identifying a programming interface
rather than describing its individual registers.

For more detail, see the commit message of patch 2.

As there are both ARM and PPC patches that depend on this patchset, I'm
requesting ACKs from clk and cpufreq in order to put this into a topic
branch that both ARM and PPC can pull.

Scott Wood (5):
  powerpc/fsl: Move fsl_guts.h out of arch/powerpc
  clk: qoriq: Move chip-specific knowledge into driver
  clk: qoriq: Add ls2080a support.
  clk: Add consumer APIs for discovering possible parent clocks
  cpufreq: qoriq: Don't look at clock implementation details

 .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
 arch/powerpc/include/asm/fsl_guts.h                |  192 ---
 arch/powerpc/platforms/85xx/mpc85xx_mds.c          |    2 +-
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c          |    2 +-
 arch/powerpc/platforms/85xx/p1022_ds.c             |    2 +-
 arch/powerpc/platforms/85xx/p1022_rdk.c            |    2 +-
 arch/powerpc/platforms/85xx/smp.c                  |    2 +-
 arch/powerpc/platforms/85xx/twr_p102x.c            |    2 +-
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c         |    2 +-
 drivers/clk/Kconfig                                |    2 +-
 drivers/clk/clk-qoriq.c                            | 1316 ++++++++++++++++----
 drivers/clk/clk.c                                  |   19 +
 drivers/cpufreq/qoriq-cpufreq.c                    |  137 +-
 drivers/iommu/fsl_pamu.c                           |    2 +-
 include/linux/clk.h                                |   31 +
 include/linux/fsl/guts.h                           |  192 +++
 sound/soc/fsl/mpc8610_hpcd.c                       |    2 +-
 sound/soc/fsl/p1022_ds.c                           |    2 +-
 sound/soc/fsl/p1022_rdk.c                          |    2 +-
 19 files changed, 1441 insertions(+), 531 deletions(-)
 delete mode 100644 arch/powerpc/include/asm/fsl_guts.h
 create mode 100644 include/linux/fsl/guts.h

-- 
2.1.4

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 1/5] powerpc/fsl: Move fsl_guts.h out of arch/powerpc
  2015-09-20  4:29 ` Scott Wood
  (?)
@ 2015-09-20  4:29   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

Freescale's Layerscape ARM chips use the same structure.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: was patch 2/5

 arch/powerpc/include/asm/fsl_guts.h        | 192 -----------------------------
 arch/powerpc/platforms/85xx/mpc85xx_mds.c  |   2 +-
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c  |   2 +-
 arch/powerpc/platforms/85xx/p1022_ds.c     |   2 +-
 arch/powerpc/platforms/85xx/p1022_rdk.c    |   2 +-
 arch/powerpc/platforms/85xx/smp.c          |   2 +-
 arch/powerpc/platforms/85xx/twr_p102x.c    |   2 +-
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c |   2 +-
 drivers/iommu/fsl_pamu.c                   |   2 +-
 include/linux/fsl/guts.h                   | 192 +++++++++++++++++++++++++++++
 sound/soc/fsl/mpc8610_hpcd.c               |   2 +-
 sound/soc/fsl/p1022_ds.c                   |   2 +-
 sound/soc/fsl/p1022_rdk.c                  |   2 +-
 13 files changed, 203 insertions(+), 203 deletions(-)
 delete mode 100644 arch/powerpc/include/asm/fsl_guts.h
 create mode 100644 include/linux/fsl/guts.h

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
deleted file mode 100644
index 43b6bb1..0000000
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * Freecale 85xx and 86xx Global Utilties register set
- *
- * Authors: Jeff Brown
- *          Timur Tabi <timur@freescale.com>
- *
- * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
- *
- * 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.
- */
-
-#ifndef __ASM_POWERPC_FSL_GUTS_H__
-#define __ASM_POWERPC_FSL_GUTS_H__
-#ifdef __KERNEL__
-
-/**
- * Global Utility Registers.
- *
- * Not all registers defined in this structure are available on all chips, so
- * you are expected to know whether a given register actually exists on your
- * chip before you access it.
- *
- * Also, some registers are similar on different chips but have slightly
- * different names.  In these cases, one name is chosen to avoid extraneous
- * #ifdefs.
- */
-struct ccsr_guts {
-	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
-	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
-	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
-	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
-	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
-	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
-	u8	res018[0x20 - 0x18];
-	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
-	u8	res024[0x30 - 0x24];
-	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
-	u8	res034[0x40 - 0x34];
-	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
-	u8	res044[0x50 - 0x44];
-	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
-	u8	res054[0x60 - 0x54];
-	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
-        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
-        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
-        u8	res06c[0x70 - 0x6c];
-	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
-#define CCSR_GUTS_DEVDISR_TB1	0x00001000
-#define CCSR_GUTS_DEVDISR_TB0	0x00004000
-	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
-	u8	res078[0x7c - 0x78];
-	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
-	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
-	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
-	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
-	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
-	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
-	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
-	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
-	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
-	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
-	__be32	svr;		/* 0x.00a4 - System Version Register */
-	u8	res0a8[0xb0 - 0xa8];
-	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
-	u8	res0b4[0xc0 - 0xb4];
-	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
-					     Called 'elbcvselcr' on 86xx SOCs */
-	u8	res0c4[0x100 - 0xc4];
-	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
-					     There are 16 registers */
-	u8	res140[0x224 - 0x140];
-	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
-	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
-	u8	res22c[0x604 - 0x22c];
-	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
-	u8	res608[0x800 - 0x608];
-	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
-	u8	res804[0x900 - 0x804];
-	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
-	u8	res904[0x908 - 0x904];
-	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
-	u8	res90c[0x914 - 0x90c];
-	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
-	u8	res918[0xb20 - 0x918];
-	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
-	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
-	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
-	u8	resb2c[0xe00 - 0xb2c];
-	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
-	u8	rese04[0xe10 - 0xe04];
-	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
-	u8	rese14[0xe20 - 0xe14];
-	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
-	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
-	u8	rese28[0xf04 - 0xe28];
-	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
-	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
-	u8	resf0c[0xf2c - 0xf0c];
-	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
-	u8	resf30[0xf40 - 0xf30];
-	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
-	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
-} __attribute__ ((packed));
-
-
-/* Alternate function signal multiplex control */
-#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
-
-#ifdef CONFIG_PPC_86xx
-
-#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
-#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
-
-/*
- * Set the DMACR register in the GUTS
- *
- * The DMACR register determines the source of initiated transfers for each
- * channel on each DMA controller.  Rather than have a bunch of repetitive
- * macros for the bit patterns, we just have a function that calculates
- * them.
- *
- * guts: Pointer to GUTS structure
- * co: The DMA controller (0 or 1)
- * ch: The channel on the DMA controller (0, 1, 2, or 3)
- * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
- */
-static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
-	unsigned int co, unsigned int ch, unsigned int device)
-{
-	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
-
-	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
-}
-
-#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
-#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
-#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
-#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
-#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
-#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
-#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
-#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
-#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
-#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
-#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
-#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
-#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
-#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
-#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
-#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
-
-/*
- * Set the DMA external control bits in the GUTS
- *
- * The DMA external control bits in the PMUXCR are only meaningful for
- * channels 0 and 3.  Any other channels are ignored.
- *
- * guts: Pointer to GUTS structure
- * co: The DMA controller (0 or 1)
- * ch: The channel on the DMA controller (0, 1, 2, or 3)
- * value: the new value for the bit (0 or 1)
- */
-static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
-	unsigned int co, unsigned int ch, unsigned int value)
-{
-	if ((ch == 0) || (ch == 3)) {
-		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
-
-		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
-	}
-}
-
-#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
-#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
-#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
-#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
-#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
-#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
-	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
-#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
-#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
-#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
-#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
-#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
-
-#endif
-
-#endif
-#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index a392e94..f0be439 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -34,6 +34,7 @@
 #include <linux/of_device.h>
 #include <linux/phy.h>
 #include <linux/memblock.h>
+#include <linux/fsl/guts.h>
 
 #include <linux/atomic.h>
 #include <asm/time.h>
@@ -51,7 +52,6 @@
 #include <asm/qe_ic.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
-#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index e358bed..50dcc00 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -17,6 +17,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -27,7 +28,6 @@
 #include <asm/mpic.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
-#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 6ac986d3..371df82 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -16,6 +16,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -25,7 +26,6 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
-#include <asm/fsl_guts.h>
 #include <asm/fsl_lbc.h>
 #include "smp.h"
 
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
index 680232d..5087bec 100644
--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -12,6 +12,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -21,7 +22,6 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
-#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index b8b8216..6ac7786 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -19,6 +19,7 @@
 #include <linux/kexec.h>
 #include <linux/highmem.h>
 #include <linux/cpu.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -26,7 +27,6 @@
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
-#include <asm/fsl_guts.h>
 #include <asm/code-patching.h>
 #include <asm/cputhreads.h>
 
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
index 30e002f..892e613 100644
--- a/arch/powerpc/platforms/85xx/twr_p102x.c
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 
@@ -23,7 +24,6 @@
 #include <asm/mpic.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
-#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 55413a5..437a9c3 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -38,7 +39,6 @@
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/simple_gpio.h>
-#include <asm/fsl_guts.h>
 
 #include "mpc86xx.h"
 
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 2570f2a2..a34355f 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -20,11 +20,11 @@
 
 #include "fsl_pamu.h"
 
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
 #include <asm/mpc85xx.h>
-#include <asm/fsl_guts.h>
 
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
new file mode 100644
index 0000000..84d971f
--- /dev/null
+++ b/include/linux/fsl/guts.h
@@ -0,0 +1,192 @@
+/**
+ * Freecale 85xx and 86xx Global Utilties register set
+ *
+ * Authors: Jeff Brown
+ *          Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#ifndef __FSL_GUTS_H__
+#define __FSL_GUTS_H__
+
+#include <linux/types.h>
+
+/**
+ * Global Utility Registers.
+ *
+ * Not all registers defined in this structure are available on all chips, so
+ * you are expected to know whether a given register actually exists on your
+ * chip before you access it.
+ *
+ * Also, some registers are similar on different chips but have slightly
+ * different names.  In these cases, one name is chosen to avoid extraneous
+ * #ifdefs.
+ */
+struct ccsr_guts {
+	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
+	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
+	u8	res018[0x20 - 0x18];
+	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
+	u8	res024[0x30 - 0x24];
+	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	u8	res034[0x40 - 0x34];
+	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	u8	res044[0x50 - 0x44];
+	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	u8	res054[0x60 - 0x54];
+	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
+        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
+        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
+        u8	res06c[0x70 - 0x6c];
+	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
+#define CCSR_GUTS_DEVDISR_TB1	0x00001000
+#define CCSR_GUTS_DEVDISR_TB0	0x00004000
+	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
+	u8	res078[0x7c - 0x78];
+	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
+	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
+	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
+	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
+	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
+	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
+	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
+	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
+	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
+	__be32	svr;		/* 0x.00a4 - System Version Register */
+	u8	res0a8[0xb0 - 0xa8];
+	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
+	u8	res0b4[0xc0 - 0xb4];
+	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
+					     Called 'elbcvselcr' on 86xx SOCs */
+	u8	res0c4[0x100 - 0xc4];
+	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
+					     There are 16 registers */
+	u8	res140[0x224 - 0x140];
+	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
+	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
+	u8	res22c[0x604 - 0x22c];
+	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
+	u8	res608[0x800 - 0x608];
+	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
+	u8	res804[0x900 - 0x804];
+	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
+	u8	res904[0x908 - 0x904];
+	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
+	u8	res90c[0x914 - 0x90c];
+	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
+	u8	res918[0xb20 - 0x918];
+	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
+	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
+	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
+	u8	resb2c[0xe00 - 0xb2c];
+	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	u8	rese04[0xe10 - 0xe04];
+	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	u8	rese14[0xe20 - 0xe14];
+	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
+	u8	rese28[0xf04 - 0xe28];
+	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
+	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
+	u8	resf0c[0xf2c - 0xf0c];
+	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
+	u8	resf30[0xf40 - 0xf30];
+	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
+	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
+} __attribute__ ((packed));
+
+
+/* Alternate function signal multiplex control */
+#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
+
+#ifdef CONFIG_PPC_86xx
+
+#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
+#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
+ */
+static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int device)
+{
+	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
+}
+
+#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
+#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
+#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
+#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
+#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
+#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
+#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
+#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
+#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
+#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
+
+/*
+ * Set the DMA external control bits in the GUTS
+ *
+ * The DMA external control bits in the PMUXCR are only meaningful for
+ * channels 0 and 3.  Any other channels are ignored.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * value: the new value for the bit (0 or 1)
+ */
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int value)
+{
+	if ((ch == 0) || (ch == 3)) {
+		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
+
+		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
+	}
+}
+
+#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
+#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
+#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
+	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
+#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
+#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
+#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
+#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
+#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
+
+#endif
+
+#endif
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 9621b91..6f236f1 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -12,11 +12,11 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/fsl/guts.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 71c1a7d..747aab0 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -11,12 +11,12 @@
  */
 
 #include <linux/module.h>
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
index ee29048..1dd49e5 100644
--- a/sound/soc/fsl/p1022_rdk.c
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -18,12 +18,12 @@
  */
 
 #include <linux/module.h>
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 1/5] powerpc/fsl: Move fsl_guts.h out of arch/powerpc
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

Freescale's Layerscape ARM chips use the same structure.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: was patch 2/5

 arch/powerpc/include/asm/fsl_guts.h        | 192 -----------------------------
 arch/powerpc/platforms/85xx/mpc85xx_mds.c  |   2 +-
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c  |   2 +-
 arch/powerpc/platforms/85xx/p1022_ds.c     |   2 +-
 arch/powerpc/platforms/85xx/p1022_rdk.c    |   2 +-
 arch/powerpc/platforms/85xx/smp.c          |   2 +-
 arch/powerpc/platforms/85xx/twr_p102x.c    |   2 +-
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c |   2 +-
 drivers/iommu/fsl_pamu.c                   |   2 +-
 include/linux/fsl/guts.h                   | 192 +++++++++++++++++++++++++++++
 sound/soc/fsl/mpc8610_hpcd.c               |   2 +-
 sound/soc/fsl/p1022_ds.c                   |   2 +-
 sound/soc/fsl/p1022_rdk.c                  |   2 +-
 13 files changed, 203 insertions(+), 203 deletions(-)
 delete mode 100644 arch/powerpc/include/asm/fsl_guts.h
 create mode 100644 include/linux/fsl/guts.h

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
deleted file mode 100644
index 43b6bb1..0000000
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * Freecale 85xx and 86xx Global Utilties register set
- *
- * Authors: Jeff Brown
- *          Timur Tabi <timur@freescale.com>
- *
- * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
- *
- * 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.
- */
-
-#ifndef __ASM_POWERPC_FSL_GUTS_H__
-#define __ASM_POWERPC_FSL_GUTS_H__
-#ifdef __KERNEL__
-
-/**
- * Global Utility Registers.
- *
- * Not all registers defined in this structure are available on all chips, so
- * you are expected to know whether a given register actually exists on your
- * chip before you access it.
- *
- * Also, some registers are similar on different chips but have slightly
- * different names.  In these cases, one name is chosen to avoid extraneous
- * #ifdefs.
- */
-struct ccsr_guts {
-	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
-	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
-	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
-	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
-	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
-	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
-	u8	res018[0x20 - 0x18];
-	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
-	u8	res024[0x30 - 0x24];
-	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
-	u8	res034[0x40 - 0x34];
-	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
-	u8	res044[0x50 - 0x44];
-	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
-	u8	res054[0x60 - 0x54];
-	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
-        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
-        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
-        u8	res06c[0x70 - 0x6c];
-	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
-#define CCSR_GUTS_DEVDISR_TB1	0x00001000
-#define CCSR_GUTS_DEVDISR_TB0	0x00004000
-	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
-	u8	res078[0x7c - 0x78];
-	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
-	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
-	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
-	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
-	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
-	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
-	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
-	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
-	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
-	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
-	__be32	svr;		/* 0x.00a4 - System Version Register */
-	u8	res0a8[0xb0 - 0xa8];
-	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
-	u8	res0b4[0xc0 - 0xb4];
-	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
-					     Called 'elbcvselcr' on 86xx SOCs */
-	u8	res0c4[0x100 - 0xc4];
-	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
-					     There are 16 registers */
-	u8	res140[0x224 - 0x140];
-	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
-	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
-	u8	res22c[0x604 - 0x22c];
-	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
-	u8	res608[0x800 - 0x608];
-	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
-	u8	res804[0x900 - 0x804];
-	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
-	u8	res904[0x908 - 0x904];
-	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
-	u8	res90c[0x914 - 0x90c];
-	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
-	u8	res918[0xb20 - 0x918];
-	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
-	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
-	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
-	u8	resb2c[0xe00 - 0xb2c];
-	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
-	u8	rese04[0xe10 - 0xe04];
-	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
-	u8	rese14[0xe20 - 0xe14];
-	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
-	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
-	u8	rese28[0xf04 - 0xe28];
-	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
-	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
-	u8	resf0c[0xf2c - 0xf0c];
-	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
-	u8	resf30[0xf40 - 0xf30];
-	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
-	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
-} __attribute__ ((packed));
-
-
-/* Alternate function signal multiplex control */
-#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
-
-#ifdef CONFIG_PPC_86xx
-
-#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
-#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
-
-/*
- * Set the DMACR register in the GUTS
- *
- * The DMACR register determines the source of initiated transfers for each
- * channel on each DMA controller.  Rather than have a bunch of repetitive
- * macros for the bit patterns, we just have a function that calculates
- * them.
- *
- * guts: Pointer to GUTS structure
- * co: The DMA controller (0 or 1)
- * ch: The channel on the DMA controller (0, 1, 2, or 3)
- * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
- */
-static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
-	unsigned int co, unsigned int ch, unsigned int device)
-{
-	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
-
-	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
-}
-
-#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
-#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
-#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
-#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
-#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
-#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
-#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
-#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
-#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
-#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
-#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
-#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
-#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
-#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
-#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
-#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
-
-/*
- * Set the DMA external control bits in the GUTS
- *
- * The DMA external control bits in the PMUXCR are only meaningful for
- * channels 0 and 3.  Any other channels are ignored.
- *
- * guts: Pointer to GUTS structure
- * co: The DMA controller (0 or 1)
- * ch: The channel on the DMA controller (0, 1, 2, or 3)
- * value: the new value for the bit (0 or 1)
- */
-static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
-	unsigned int co, unsigned int ch, unsigned int value)
-{
-	if ((ch == 0) || (ch == 3)) {
-		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
-
-		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
-	}
-}
-
-#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
-#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
-#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
-#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
-#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
-#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
-	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
-#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
-#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
-#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
-#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
-#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
-
-#endif
-
-#endif
-#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index a392e94..f0be439 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -34,6 +34,7 @@
 #include <linux/of_device.h>
 #include <linux/phy.h>
 #include <linux/memblock.h>
+#include <linux/fsl/guts.h>
 
 #include <linux/atomic.h>
 #include <asm/time.h>
@@ -51,7 +52,6 @@
 #include <asm/qe_ic.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
-#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index e358bed..50dcc00 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -17,6 +17,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -27,7 +28,6 @@
 #include <asm/mpic.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
-#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 6ac986d3..371df82 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -16,6 +16,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -25,7 +26,6 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
-#include <asm/fsl_guts.h>
 #include <asm/fsl_lbc.h>
 #include "smp.h"
 
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
index 680232d..5087bec 100644
--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -12,6 +12,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -21,7 +22,6 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
-#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index b8b8216..6ac7786 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -19,6 +19,7 @@
 #include <linux/kexec.h>
 #include <linux/highmem.h>
 #include <linux/cpu.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -26,7 +27,6 @@
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
-#include <asm/fsl_guts.h>
 #include <asm/code-patching.h>
 #include <asm/cputhreads.h>
 
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
index 30e002f..892e613 100644
--- a/arch/powerpc/platforms/85xx/twr_p102x.c
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 
@@ -23,7 +24,6 @@
 #include <asm/mpic.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
-#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 55413a5..437a9c3 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -38,7 +39,6 @@
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/simple_gpio.h>
-#include <asm/fsl_guts.h>
 
 #include "mpc86xx.h"
 
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 2570f2a2..a34355f 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -20,11 +20,11 @@
 
 #include "fsl_pamu.h"
 
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
 #include <asm/mpc85xx.h>
-#include <asm/fsl_guts.h>
 
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
new file mode 100644
index 0000000..84d971f
--- /dev/null
+++ b/include/linux/fsl/guts.h
@@ -0,0 +1,192 @@
+/**
+ * Freecale 85xx and 86xx Global Utilties register set
+ *
+ * Authors: Jeff Brown
+ *          Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#ifndef __FSL_GUTS_H__
+#define __FSL_GUTS_H__
+
+#include <linux/types.h>
+
+/**
+ * Global Utility Registers.
+ *
+ * Not all registers defined in this structure are available on all chips, so
+ * you are expected to know whether a given register actually exists on your
+ * chip before you access it.
+ *
+ * Also, some registers are similar on different chips but have slightly
+ * different names.  In these cases, one name is chosen to avoid extraneous
+ * #ifdefs.
+ */
+struct ccsr_guts {
+	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
+	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
+	u8	res018[0x20 - 0x18];
+	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
+	u8	res024[0x30 - 0x24];
+	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	u8	res034[0x40 - 0x34];
+	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	u8	res044[0x50 - 0x44];
+	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	u8	res054[0x60 - 0x54];
+	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
+        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
+        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
+        u8	res06c[0x70 - 0x6c];
+	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
+#define CCSR_GUTS_DEVDISR_TB1	0x00001000
+#define CCSR_GUTS_DEVDISR_TB0	0x00004000
+	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
+	u8	res078[0x7c - 0x78];
+	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
+	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
+	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
+	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
+	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
+	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
+	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
+	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
+	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
+	__be32	svr;		/* 0x.00a4 - System Version Register */
+	u8	res0a8[0xb0 - 0xa8];
+	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
+	u8	res0b4[0xc0 - 0xb4];
+	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
+					     Called 'elbcvselcr' on 86xx SOCs */
+	u8	res0c4[0x100 - 0xc4];
+	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
+					     There are 16 registers */
+	u8	res140[0x224 - 0x140];
+	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
+	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
+	u8	res22c[0x604 - 0x22c];
+	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
+	u8	res608[0x800 - 0x608];
+	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
+	u8	res804[0x900 - 0x804];
+	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
+	u8	res904[0x908 - 0x904];
+	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
+	u8	res90c[0x914 - 0x90c];
+	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
+	u8	res918[0xb20 - 0x918];
+	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
+	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
+	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
+	u8	resb2c[0xe00 - 0xb2c];
+	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	u8	rese04[0xe10 - 0xe04];
+	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	u8	rese14[0xe20 - 0xe14];
+	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
+	u8	rese28[0xf04 - 0xe28];
+	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
+	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
+	u8	resf0c[0xf2c - 0xf0c];
+	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
+	u8	resf30[0xf40 - 0xf30];
+	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
+	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
+} __attribute__ ((packed));
+
+
+/* Alternate function signal multiplex control */
+#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
+
+#ifdef CONFIG_PPC_86xx
+
+#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
+#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
+ */
+static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int device)
+{
+	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
+}
+
+#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
+#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
+#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
+#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
+#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
+#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
+#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
+#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
+#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
+#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
+
+/*
+ * Set the DMA external control bits in the GUTS
+ *
+ * The DMA external control bits in the PMUXCR are only meaningful for
+ * channels 0 and 3.  Any other channels are ignored.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * value: the new value for the bit (0 or 1)
+ */
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int value)
+{
+	if ((ch == 0) || (ch == 3)) {
+		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
+
+		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
+	}
+}
+
+#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
+#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
+#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
+	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
+#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
+#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
+#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
+#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
+#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
+
+#endif
+
+#endif
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 9621b91..6f236f1 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -12,11 +12,11 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/fsl/guts.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 71c1a7d..747aab0 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -11,12 +11,12 @@
  */
 
 #include <linux/module.h>
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
index ee29048..1dd49e5 100644
--- a/sound/soc/fsl/p1022_rdk.c
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -18,12 +18,12 @@
  */
 
 #include <linux/module.h>
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 1/5] powerpc/fsl: Move fsl_guts.h out of arch/powerpc
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

Freescale's Layerscape ARM chips use the same structure.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: was patch 2/5

 arch/powerpc/include/asm/fsl_guts.h        | 192 -----------------------------
 arch/powerpc/platforms/85xx/mpc85xx_mds.c  |   2 +-
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c  |   2 +-
 arch/powerpc/platforms/85xx/p1022_ds.c     |   2 +-
 arch/powerpc/platforms/85xx/p1022_rdk.c    |   2 +-
 arch/powerpc/platforms/85xx/smp.c          |   2 +-
 arch/powerpc/platforms/85xx/twr_p102x.c    |   2 +-
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c |   2 +-
 drivers/iommu/fsl_pamu.c                   |   2 +-
 include/linux/fsl/guts.h                   | 192 +++++++++++++++++++++++++++++
 sound/soc/fsl/mpc8610_hpcd.c               |   2 +-
 sound/soc/fsl/p1022_ds.c                   |   2 +-
 sound/soc/fsl/p1022_rdk.c                  |   2 +-
 13 files changed, 203 insertions(+), 203 deletions(-)
 delete mode 100644 arch/powerpc/include/asm/fsl_guts.h
 create mode 100644 include/linux/fsl/guts.h

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
deleted file mode 100644
index 43b6bb1..0000000
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * Freecale 85xx and 86xx Global Utilties register set
- *
- * Authors: Jeff Brown
- *          Timur Tabi <timur@freescale.com>
- *
- * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
- *
- * 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.
- */
-
-#ifndef __ASM_POWERPC_FSL_GUTS_H__
-#define __ASM_POWERPC_FSL_GUTS_H__
-#ifdef __KERNEL__
-
-/**
- * Global Utility Registers.
- *
- * Not all registers defined in this structure are available on all chips, so
- * you are expected to know whether a given register actually exists on your
- * chip before you access it.
- *
- * Also, some registers are similar on different chips but have slightly
- * different names.  In these cases, one name is chosen to avoid extraneous
- * #ifdefs.
- */
-struct ccsr_guts {
-	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
-	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
-	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
-	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
-	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
-	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
-	u8	res018[0x20 - 0x18];
-	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
-	u8	res024[0x30 - 0x24];
-	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
-	u8	res034[0x40 - 0x34];
-	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
-	u8	res044[0x50 - 0x44];
-	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
-	u8	res054[0x60 - 0x54];
-	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
-        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
-        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
-        u8	res06c[0x70 - 0x6c];
-	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
-#define CCSR_GUTS_DEVDISR_TB1	0x00001000
-#define CCSR_GUTS_DEVDISR_TB0	0x00004000
-	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
-	u8	res078[0x7c - 0x78];
-	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
-	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
-	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
-	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
-	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
-	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
-	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
-	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
-	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
-	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
-	__be32	svr;		/* 0x.00a4 - System Version Register */
-	u8	res0a8[0xb0 - 0xa8];
-	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
-	u8	res0b4[0xc0 - 0xb4];
-	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
-					     Called 'elbcvselcr' on 86xx SOCs */
-	u8	res0c4[0x100 - 0xc4];
-	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
-					     There are 16 registers */
-	u8	res140[0x224 - 0x140];
-	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
-	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
-	u8	res22c[0x604 - 0x22c];
-	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
-	u8	res608[0x800 - 0x608];
-	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
-	u8	res804[0x900 - 0x804];
-	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
-	u8	res904[0x908 - 0x904];
-	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
-	u8	res90c[0x914 - 0x90c];
-	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
-	u8	res918[0xb20 - 0x918];
-	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
-	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
-	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
-	u8	resb2c[0xe00 - 0xb2c];
-	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
-	u8	rese04[0xe10 - 0xe04];
-	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
-	u8	rese14[0xe20 - 0xe14];
-	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
-	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
-	u8	rese28[0xf04 - 0xe28];
-	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
-	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
-	u8	resf0c[0xf2c - 0xf0c];
-	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
-	u8	resf30[0xf40 - 0xf30];
-	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
-	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
-} __attribute__ ((packed));
-
-
-/* Alternate function signal multiplex control */
-#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
-
-#ifdef CONFIG_PPC_86xx
-
-#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
-#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
-
-/*
- * Set the DMACR register in the GUTS
- *
- * The DMACR register determines the source of initiated transfers for each
- * channel on each DMA controller.  Rather than have a bunch of repetitive
- * macros for the bit patterns, we just have a function that calculates
- * them.
- *
- * guts: Pointer to GUTS structure
- * co: The DMA controller (0 or 1)
- * ch: The channel on the DMA controller (0, 1, 2, or 3)
- * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
- */
-static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
-	unsigned int co, unsigned int ch, unsigned int device)
-{
-	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
-
-	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
-}
-
-#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
-#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
-#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
-#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
-#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
-#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
-#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
-#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
-#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
-#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
-#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
-#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
-#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
-#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
-#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
-#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
-
-/*
- * Set the DMA external control bits in the GUTS
- *
- * The DMA external control bits in the PMUXCR are only meaningful for
- * channels 0 and 3.  Any other channels are ignored.
- *
- * guts: Pointer to GUTS structure
- * co: The DMA controller (0 or 1)
- * ch: The channel on the DMA controller (0, 1, 2, or 3)
- * value: the new value for the bit (0 or 1)
- */
-static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
-	unsigned int co, unsigned int ch, unsigned int value)
-{
-	if ((ch == 0) || (ch == 3)) {
-		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
-
-		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
-	}
-}
-
-#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
-#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
-#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
-#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
-#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
-#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
-	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
-#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
-#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
-#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
-#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
-#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
-
-#endif
-
-#endif
-#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index a392e94..f0be439 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -34,6 +34,7 @@
 #include <linux/of_device.h>
 #include <linux/phy.h>
 #include <linux/memblock.h>
+#include <linux/fsl/guts.h>
 
 #include <linux/atomic.h>
 #include <asm/time.h>
@@ -51,7 +52,6 @@
 #include <asm/qe_ic.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
-#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index e358bed..50dcc00 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -17,6 +17,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -27,7 +28,6 @@
 #include <asm/mpic.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
-#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 6ac986d3..371df82 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -16,6 +16,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -25,7 +26,6 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
-#include <asm/fsl_guts.h>
 #include <asm/fsl_lbc.h>
 #include "smp.h"
 
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
index 680232d..5087bec 100644
--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -12,6 +12,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -21,7 +22,6 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
-#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index b8b8216..6ac7786 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -19,6 +19,7 @@
 #include <linux/kexec.h>
 #include <linux/highmem.h>
 #include <linux/cpu.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -26,7 +27,6 @@
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
-#include <asm/fsl_guts.h>
 #include <asm/code-patching.h>
 #include <asm/cputhreads.h>
 
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
index 30e002f..892e613 100644
--- a/arch/powerpc/platforms/85xx/twr_p102x.c
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 
@@ -23,7 +24,6 @@
 #include <asm/mpic.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
-#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 55413a5..437a9c3 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of.h>
+#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -38,7 +39,6 @@
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/simple_gpio.h>
-#include <asm/fsl_guts.h>
 
 #include "mpc86xx.h"
 
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 2570f2a2..a34355f 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -20,11 +20,11 @@
 
 #include "fsl_pamu.h"
 
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
 #include <asm/mpc85xx.h>
-#include <asm/fsl_guts.h>
 
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
new file mode 100644
index 0000000..84d971f
--- /dev/null
+++ b/include/linux/fsl/guts.h
@@ -0,0 +1,192 @@
+/**
+ * Freecale 85xx and 86xx Global Utilties register set
+ *
+ * Authors: Jeff Brown
+ *          Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#ifndef __FSL_GUTS_H__
+#define __FSL_GUTS_H__
+
+#include <linux/types.h>
+
+/**
+ * Global Utility Registers.
+ *
+ * Not all registers defined in this structure are available on all chips, so
+ * you are expected to know whether a given register actually exists on your
+ * chip before you access it.
+ *
+ * Also, some registers are similar on different chips but have slightly
+ * different names.  In these cases, one name is chosen to avoid extraneous
+ * #ifdefs.
+ */
+struct ccsr_guts {
+	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
+	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
+	u8	res018[0x20 - 0x18];
+	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
+	u8	res024[0x30 - 0x24];
+	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	u8	res034[0x40 - 0x34];
+	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	u8	res044[0x50 - 0x44];
+	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	u8	res054[0x60 - 0x54];
+	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
+        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
+        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
+        u8	res06c[0x70 - 0x6c];
+	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
+#define CCSR_GUTS_DEVDISR_TB1	0x00001000
+#define CCSR_GUTS_DEVDISR_TB0	0x00004000
+	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
+	u8	res078[0x7c - 0x78];
+	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
+	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
+	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
+	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
+	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
+	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
+	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
+	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
+	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
+	__be32	svr;		/* 0x.00a4 - System Version Register */
+	u8	res0a8[0xb0 - 0xa8];
+	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
+	u8	res0b4[0xc0 - 0xb4];
+	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
+					     Called 'elbcvselcr' on 86xx SOCs */
+	u8	res0c4[0x100 - 0xc4];
+	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
+					     There are 16 registers */
+	u8	res140[0x224 - 0x140];
+	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
+	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
+	u8	res22c[0x604 - 0x22c];
+	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
+	u8	res608[0x800 - 0x608];
+	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
+	u8	res804[0x900 - 0x804];
+	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
+	u8	res904[0x908 - 0x904];
+	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
+	u8	res90c[0x914 - 0x90c];
+	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
+	u8	res918[0xb20 - 0x918];
+	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
+	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
+	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
+	u8	resb2c[0xe00 - 0xb2c];
+	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	u8	rese04[0xe10 - 0xe04];
+	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	u8	rese14[0xe20 - 0xe14];
+	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
+	u8	rese28[0xf04 - 0xe28];
+	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
+	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
+	u8	resf0c[0xf2c - 0xf0c];
+	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
+	u8	resf30[0xf40 - 0xf30];
+	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
+	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
+} __attribute__ ((packed));
+
+
+/* Alternate function signal multiplex control */
+#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
+
+#ifdef CONFIG_PPC_86xx
+
+#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
+#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
+ */
+static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int device)
+{
+	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
+}
+
+#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
+#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
+#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
+#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
+#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
+#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
+#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
+#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
+#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
+#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
+
+/*
+ * Set the DMA external control bits in the GUTS
+ *
+ * The DMA external control bits in the PMUXCR are only meaningful for
+ * channels 0 and 3.  Any other channels are ignored.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * value: the new value for the bit (0 or 1)
+ */
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int value)
+{
+	if ((ch == 0) || (ch == 3)) {
+		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
+
+		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
+	}
+}
+
+#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
+#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
+#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
+	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
+#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
+#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
+#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
+#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
+#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
+
+#endif
+
+#endif
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 9621b91..6f236f1 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -12,11 +12,11 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/fsl/guts.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 71c1a7d..747aab0 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -11,12 +11,12 @@
  */
 
 #include <linux/module.h>
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
index ee29048..1dd49e5 100644
--- a/sound/soc/fsl/p1022_rdk.c
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -18,12 +18,12 @@
  */
 
 #include <linux/module.h>
+#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 2/5] clk: qoriq: Move chip-specific knowledge into driver
  2015-09-20  4:29 ` Scott Wood
  (?)
@ 2015-09-20  4:29   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

The device tree should describe the chips (or chip-like subblocks) in
the system, but it generally does not describe individual registers --
it should identify, rather than describe, a programming interface.

This has not been the case with the QorIQ clockgen nodes.  The
knowledge of what each bit setting of CLKCnCSR means is encoded in
three places (binding, pll node, and mux node), and the last also needs
to know which options are valid on a particular chip.  All three of
these locations are considered stable ABI, making it difficult to fix
mistakes (of which I have found several), much less refactor the
abstraction to be able to address problems, limitations, or new chips.

Under the current binding, a pll clock specifier of 2 means that the
PLL is divided by 4 -- and the driver implements this, unless there
happen to be four clock-output-names rather than 3, in which case it
interprets it as PLL divided by 3.  This does not appear in the binding
documentation at all.  That hack is now considered stable ABI.

The current device tree nodes contain errors, such as saying that
T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options.
The current binding also ignores some restrictions on clock selection,
such as p5020's requirement that if a core uses the "wrong" PLL, that
PLL must be clocked lower than the "correct" PLL and be at most 80% of
the rated CPU frequency.

Possibly because of the lack of the ability to express such nuance in
the binding, some valid options are omitted from the device trees, such
as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from
PLL1 (again, only if they are at most 80% of rated CPU frequency).
This omission, combined with excessive caution in the cpufreq driver
(addressed in a subsequent patch), means that currently on a 1500 MHz
p4080 with typical PLL configuration, cpufreq can lower the frequency
to 1200 MHz on half the CPUs and do nothing on the others.  With this
patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a
rev3 p4080 half can be lowered to 750 MHz and the other half to 600
MHz.

The current binding only deals with CPU clocks.  To describe FMan in
the device tree, we need to describe its clock.  Some chips have
additional muxes that work like the CPU muxes, but are not described in
the device tree.  Others require inspecting the Reset Control Word to
determine which PLL is used.  Rather than continue to extend this mess,
replace it.  Have the driver bind to the chip-specific clockgen
compatible, and keep the detailed description of quirky chip variations
in the driver, where it can be easily fixed, refactored, and extended.

Older device trees will continue to work (including a workaround for
old ls1021a device trees that are missing compatible and reg in the
clockgen node, which even the old binding required).  The pll/mux
details in old device trees will be ignored, but "clocks" properties
pointing at the old nodes will still work, and be directed at the
corresponding new clock.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v2: was patch 3/5

Added missing initialization of hwc->cg.

 .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
 drivers/clk/clk-qoriq.c                            | 1261 ++++++++++++++++----
 2 files changed, 1090 insertions(+), 232 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
index df4a259..16a3ec4 100644
--- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
+++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
@@ -1,6 +1,6 @@
 * Clock Block on Freescale QorIQ Platforms
 
-Freescale qoriq chips take primary clocking input from the external
+Freescale QorIQ chips take primary clocking input from the external
 SYSCLK signal. The SYSCLK input (frequency) is multiplied using
 multiple phase locked loops (PLL) to create a variety of frequencies
 which can then be passed to a variety of internal logic, including
@@ -13,14 +13,16 @@ which the chip complies.
 Chassis Version		Example Chips
 ---------------		-------------
 1.0			p4080, p5020, p5040
-2.0			t4240, b4860, t1040
+2.0			t4240, b4860
 
 1. Clock Block Binding
 
 Required properties:
-- compatible: Should contain a specific clock block compatible string
-	and a single chassis clock compatible string.
-	Clock block strings include, but not limited to, one of the:
+- compatible: Should contain a chip-specific clock block compatible
+	string and (if applicable) may contain a chassis-version clock
+	compatible string.
+
+	Chip-specific strings are of the form "fsl,<chip>-clockgen", such as:
 	* "fsl,p2041-clockgen"
 	* "fsl,p3041-clockgen"
 	* "fsl,p4080-clockgen"
@@ -30,15 +32,14 @@ Required properties:
 	* "fsl,b4420-clockgen"
 	* "fsl,b4860-clockgen"
 	* "fsl,ls1021a-clockgen"
-	Chassis clock strings include:
+	Chassis-version clock strings include:
 	* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
 	* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
 - reg: Describes the address of the device's resources within the
 	address space defined by its parent bus, and resource zero
 	represents the clock register set
-- clock-frequency: Input system clock frequency
 
-Recommended properties:
+Optional properties:
 - ranges: Allows valid translation between child's address space and
 	parent's. Must be present if the device has sub-nodes.
 - #address-cells: Specifies the number of cells used to represent
@@ -47,8 +48,46 @@ Recommended properties:
 - #size-cells: Specifies the number of cells used to represent
 	the size of an address. Must be present if the device has
 	sub-nodes and set to 1 if present
+- clock-frequency: Input system clock frequency (SYSCLK)
+- clocks: If clock-frequency is not specified, sysclk may be provided
+	as an input clock.  Either clock-frequency or clocks must be
+	provided.
+
+2. Clock Provider
+
+The clockgen node should act as a clock provider, though in older device
+trees the children of the clockgen node are the clock providers.
+
+When the clockgen node is a clock provider, #clock-cells = <2>.
+The first cell of the clock specifier is the clock type, and the
+second cell is the clock index for the specified type.
+
+	Type#	Name		Index Cell
+	0	sysclk		must be 0
+	1	cmux		index (n in CLKCnCSR)
+	2	hwaccel		index (n in CLKCGnHWACSR)
+	3	fman		0 for fm1, 1 for fm2
+	4	platform pll	0=pll, 1=pll/2, 2=pll/3, 3=pll/4
+
+3. Example
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+		clock-frequency = <133333333>;
+		reg = <0xe1000 0x1000>;
+		#clock-cells = <2>;
+	};
+
+	fman@400000 {
+		...
+		clocks = <&clockgen 3 0>;
+		...
+	};
+}
+4. Legacy Child Nodes
 
-2. Clock Provider/Consumer Binding
+NOTE: These nodes are deprecated.  Kernels should continue to support
+device trees with these nodes, but new device trees should not use them.
 
 Most of the bindings are from the common clock binding[1].
  [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -82,7 +121,7 @@ Recommended properties:
 - reg: Should be the offset and length of clock block base address.
 	The length should be 4.
 
-Example for clock block and clock provider:
+Legacy Example:
 / {
 	clockgen: global-utilities@e1000 {
 		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
@@ -142,7 +181,7 @@ Example for clock block and clock provider:
 	};
 };
 
-Example for clock consumer:
+Example for legacy clock consumer:
 
 / {
 	cpu0: PowerPC,e5500@0 {
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index cda90a9..06281a3 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -10,7 +10,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/fsl/guts.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -19,213 +21,934 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
-struct cmux_clk {
+#define PLL_DIV1	0
+#define PLL_DIV2	1
+#define PLL_DIV3	2
+#define PLL_DIV4	3
+
+#define PLATFORM_PLL	0
+#define CGA_PLL1	1
+#define CGA_PLL2	2
+#define CGA_PLL3	3
+#define CGA_PLL4	4	/* only on clockgen-1.0, which lacks CGB */
+#define CGB_PLL1	4
+#define CGB_PLL2	5
+
+struct clockgen_pll_div {
+	struct clk *clk;
+	char name[32];
+};
+
+struct clockgen_pll {
+	struct clockgen_pll_div div[4];
+};
+
+#define CLKSEL_VALID	1
+#define CLKSEL_80PCT	2	/* Only allowed if PLL <= 80% of max cpu freq */
+
+struct clockgen_sourceinfo {
+	u32 flags;	/* CLKSEL_xxx */
+	int pll;	/* CGx_PLLn */
+	int div;	/* PLL_DIVn */
+};
+
+#define NUM_MUX_PARENTS	16
+
+struct clockgen_muxinfo {
+	struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
+};
+
+#define NUM_HWACCEL	5
+#define NUM_CMUX	8
+
+struct clockgen;
+
+/*
+ * cmux freq must be >= platform pll.
+ * If not set, cmux freq must be >= platform pll/2
+ */
+#define CG_CMUX_GE_PLAT		1
+#define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
+
+struct clockgen_chipinfo {
+	const char *compat, *guts_compat;
+	const struct clockgen_muxinfo *cmux_groups[2];
+	const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
+	void (*init_periph)(struct clockgen *cg);
+	int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
+	u32 pll_mask;	/* 1 << n bit set if PLL n is valid */
+	u32 flags;	/* CG_xxx */
+};
+
+struct clockgen {
+	struct device_node *node;
+	void __iomem *regs;
+	struct clockgen_chipinfo info; /* mutable copy */
+	struct clk *sysclk;
+	struct clockgen_pll pll[6];
+	struct clk *cmux[NUM_CMUX];
+	struct clk *hwaccel[NUM_HWACCEL];
+	struct clk *fman[2];
+	struct ccsr_guts __iomem *guts;
+};
+
+static struct clockgen clockgen;
+
+static const struct clockgen_muxinfo p2041_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p2041_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[4] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		[8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+		[9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+		[12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
+		[13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo t1023_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo t1040_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga = {
+	{
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
+	{
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
+	{
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo t1023_hwa1 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t1023_hwa2 = {
+	{
+		[6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo t2080_hwa1 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t2080_hwa2 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa1 = {
+	{
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa4 = {
+	{
+		[2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		[3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+		[4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		[6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa5 = {
+	{
+		[2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+		[3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
+		[4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		[6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		[7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+	},
+};
+
+#define RCWSR7_FM1_CLK_SEL	0x40000000
+#define RCWSR7_FM2_CLK_SEL	0x20000000
+#define RCWSR7_HWA_ASYNC_DIV	0x04000000
+
+static void __init p2041_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p4080_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+	if (reg & RCWSR7_FM2_CLK_SEL)
+		cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+	else
+		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5020_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+	int div = PLL_DIV2;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+	if (reg & RCWSR7_HWA_ASYNC_DIV)
+		div = PLL_DIV4;
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5040_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+	int div = PLL_DIV2;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+	if (reg & RCWSR7_HWA_ASYNC_DIV)
+		div = PLL_DIV4;
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+	if (reg & RCWSR7_FM2_CLK_SEL)
+		cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
+	else
+		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init t1023_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[1];
+}
+
+static void __init t1040_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
+}
+
+static void __init t2080_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[0];
+}
+
+static void __init t4240_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[3];
+	cg->fman[1] = cg->hwaccel[4];
+}
+
+static const struct clockgen_chipinfo chipinfo[] = {
+	{
+		.compat = "fsl,b4420-clockgen",
+		.guts_compat = "fsl,b4860-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t2080_hwa1
+		},
+		.cmux_to_group = {
+			0, 1, 1, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,b4860-clockgen",
+		.guts_compat = "fsl,b4860-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t2080_hwa1
+		},
+		.cmux_to_group = {
+			0, 1, 1, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,ls1021a-clockgen",
+		.cmux_groups = {
+			&t1023_cmux
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x03,
+	},
+	{
+		.compat = "fsl,p2041-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p2041_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p3041-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p2041_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p4080-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p4080_init_periph,
+		.cmux_groups = {
+			&p4080_cmux_grp1, &p4080_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 0, 0, 1, 1, 1, 1
+		},
+		.pll_mask = 0x1f,
+	},
+	{
+		.compat = "fsl,p5020-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p5020_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p5040-clockgen",
+		.guts_compat = "fsl,p5040-device-config",
+		.init_periph = p5040_init_periph,
+		.cmux_groups = {
+			&p5040_cmux_grp1, &p5040_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x0f,
+	},
+	{
+		.compat = "fsl,t1023-clockgen",
+		.guts_compat = "fsl,t1023-device-config",
+		.init_periph = t1023_init_periph,
+		.cmux_groups = {
+			&t1023_cmux
+		},
+		.hwaccel = {
+			&t1023_hwa1, &t1023_hwa2
+		},
+		.cmux_to_group = {
+			0, 0, -1
+		},
+		.pll_mask = 0x03,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t1040-clockgen",
+		.guts_compat = "fsl,t1040-device-config",
+		.init_periph = t1040_init_periph,
+		.cmux_groups = {
+			&t1040_cmux
+		},
+		.cmux_to_group = {
+			0, 0, 0, 0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t2080-clockgen",
+		.guts_compat = "fsl,t2080-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12
+		},
+		.hwaccel = {
+			&t2080_hwa1, &t2080_hwa2
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t4240-clockgen",
+		.guts_compat = "fsl,t4240-device-config",
+		.init_periph = t4240_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
+		},
+		.cmux_to_group = {
+			0, 0, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{},
+};
+
+struct mux_hwclock {
 	struct clk_hw hw;
-	void __iomem *reg;
-	unsigned int clk_per_pll;
-	u32 flags;
+	struct clockgen *cg;
+	const struct clockgen_muxinfo *info;
+	u32 __iomem *reg;
+	u8 parent_to_clksel[NUM_MUX_PARENTS];
+	s8 clksel_to_parent[NUM_MUX_PARENTS];
+	int num_parents;
 };
 
-#define PLL_KILL			BIT(31)
+#define to_mux_hwclock(p)	container_of(p, struct mux_hwclock, hw)
+#define CLKSEL_MASK		0x78000000
 #define	CLKSEL_SHIFT		27
-#define CLKSEL_ADJUST		BIT(0)
-#define to_cmux_clk(p)		container_of(p, struct cmux_clk, hw)
 
-static int cmux_set_parent(struct clk_hw *hw, u8 idx)
+static int mux_set_parent(struct clk_hw *hw, u8 idx)
 {
-	struct cmux_clk *clk = to_cmux_clk(hw);
+	struct mux_hwclock *hwc = to_mux_hwclock(hw);
 	u32 clksel;
 
-	clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll;
-	if (clk->flags & CLKSEL_ADJUST)
-		clksel += 8;
-	clksel = (clksel & 0xf) << CLKSEL_SHIFT;
-	iowrite32be(clksel, clk->reg);
+	if (idx >= hwc->num_parents)
+		return -EINVAL;
+
+	clksel = hwc->parent_to_clksel[idx];
+	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
 
 	return 0;
 }
 
-static u8 cmux_get_parent(struct clk_hw *hw)
+static u8 mux_get_parent(struct clk_hw *hw)
 {
-	struct cmux_clk *clk = to_cmux_clk(hw);
+	struct mux_hwclock *hwc = to_mux_hwclock(hw);
 	u32 clksel;
+	s8 ret;
 
-	clksel = ioread32be(clk->reg);
-	clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
-	if (clk->flags & CLKSEL_ADJUST)
-		clksel -= 8;
-	clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4;
+	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 
-	return clksel;
+	ret = hwc->clksel_to_parent[clksel];
+	if (ret < 0) {
+		pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg);
+		return 0;
+	}
+
+	return ret;
 }
 
 static const struct clk_ops cmux_ops = {
-	.get_parent = cmux_get_parent,
-	.set_parent = cmux_set_parent,
+	.get_parent = mux_get_parent,
+	.set_parent = mux_set_parent,
 };
 
-static void __init core_mux_init(struct device_node *np)
+/*
+ * Don't allow setting for now, as the clock options haven't been
+ * sanitized for additional restrictions.
+ */
+static const struct clk_ops hwaccel_ops = {
+	.get_parent = mux_get_parent,
+};
+
+static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
+						  struct mux_hwclock *hwc,
+						  int idx)
 {
-	struct clk *clk;
-	struct clk_init_data init;
-	struct cmux_clk *cmux_clk;
-	struct device_node *node;
-	int rc, count, i;
-	u32	offset;
-	const char *clk_name;
-	const char **parent_names;
-	struct of_phandle_args clkspec;
+	int pll, div;
 
-	rc = of_property_read_u32(np, "reg", &offset);
-	if (rc) {
-		pr_err("%s: could not get reg property\n", np->name);
-		return;
-	}
+	if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
+		return NULL;
 
-	/* get the input clock source count */
-	count = of_property_count_strings(np, "clock-names");
-	if (count < 0) {
-		pr_err("%s: get clock count error\n", np->name);
-		return;
-	}
-	parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
-	if (!parent_names)
-		return;
+	pll = hwc->info->clksel[idx].pll;
+	div = hwc->info->clksel[idx].div;
 
-	for (i = 0; i < count; i++)
-		parent_names[i] = of_clk_get_parent_name(np, i);
+	return &cg->pll[pll].div[div];
+}
 
-	cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL);
-	if (!cmux_clk)
-		goto err_name;
+static struct clk * __init create_mux_common(struct clockgen *cg,
+					     struct mux_hwclock *hwc,
+					     const struct clk_ops *ops,
+					     unsigned long min_rate,
+					     unsigned long pct80_rate,
+					     const char *fmt, int idx)
+{
+	struct clk_init_data init = {};
+	struct clk *clk;
+	const struct clockgen_pll_div *div;
+	const char *parent_names[NUM_MUX_PARENTS];
+	char name[32];
+	int i, j;
 
-	cmux_clk->reg = of_iomap(np, 0);
-	if (!cmux_clk->reg) {
-		pr_err("%s: could not map register\n", __func__);
-		goto err_clk;
-	}
+	snprintf(name, sizeof(name), fmt, idx);
 
-	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
-					&clkspec);
-	if (rc) {
-		pr_err("%s: parse clock node error\n", __func__);
-		goto err_clk;
-	}
+	for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
+		unsigned long rate;
 
-	cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np,
-			"clock-output-names");
-	of_node_put(clkspec.np);
+		hwc->clksel_to_parent[i] = -1;
 
-	node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
-	if (node && (offset >= 0x80))
-		cmux_clk->flags = CLKSEL_ADJUST;
+		div = get_pll_div(cg, hwc, i);
+		if (!div)
+			continue;
 
-	rc = of_property_read_string_index(np, "clock-output-names",
-					   0, &clk_name);
-	if (rc) {
-		pr_err("%s: read clock names error\n", np->name);
-		goto err_clk;
+		rate = clk_get_rate(div->clk);
+
+		if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
+		    rate > pct80_rate)
+			continue;
+		if (rate < min_rate)
+			continue;
+
+		parent_names[j] = div->name;
+		hwc->parent_to_clksel[j] = i;
+		hwc->clksel_to_parent[i] = j;
+		j++;
 	}
 
-	init.name = clk_name;
-	init.ops = &cmux_ops;
+	init.name = name;
+	init.ops = ops;
 	init.parent_names = parent_names;
-	init.num_parents = count;
+	init.num_parents = hwc->num_parents = j;
 	init.flags = 0;
-	cmux_clk->hw.init = &init;
+	hwc->hw.init = &init;
+	hwc->cg = cg;
 
-	clk = clk_register(NULL, &cmux_clk->hw);
+	clk = clk_register(NULL, &hwc->hw);
 	if (IS_ERR(clk)) {
-		pr_err("%s: could not register clock\n", clk_name);
-		goto err_clk;
+		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+		       PTR_ERR(clk));
+		kfree(hwc);
+		return NULL;
+	}
+
+	return clk;
+}
+
+static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
+{
+	struct mux_hwclock *hwc;
+	const struct clockgen_pll_div *div;
+	unsigned long plat_rate, min_rate;
+	u64 pct80_rate;
+	u32 clksel;
+
+	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+	if (!hwc)
+		return NULL;
+
+	hwc->reg = cg->regs + 0x20 * idx;
+	hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
+
+	/*
+	 * Find the rate for the default clksel, and treat it as the
+	 * maximum rated core frequency.  If this is an incorrect
+	 * assumption, certain clock options (possibly including the
+	 * default clksel) may be inappropriately excluded on certain
+	 * chips.
+	 */
+	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	div = get_pll_div(cg, hwc, clksel);
+	if (!div)
+		return NULL;
+
+	pct80_rate = clk_get_rate(div->clk);
+	pct80_rate *= 8;
+	do_div(pct80_rate, 10);
+
+	plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
+
+	if (cg->info.flags & CG_CMUX_GE_PLAT)
+		min_rate = plat_rate;
+	else
+		min_rate = plat_rate / 2;
+
+	return create_mux_common(cg, hwc, &cmux_ops, min_rate,
+				 pct80_rate, "cg-cmux%d", idx);
+}
+
+static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
+{
+	struct mux_hwclock *hwc;
+
+	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+	if (!hwc)
+		return NULL;
+
+	hwc->reg = cg->regs + 0x20 * idx + 0x10;
+	hwc->info = cg->info.hwaccel[idx];
+
+	return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
+				 "cg-hwaccel%d", idx);
+}
+
+static void __init create_muxes(struct clockgen *cg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
+		if (cg->info.cmux_to_group[i] < 0)
+			break;
+		if (cg->info.cmux_to_group[i] >=
+		    ARRAY_SIZE(cg->info.cmux_groups)) {
+			WARN_ON_ONCE(1);
+			continue;
+		}
+
+		cg->cmux[i] = create_one_cmux(cg, i);
 	}
 
+	for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
+		if (!cg->info.hwaccel[i])
+			continue;
+
+		cg->hwaccel[i] = create_one_hwaccel(cg, i);
+	}
+}
+
+static void __init clockgen_init(struct device_node *np);
+
+/* Legacy nodes may get probed before the parent clockgen node */
+static void __init legacy_init_clockgen(struct device_node *np)
+{
+	if (!clockgen.node)
+		clockgen_init(of_get_parent(np));
+}
+
+/* Legacy node */
+static void __init core_mux_init(struct device_node *np)
+{
+	struct clk *clk;
+	struct resource res;
+	int idx, rc;
+
+	legacy_init_clockgen(np);
+
+	if (of_address_to_resource(np, 0, &res))
+		return;
+
+	idx = (res.start & 0xf0) >> 5;
+	clk = clockgen.cmux[idx];
+
 	rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
 	if (rc) {
-		pr_err("Could not register clock provider for node:%s\n",
-		       np->name);
-		goto err_clk;
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, rc);
+		return;
 	}
-	goto err_name;
+}
 
-err_clk:
-	kfree(cmux_clk);
-err_name:
-	/* free *_names because they are reallocated when registered */
-	kfree(parent_names);
+static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
+{
+	u32 rate;
+
+	if (of_property_read_u32(node, "clock-frequency", &rate))
+		return ERR_PTR(-ENODEV);
+
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
 }
 
-static void __init core_pll_init(struct device_node *np)
+static struct clk *sysclk_from_parent(const char *name)
+{
+	struct clk *clk;
+	const char *parent_name;
+
+	clk = of_clk_get(clockgen.node, 0);
+	if (IS_ERR(clk))
+		return clk;
+
+	/* Register the input clock under the desired name. */
+	parent_name = __clk_get_name(clk);
+	clk = clk_register_fixed_factor(NULL, name, parent_name,
+					0, 1, 1);
+	if (IS_ERR(clk))
+		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+		       PTR_ERR(clk));
+
+	return clk;
+}
+
+static struct clk * __init create_sysclk(const char *name)
+{
+	struct device_node *sysclk;
+	struct clk *clk;
+
+	clk = sysclk_from_fixed(clockgen.node, name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	clk = sysclk_from_parent(name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	sysclk = of_get_child_by_name(clockgen.node, "sysclk");
+	if (sysclk) {
+		clk = sysclk_from_fixed(sysclk, name);
+		if (!IS_ERR(clk))
+			return clk;
+	}
+
+	pr_err("%s: No input clock\n", __func__);
+	return NULL;
+}
+
+/* Legacy node */
+static void __init sysclk_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	legacy_init_clockgen(node);
+
+	clk = clockgen.sysclk;
+	if (clk)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+#define PLL_KILL BIT(31)
+
+static void __init create_one_pll(struct clockgen *cg, int idx)
 {
+	u32 __iomem *reg;
 	u32 mult;
-	int i, rc, count;
-	const char *clk_name, *parent_name;
-	struct clk_onecell_data *onecell_data;
-	struct clk      **subclks;
-	void __iomem *base;
+	struct clockgen_pll *pll = &cg->pll[idx];
+	int i;
 
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("iomap error\n");
+	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
-	}
 
-	/* get the multiple of PLL */
-	mult = ioread32be(base);
+	if (idx == PLATFORM_PLL)
+		reg = cg->regs + 0xc00;
+	else
+		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
 
-	/* check if this PLL is disabled */
+	/* Get the multiple of PLL */
+	mult = ioread32be(reg);
+
+	/* Check if this PLL is disabled */
 	if (mult & PLL_KILL) {
-		pr_debug("PLL:%s is disabled\n", np->name);
-		goto err_map;
+		pr_debug("%s(): pll %p disabled\n", __func__, reg);
+		return;
 	}
-	mult = (mult >> 1) & 0x3f;
 
-	parent_name = of_clk_get_parent_name(np, 0);
-	if (!parent_name) {
-		pr_err("PLL: %s must have a parent\n", np->name);
-		goto err_map;
+	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
+		mult = (mult & GENMASK(8, 1)) >> 1;
+	else
+		mult = (mult & GENMASK(6, 1)) >> 1;
+
+	for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
+		struct clk *clk;
+
+		snprintf(pll->div[i].name, sizeof(pll->div[i].name),
+			 "cg-pll%d-div%d", idx, i + 1);
+
+		clk = clk_register_fixed_factor(NULL,
+				pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
+		if (IS_ERR(clk)) {
+			pr_err("%s: %s: register failed %ld\n",
+			       __func__, pll->div[i].name, PTR_ERR(clk));
+			continue;
+		}
+
+		pll->div[i].clk = clk;
 	}
+}
+
+static void __init create_plls(struct clockgen *cg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
+		create_one_pll(cg, i);
+}
 
+static void __init legacy_pll_init(struct device_node *np, int idx)
+{
+	struct clockgen_pll *pll;
+	struct clk_onecell_data *onecell_data;
+	struct clk **subclks;
+	int count, rc;
+
+	legacy_init_clockgen(np);
+
+	pll = &clockgen.pll[idx];
 	count = of_property_count_strings(np, "clock-output-names");
-	if (count < 0 || count > 4) {
-		pr_err("%s: clock is not supported\n", np->name);
-		goto err_map;
-	}
 
-	subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
+	BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
+	subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
 	if (!subclks)
-		goto err_map;
+		return;
 
 	onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
 	if (!onecell_data)
 		goto err_clks;
 
-	for (i = 0; i < count; i++) {
-		rc = of_property_read_string_index(np, "clock-output-names",
-						   i, &clk_name);
-		if (rc) {
-			pr_err("%s: could not get clock names\n", np->name);
-			goto err_cell;
-		}
-
-		/*
-		 * when count == 4, there are 4 output clocks:
-		 * /1, /2, /3, /4 respectively
-		 * when count < 4, there are at least 2 output clocks:
-		 * /1, /2, (/4, if count == 3) respectively.
-		 */
-		if (count == 4)
-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
-					parent_name, 0, mult, 1 + i);
-		else
-
-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
-					parent_name, 0, mult, 1 << i);
-
-		if (IS_ERR(subclks[i])) {
-			pr_err("%s: could not register clock\n", clk_name);
-			goto err_cell;
-		}
+	if (count <= 3) {
+		subclks[0] = pll->div[0].clk;
+		subclks[1] = pll->div[1].clk;
+		subclks[2] = pll->div[3].clk;
+	} else {
+		subclks[0] = pll->div[0].clk;
+		subclks[1] = pll->div[1].clk;
+		subclks[2] = pll->div[2].clk;
+		subclks[3] = pll->div[3].clk;
 	}
 
 	onecell_data->clks = subclks;
@@ -233,125 +956,221 @@ static void __init core_pll_init(struct device_node *np)
 
 	rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
 	if (rc) {
-		pr_err("Could not register clk provider for node:%s\n",
-		       np->name);
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, rc);
 		goto err_cell;
 	}
 
-	iounmap(base);
 	return;
 err_cell:
 	kfree(onecell_data);
 err_clks:
 	kfree(subclks);
-err_map:
-	iounmap(base);
 }
 
-static void __init sysclk_init(struct device_node *node)
+/* Legacy node */
+static void __init pltfrm_pll_init(struct device_node *np)
 {
-	struct clk *clk;
-	const char *clk_name = node->name;
-	struct device_node *np = of_get_parent(node);
-	u32 rate;
+	legacy_pll_init(np, PLATFORM_PLL);
+}
 
-	if (!np) {
-		pr_err("could not get parent node\n");
+/* Legacy node */
+static void __init core_pll_init(struct device_node *np)
+{
+	struct resource res;
+	int idx;
+
+	if (of_address_to_resource(np, 0, &res))
 		return;
+
+	if ((res.start & 0xfff) == 0xc00) {
+		/*
+		 * ls1021a devtree labels the platform PLL
+		 * with the core PLL compatible
+		 */
+		pltfrm_pll_init(np);
+	} else {
+		idx = (res.start & 0xf0) >> 5;
+		legacy_pll_init(np, CGA_PLL1 + idx);
 	}
+}
 
-	if (of_property_read_u32(np, "clock-frequency", &rate)) {
-		of_node_put(node);
-		return;
+static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clockgen *cg = data;
+	struct clk *clk;
+	struct clockgen_pll *pll;
+	u32 type, idx;
+
+	if (clkspec->args_count < 2) {
+		pr_err("%s: insufficient phandle args\n", __func__);
+		return ERR_PTR(-EINVAL);
 	}
 
-	of_property_read_string(np, "clock-output-names", &clk_name);
+	type = clkspec->args[0];
+	idx = clkspec->args[1];
 
-	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
-	if (!IS_ERR(clk))
-		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	switch (type) {
+	case 0:
+		if (idx != 0)
+			goto bad_args;
+		clk = cg->sysclk;
+		break;
+	case 1:
+		if (idx >= ARRAY_SIZE(cg->cmux))
+			goto bad_args;
+		clk = cg->cmux[idx];
+		break;
+	case 2:
+		if (idx >= ARRAY_SIZE(cg->hwaccel))
+			goto bad_args;
+		clk = cg->hwaccel[idx];
+		break;
+	case 3:
+		if (idx >= ARRAY_SIZE(cg->fman))
+			goto bad_args;
+		clk = cg->fman[idx];
+		break;
+	case 4:
+		pll = &cg->pll[PLATFORM_PLL];
+		if (idx >= ARRAY_SIZE(pll->div))
+			goto bad_args;
+		clk = pll->div[idx].clk;
+		break;
+	default:
+		goto bad_args;
+	}
+
+	if (!clk)
+		return ERR_PTR(-ENOENT);
+	return clk;
+
+bad_args:
+	pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx);
+	return ERR_PTR(-EINVAL);
 }
 
-static void __init pltfrm_pll_init(struct device_node *np)
+#ifdef CONFIG_PPC
+#include <asm/mpc85xx.h>
+
+static const u32 a4510_svrs[] __initconst = {
+	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
+	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
+	(SVR_P2041 << 8) | 0x10,	/* P2041 1.0 */
+	(SVR_P2041 << 8) | 0x11,	/* P2041 1.1 */
+	(SVR_P3041 << 8) | 0x10,	/* P3041 1.0 */
+	(SVR_P3041 << 8) | 0x11,	/* P3041 1.1 */
+	(SVR_P4040 << 8) | 0x20,	/* P4040 2.0 */
+	(SVR_P4080 << 8) | 0x20,	/* P4080 2.0 */
+	(SVR_P5010 << 8) | 0x10,	/* P5010 1.0 */
+	(SVR_P5010 << 8) | 0x20,	/* P5010 2.0 */
+	(SVR_P5020 << 8) | 0x10,	/* P5020 1.0 */
+	(SVR_P5021 << 8) | 0x10,	/* P5021 1.0 */
+	(SVR_P5040 << 8) | 0x10,	/* P5040 1.0 */
+};
+
+#define SVR_SECURITY	0x80000	/* The Security (E) bit */
+
+static bool __init has_erratum_a4510(void)
 {
-	void __iomem *base;
-	uint32_t mult;
-	const char *parent_name, *clk_name;
-	int i, _errno;
-	struct clk_onecell_data *cod;
-
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
-		return;
+	u32 svr = mfspr(SPRN_SVR);
+	int i;
+
+	svr &= ~SVR_SECURITY;
+
+	for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
+		if (svr == a4510_svrs[i])
+			return true;
 	}
 
-	/* Get the multiple of PLL */
-	mult = ioread32be(base);
+	return false;
+}
+#else
+static bool __init has_erratum_a4510(void)
+{
+	return false;
+}
+#endif
 
-	iounmap(base);
+static void __init clockgen_init(struct device_node *np)
+{
+	int i, ret;
+	bool is_old_ls1021a = false;
 
-	/* Check if this PLL is disabled */
-	if (mult & PLL_KILL) {
-		pr_debug("%s(): %s: Disabled\n", __func__, np->name);
+	/* May have already been called by a legacy probe */
+	if (clockgen.node)
 		return;
-	}
-	mult = (mult & GENMASK(6, 1)) >> 1;
 
-	parent_name = of_clk_get_parent_name(np, 0);
-	if (!parent_name) {
-		pr_err("%s(): %s: of_clk_get_parent_name() failed\n",
-		       __func__, np->name);
+	clockgen.node = np;
+	clockgen.regs = of_iomap(np, 0);
+	if (!clockgen.regs &&
+	    of_device_is_compatible(of_root, "fsl,ls1021a")) {
+		/* Compatibility hack for old, broken device trees */
+		clockgen.regs = ioremap(0x1ee1000, 0x1000);
+		is_old_ls1021a = true;
+	}
+	if (!clockgen.regs) {
+		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
 		return;
 	}
 
-	i = of_property_count_strings(np, "clock-output-names");
-	if (i < 0) {
-		pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n",
-		       __func__, np->name, i);
-		return;
+	for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
+		if (of_device_is_compatible(np, chipinfo[i].compat))
+			break;
+		if (is_old_ls1021a &&
+		    !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
+			break;
 	}
 
-	cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL);
-	if (!cod)
-		return;
-	cod->clks = (struct clk **)(cod + 1);
-	cod->clk_num = i;
-
-	for (i = 0; i < cod->clk_num; i++) {
-		_errno = of_property_read_string_index(np, "clock-output-names",
-						       i, &clk_name);
-		if (_errno < 0) {
-			pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n",
-			       __func__, np->name, _errno);
-			goto return_clk_unregister;
-		}
+	if (i == ARRAY_SIZE(chipinfo)) {
+		pr_err("%s: unknown clockgen node %s\n", __func__,
+		       np->full_name);
+		goto err;
+	}
+	clockgen.info = chipinfo[i];
+
+	if (clockgen.info.guts_compat) {
+		struct device_node *guts;
 
-		cod->clks[i] = clk_register_fixed_factor(NULL, clk_name,
-					       parent_name, 0, mult, 1 + i);
-		if (IS_ERR(cod->clks[i])) {
-			pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n",
-			       __func__, np->name,
-			       clk_name, PTR_ERR(cod->clks[i]));
-			goto return_clk_unregister;
+		guts = of_find_compatible_node(NULL, NULL,
+					       clockgen.info.guts_compat);
+		if (guts) {
+			clockgen.guts = of_iomap(guts, 0);
+			if (!clockgen.guts) {
+				pr_err("%s: Couldn't map %s regs\n", __func__,
+				       guts->full_name);
+			}
 		}
+
 	}
 
-	_errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod);
-	if (_errno < 0) {
-		pr_err("%s(): %s: of_clk_add_provider() = %d\n",
-		       __func__, np->name, _errno);
-		goto return_clk_unregister;
+	if (has_erratum_a4510())
+		clockgen.info.flags |= CG_CMUX_GE_PLAT;
+
+	clockgen.sysclk = create_sysclk("cg-sysclk");
+	create_plls(&clockgen);
+	create_muxes(&clockgen);
+
+	if (clockgen.info.init_periph)
+		clockgen.info.init_periph(&clockgen);
+
+	ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
+	if (ret) {
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, ret);
 	}
 
 	return;
-
-return_clk_unregister:
-	while (--i >= 0)
-		clk_unregister(cod->clks[i]);
-	kfree(cod);
+err:
+	iounmap(clockgen.regs);
+	clockgen.regs = NULL;
 }
 
+CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+
+/* Legacy nodes */
 CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
 CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
 CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 2/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

The device tree should describe the chips (or chip-like subblocks) in
the system, but it generally does not describe individual registers --
it should identify, rather than describe, a programming interface.

This has not been the case with the QorIQ clockgen nodes.  The
knowledge of what each bit setting of CLKCnCSR means is encoded in
three places (binding, pll node, and mux node), and the last also needs
to know which options are valid on a particular chip.  All three of
these locations are considered stable ABI, making it difficult to fix
mistakes (of which I have found several), much less refactor the
abstraction to be able to address problems, limitations, or new chips.

Under the current binding, a pll clock specifier of 2 means that the
PLL is divided by 4 -- and the driver implements this, unless there
happen to be four clock-output-names rather than 3, in which case it
interprets it as PLL divided by 3.  This does not appear in the binding
documentation at all.  That hack is now considered stable ABI.

The current device tree nodes contain errors, such as saying that
T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options.
The current binding also ignores some restrictions on clock selection,
such as p5020's requirement that if a core uses the "wrong" PLL, that
PLL must be clocked lower than the "correct" PLL and be at most 80% of
the rated CPU frequency.

Possibly because of the lack of the ability to express such nuance in
the binding, some valid options are omitted from the device trees, such
as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from
PLL1 (again, only if they are at most 80% of rated CPU frequency).
This omission, combined with excessive caution in the cpufreq driver
(addressed in a subsequent patch), means that currently on a 1500 MHz
p4080 with typical PLL configuration, cpufreq can lower the frequency
to 1200 MHz on half the CPUs and do nothing on the others.  With this
patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a
rev3 p4080 half can be lowered to 750 MHz and the other half to 600
MHz.

The current binding only deals with CPU clocks.  To describe FMan in
the device tree, we need to describe its clock.  Some chips have
additional muxes that work like the CPU muxes, but are not described in
the device tree.  Others require inspecting the Reset Control Word to
determine which PLL is used.  Rather than continue to extend this mess,
replace it.  Have the driver bind to the chip-specific clockgen
compatible, and keep the detailed description of quirky chip variations
in the driver, where it can be easily fixed, refactored, and extended.

Older device trees will continue to work (including a workaround for
old ls1021a device trees that are missing compatible and reg in the
clockgen node, which even the old binding required).  The pll/mux
details in old device trees will be ignored, but "clocks" properties
pointing at the old nodes will still work, and be directed at the
corresponding new clock.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v2: was patch 3/5

Added missing initialization of hwc->cg.

 .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
 drivers/clk/clk-qoriq.c                            | 1261 ++++++++++++++++----
 2 files changed, 1090 insertions(+), 232 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
index df4a259..16a3ec4 100644
--- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
+++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
@@ -1,6 +1,6 @@
 * Clock Block on Freescale QorIQ Platforms
 
-Freescale qoriq chips take primary clocking input from the external
+Freescale QorIQ chips take primary clocking input from the external
 SYSCLK signal. The SYSCLK input (frequency) is multiplied using
 multiple phase locked loops (PLL) to create a variety of frequencies
 which can then be passed to a variety of internal logic, including
@@ -13,14 +13,16 @@ which the chip complies.
 Chassis Version		Example Chips
 ---------------		-------------
 1.0			p4080, p5020, p5040
-2.0			t4240, b4860, t1040
+2.0			t4240, b4860
 
 1. Clock Block Binding
 
 Required properties:
-- compatible: Should contain a specific clock block compatible string
-	and a single chassis clock compatible string.
-	Clock block strings include, but not limited to, one of the:
+- compatible: Should contain a chip-specific clock block compatible
+	string and (if applicable) may contain a chassis-version clock
+	compatible string.
+
+	Chip-specific strings are of the form "fsl,<chip>-clockgen", such as:
 	* "fsl,p2041-clockgen"
 	* "fsl,p3041-clockgen"
 	* "fsl,p4080-clockgen"
@@ -30,15 +32,14 @@ Required properties:
 	* "fsl,b4420-clockgen"
 	* "fsl,b4860-clockgen"
 	* "fsl,ls1021a-clockgen"
-	Chassis clock strings include:
+	Chassis-version clock strings include:
 	* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
 	* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
 - reg: Describes the address of the device's resources within the
 	address space defined by its parent bus, and resource zero
 	represents the clock register set
-- clock-frequency: Input system clock frequency
 
-Recommended properties:
+Optional properties:
 - ranges: Allows valid translation between child's address space and
 	parent's. Must be present if the device has sub-nodes.
 - #address-cells: Specifies the number of cells used to represent
@@ -47,8 +48,46 @@ Recommended properties:
 - #size-cells: Specifies the number of cells used to represent
 	the size of an address. Must be present if the device has
 	sub-nodes and set to 1 if present
+- clock-frequency: Input system clock frequency (SYSCLK)
+- clocks: If clock-frequency is not specified, sysclk may be provided
+	as an input clock.  Either clock-frequency or clocks must be
+	provided.
+
+2. Clock Provider
+
+The clockgen node should act as a clock provider, though in older device
+trees the children of the clockgen node are the clock providers.
+
+When the clockgen node is a clock provider, #clock-cells = <2>.
+The first cell of the clock specifier is the clock type, and the
+second cell is the clock index for the specified type.
+
+	Type#	Name		Index Cell
+	0	sysclk		must be 0
+	1	cmux		index (n in CLKCnCSR)
+	2	hwaccel		index (n in CLKCGnHWACSR)
+	3	fman		0 for fm1, 1 for fm2
+	4	platform pll	0=pll, 1=pll/2, 2=pll/3, 3=pll/4
+
+3. Example
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+		clock-frequency = <133333333>;
+		reg = <0xe1000 0x1000>;
+		#clock-cells = <2>;
+	};
+
+	fman@400000 {
+		...
+		clocks = <&clockgen 3 0>;
+		...
+	};
+}
+4. Legacy Child Nodes
 
-2. Clock Provider/Consumer Binding
+NOTE: These nodes are deprecated.  Kernels should continue to support
+device trees with these nodes, but new device trees should not use them.
 
 Most of the bindings are from the common clock binding[1].
  [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -82,7 +121,7 @@ Recommended properties:
 - reg: Should be the offset and length of clock block base address.
 	The length should be 4.
 
-Example for clock block and clock provider:
+Legacy Example:
 / {
 	clockgen: global-utilities@e1000 {
 		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
@@ -142,7 +181,7 @@ Example for clock block and clock provider:
 	};
 };
 
-Example for clock consumer:
+Example for legacy clock consumer:
 
 / {
 	cpu0: PowerPC,e5500@0 {
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index cda90a9..06281a3 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -10,7 +10,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/fsl/guts.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -19,213 +21,934 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
-struct cmux_clk {
+#define PLL_DIV1	0
+#define PLL_DIV2	1
+#define PLL_DIV3	2
+#define PLL_DIV4	3
+
+#define PLATFORM_PLL	0
+#define CGA_PLL1	1
+#define CGA_PLL2	2
+#define CGA_PLL3	3
+#define CGA_PLL4	4	/* only on clockgen-1.0, which lacks CGB */
+#define CGB_PLL1	4
+#define CGB_PLL2	5
+
+struct clockgen_pll_div {
+	struct clk *clk;
+	char name[32];
+};
+
+struct clockgen_pll {
+	struct clockgen_pll_div div[4];
+};
+
+#define CLKSEL_VALID	1
+#define CLKSEL_80PCT	2	/* Only allowed if PLL <= 80% of max cpu freq */
+
+struct clockgen_sourceinfo {
+	u32 flags;	/* CLKSEL_xxx */
+	int pll;	/* CGx_PLLn */
+	int div;	/* PLL_DIVn */
+};
+
+#define NUM_MUX_PARENTS	16
+
+struct clockgen_muxinfo {
+	struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
+};
+
+#define NUM_HWACCEL	5
+#define NUM_CMUX	8
+
+struct clockgen;
+
+/*
+ * cmux freq must be >= platform pll.
+ * If not set, cmux freq must be >= platform pll/2
+ */
+#define CG_CMUX_GE_PLAT		1
+#define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
+
+struct clockgen_chipinfo {
+	const char *compat, *guts_compat;
+	const struct clockgen_muxinfo *cmux_groups[2];
+	const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
+	void (*init_periph)(struct clockgen *cg);
+	int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
+	u32 pll_mask;	/* 1 << n bit set if PLL n is valid */
+	u32 flags;	/* CG_xxx */
+};
+
+struct clockgen {
+	struct device_node *node;
+	void __iomem *regs;
+	struct clockgen_chipinfo info; /* mutable copy */
+	struct clk *sysclk;
+	struct clockgen_pll pll[6];
+	struct clk *cmux[NUM_CMUX];
+	struct clk *hwaccel[NUM_HWACCEL];
+	struct clk *fman[2];
+	struct ccsr_guts __iomem *guts;
+};
+
+static struct clockgen clockgen;
+
+static const struct clockgen_muxinfo p2041_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p2041_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[4] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		[8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+		[9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+		[12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
+		[13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo t1023_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo t1040_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga = {
+	{
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
+	{
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
+	{
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo t1023_hwa1 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t1023_hwa2 = {
+	{
+		[6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo t2080_hwa1 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t2080_hwa2 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa1 = {
+	{
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa4 = {
+	{
+		[2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		[3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+		[4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		[6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa5 = {
+	{
+		[2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+		[3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
+		[4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		[6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		[7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+	},
+};
+
+#define RCWSR7_FM1_CLK_SEL	0x40000000
+#define RCWSR7_FM2_CLK_SEL	0x20000000
+#define RCWSR7_HWA_ASYNC_DIV	0x04000000
+
+static void __init p2041_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p4080_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+	if (reg & RCWSR7_FM2_CLK_SEL)
+		cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+	else
+		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5020_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+	int div = PLL_DIV2;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+	if (reg & RCWSR7_HWA_ASYNC_DIV)
+		div = PLL_DIV4;
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5040_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+	int div = PLL_DIV2;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+	if (reg & RCWSR7_HWA_ASYNC_DIV)
+		div = PLL_DIV4;
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+	if (reg & RCWSR7_FM2_CLK_SEL)
+		cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
+	else
+		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init t1023_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[1];
+}
+
+static void __init t1040_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
+}
+
+static void __init t2080_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[0];
+}
+
+static void __init t4240_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[3];
+	cg->fman[1] = cg->hwaccel[4];
+}
+
+static const struct clockgen_chipinfo chipinfo[] = {
+	{
+		.compat = "fsl,b4420-clockgen",
+		.guts_compat = "fsl,b4860-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t2080_hwa1
+		},
+		.cmux_to_group = {
+			0, 1, 1, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,b4860-clockgen",
+		.guts_compat = "fsl,b4860-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t2080_hwa1
+		},
+		.cmux_to_group = {
+			0, 1, 1, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,ls1021a-clockgen",
+		.cmux_groups = {
+			&t1023_cmux
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x03,
+	},
+	{
+		.compat = "fsl,p2041-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p2041_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p3041-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p2041_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p4080-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p4080_init_periph,
+		.cmux_groups = {
+			&p4080_cmux_grp1, &p4080_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 0, 0, 1, 1, 1, 1
+		},
+		.pll_mask = 0x1f,
+	},
+	{
+		.compat = "fsl,p5020-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p5020_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p5040-clockgen",
+		.guts_compat = "fsl,p5040-device-config",
+		.init_periph = p5040_init_periph,
+		.cmux_groups = {
+			&p5040_cmux_grp1, &p5040_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x0f,
+	},
+	{
+		.compat = "fsl,t1023-clockgen",
+		.guts_compat = "fsl,t1023-device-config",
+		.init_periph = t1023_init_periph,
+		.cmux_groups = {
+			&t1023_cmux
+		},
+		.hwaccel = {
+			&t1023_hwa1, &t1023_hwa2
+		},
+		.cmux_to_group = {
+			0, 0, -1
+		},
+		.pll_mask = 0x03,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t1040-clockgen",
+		.guts_compat = "fsl,t1040-device-config",
+		.init_periph = t1040_init_periph,
+		.cmux_groups = {
+			&t1040_cmux
+		},
+		.cmux_to_group = {
+			0, 0, 0, 0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t2080-clockgen",
+		.guts_compat = "fsl,t2080-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12
+		},
+		.hwaccel = {
+			&t2080_hwa1, &t2080_hwa2
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t4240-clockgen",
+		.guts_compat = "fsl,t4240-device-config",
+		.init_periph = t4240_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
+		},
+		.cmux_to_group = {
+			0, 0, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{},
+};
+
+struct mux_hwclock {
 	struct clk_hw hw;
-	void __iomem *reg;
-	unsigned int clk_per_pll;
-	u32 flags;
+	struct clockgen *cg;
+	const struct clockgen_muxinfo *info;
+	u32 __iomem *reg;
+	u8 parent_to_clksel[NUM_MUX_PARENTS];
+	s8 clksel_to_parent[NUM_MUX_PARENTS];
+	int num_parents;
 };
 
-#define PLL_KILL			BIT(31)
+#define to_mux_hwclock(p)	container_of(p, struct mux_hwclock, hw)
+#define CLKSEL_MASK		0x78000000
 #define	CLKSEL_SHIFT		27
-#define CLKSEL_ADJUST		BIT(0)
-#define to_cmux_clk(p)		container_of(p, struct cmux_clk, hw)
 
-static int cmux_set_parent(struct clk_hw *hw, u8 idx)
+static int mux_set_parent(struct clk_hw *hw, u8 idx)
 {
-	struct cmux_clk *clk = to_cmux_clk(hw);
+	struct mux_hwclock *hwc = to_mux_hwclock(hw);
 	u32 clksel;
 
-	clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll;
-	if (clk->flags & CLKSEL_ADJUST)
-		clksel += 8;
-	clksel = (clksel & 0xf) << CLKSEL_SHIFT;
-	iowrite32be(clksel, clk->reg);
+	if (idx >= hwc->num_parents)
+		return -EINVAL;
+
+	clksel = hwc->parent_to_clksel[idx];
+	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
 
 	return 0;
 }
 
-static u8 cmux_get_parent(struct clk_hw *hw)
+static u8 mux_get_parent(struct clk_hw *hw)
 {
-	struct cmux_clk *clk = to_cmux_clk(hw);
+	struct mux_hwclock *hwc = to_mux_hwclock(hw);
 	u32 clksel;
+	s8 ret;
 
-	clksel = ioread32be(clk->reg);
-	clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
-	if (clk->flags & CLKSEL_ADJUST)
-		clksel -= 8;
-	clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4;
+	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 
-	return clksel;
+	ret = hwc->clksel_to_parent[clksel];
+	if (ret < 0) {
+		pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg);
+		return 0;
+	}
+
+	return ret;
 }
 
 static const struct clk_ops cmux_ops = {
-	.get_parent = cmux_get_parent,
-	.set_parent = cmux_set_parent,
+	.get_parent = mux_get_parent,
+	.set_parent = mux_set_parent,
 };
 
-static void __init core_mux_init(struct device_node *np)
+/*
+ * Don't allow setting for now, as the clock options haven't been
+ * sanitized for additional restrictions.
+ */
+static const struct clk_ops hwaccel_ops = {
+	.get_parent = mux_get_parent,
+};
+
+static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
+						  struct mux_hwclock *hwc,
+						  int idx)
 {
-	struct clk *clk;
-	struct clk_init_data init;
-	struct cmux_clk *cmux_clk;
-	struct device_node *node;
-	int rc, count, i;
-	u32	offset;
-	const char *clk_name;
-	const char **parent_names;
-	struct of_phandle_args clkspec;
+	int pll, div;
 
-	rc = of_property_read_u32(np, "reg", &offset);
-	if (rc) {
-		pr_err("%s: could not get reg property\n", np->name);
-		return;
-	}
+	if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
+		return NULL;
 
-	/* get the input clock source count */
-	count = of_property_count_strings(np, "clock-names");
-	if (count < 0) {
-		pr_err("%s: get clock count error\n", np->name);
-		return;
-	}
-	parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
-	if (!parent_names)
-		return;
+	pll = hwc->info->clksel[idx].pll;
+	div = hwc->info->clksel[idx].div;
 
-	for (i = 0; i < count; i++)
-		parent_names[i] = of_clk_get_parent_name(np, i);
+	return &cg->pll[pll].div[div];
+}
 
-	cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL);
-	if (!cmux_clk)
-		goto err_name;
+static struct clk * __init create_mux_common(struct clockgen *cg,
+					     struct mux_hwclock *hwc,
+					     const struct clk_ops *ops,
+					     unsigned long min_rate,
+					     unsigned long pct80_rate,
+					     const char *fmt, int idx)
+{
+	struct clk_init_data init = {};
+	struct clk *clk;
+	const struct clockgen_pll_div *div;
+	const char *parent_names[NUM_MUX_PARENTS];
+	char name[32];
+	int i, j;
 
-	cmux_clk->reg = of_iomap(np, 0);
-	if (!cmux_clk->reg) {
-		pr_err("%s: could not map register\n", __func__);
-		goto err_clk;
-	}
+	snprintf(name, sizeof(name), fmt, idx);
 
-	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
-					&clkspec);
-	if (rc) {
-		pr_err("%s: parse clock node error\n", __func__);
-		goto err_clk;
-	}
+	for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
+		unsigned long rate;
 
-	cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np,
-			"clock-output-names");
-	of_node_put(clkspec.np);
+		hwc->clksel_to_parent[i] = -1;
 
-	node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
-	if (node && (offset >= 0x80))
-		cmux_clk->flags = CLKSEL_ADJUST;
+		div = get_pll_div(cg, hwc, i);
+		if (!div)
+			continue;
 
-	rc = of_property_read_string_index(np, "clock-output-names",
-					   0, &clk_name);
-	if (rc) {
-		pr_err("%s: read clock names error\n", np->name);
-		goto err_clk;
+		rate = clk_get_rate(div->clk);
+
+		if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
+		    rate > pct80_rate)
+			continue;
+		if (rate < min_rate)
+			continue;
+
+		parent_names[j] = div->name;
+		hwc->parent_to_clksel[j] = i;
+		hwc->clksel_to_parent[i] = j;
+		j++;
 	}
 
-	init.name = clk_name;
-	init.ops = &cmux_ops;
+	init.name = name;
+	init.ops = ops;
 	init.parent_names = parent_names;
-	init.num_parents = count;
+	init.num_parents = hwc->num_parents = j;
 	init.flags = 0;
-	cmux_clk->hw.init = &init;
+	hwc->hw.init = &init;
+	hwc->cg = cg;
 
-	clk = clk_register(NULL, &cmux_clk->hw);
+	clk = clk_register(NULL, &hwc->hw);
 	if (IS_ERR(clk)) {
-		pr_err("%s: could not register clock\n", clk_name);
-		goto err_clk;
+		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+		       PTR_ERR(clk));
+		kfree(hwc);
+		return NULL;
+	}
+
+	return clk;
+}
+
+static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
+{
+	struct mux_hwclock *hwc;
+	const struct clockgen_pll_div *div;
+	unsigned long plat_rate, min_rate;
+	u64 pct80_rate;
+	u32 clksel;
+
+	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+	if (!hwc)
+		return NULL;
+
+	hwc->reg = cg->regs + 0x20 * idx;
+	hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
+
+	/*
+	 * Find the rate for the default clksel, and treat it as the
+	 * maximum rated core frequency.  If this is an incorrect
+	 * assumption, certain clock options (possibly including the
+	 * default clksel) may be inappropriately excluded on certain
+	 * chips.
+	 */
+	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	div = get_pll_div(cg, hwc, clksel);
+	if (!div)
+		return NULL;
+
+	pct80_rate = clk_get_rate(div->clk);
+	pct80_rate *= 8;
+	do_div(pct80_rate, 10);
+
+	plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
+
+	if (cg->info.flags & CG_CMUX_GE_PLAT)
+		min_rate = plat_rate;
+	else
+		min_rate = plat_rate / 2;
+
+	return create_mux_common(cg, hwc, &cmux_ops, min_rate,
+				 pct80_rate, "cg-cmux%d", idx);
+}
+
+static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
+{
+	struct mux_hwclock *hwc;
+
+	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+	if (!hwc)
+		return NULL;
+
+	hwc->reg = cg->regs + 0x20 * idx + 0x10;
+	hwc->info = cg->info.hwaccel[idx];
+
+	return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
+				 "cg-hwaccel%d", idx);
+}
+
+static void __init create_muxes(struct clockgen *cg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
+		if (cg->info.cmux_to_group[i] < 0)
+			break;
+		if (cg->info.cmux_to_group[i] >=
+		    ARRAY_SIZE(cg->info.cmux_groups)) {
+			WARN_ON_ONCE(1);
+			continue;
+		}
+
+		cg->cmux[i] = create_one_cmux(cg, i);
 	}
 
+	for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
+		if (!cg->info.hwaccel[i])
+			continue;
+
+		cg->hwaccel[i] = create_one_hwaccel(cg, i);
+	}
+}
+
+static void __init clockgen_init(struct device_node *np);
+
+/* Legacy nodes may get probed before the parent clockgen node */
+static void __init legacy_init_clockgen(struct device_node *np)
+{
+	if (!clockgen.node)
+		clockgen_init(of_get_parent(np));
+}
+
+/* Legacy node */
+static void __init core_mux_init(struct device_node *np)
+{
+	struct clk *clk;
+	struct resource res;
+	int idx, rc;
+
+	legacy_init_clockgen(np);
+
+	if (of_address_to_resource(np, 0, &res))
+		return;
+
+	idx = (res.start & 0xf0) >> 5;
+	clk = clockgen.cmux[idx];
+
 	rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
 	if (rc) {
-		pr_err("Could not register clock provider for node:%s\n",
-		       np->name);
-		goto err_clk;
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, rc);
+		return;
 	}
-	goto err_name;
+}
 
-err_clk:
-	kfree(cmux_clk);
-err_name:
-	/* free *_names because they are reallocated when registered */
-	kfree(parent_names);
+static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
+{
+	u32 rate;
+
+	if (of_property_read_u32(node, "clock-frequency", &rate))
+		return ERR_PTR(-ENODEV);
+
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
 }
 
-static void __init core_pll_init(struct device_node *np)
+static struct clk *sysclk_from_parent(const char *name)
+{
+	struct clk *clk;
+	const char *parent_name;
+
+	clk = of_clk_get(clockgen.node, 0);
+	if (IS_ERR(clk))
+		return clk;
+
+	/* Register the input clock under the desired name. */
+	parent_name = __clk_get_name(clk);
+	clk = clk_register_fixed_factor(NULL, name, parent_name,
+					0, 1, 1);
+	if (IS_ERR(clk))
+		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+		       PTR_ERR(clk));
+
+	return clk;
+}
+
+static struct clk * __init create_sysclk(const char *name)
+{
+	struct device_node *sysclk;
+	struct clk *clk;
+
+	clk = sysclk_from_fixed(clockgen.node, name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	clk = sysclk_from_parent(name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	sysclk = of_get_child_by_name(clockgen.node, "sysclk");
+	if (sysclk) {
+		clk = sysclk_from_fixed(sysclk, name);
+		if (!IS_ERR(clk))
+			return clk;
+	}
+
+	pr_err("%s: No input clock\n", __func__);
+	return NULL;
+}
+
+/* Legacy node */
+static void __init sysclk_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	legacy_init_clockgen(node);
+
+	clk = clockgen.sysclk;
+	if (clk)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+#define PLL_KILL BIT(31)
+
+static void __init create_one_pll(struct clockgen *cg, int idx)
 {
+	u32 __iomem *reg;
 	u32 mult;
-	int i, rc, count;
-	const char *clk_name, *parent_name;
-	struct clk_onecell_data *onecell_data;
-	struct clk      **subclks;
-	void __iomem *base;
+	struct clockgen_pll *pll = &cg->pll[idx];
+	int i;
 
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("iomap error\n");
+	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
-	}
 
-	/* get the multiple of PLL */
-	mult = ioread32be(base);
+	if (idx == PLATFORM_PLL)
+		reg = cg->regs + 0xc00;
+	else
+		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
 
-	/* check if this PLL is disabled */
+	/* Get the multiple of PLL */
+	mult = ioread32be(reg);
+
+	/* Check if this PLL is disabled */
 	if (mult & PLL_KILL) {
-		pr_debug("PLL:%s is disabled\n", np->name);
-		goto err_map;
+		pr_debug("%s(): pll %p disabled\n", __func__, reg);
+		return;
 	}
-	mult = (mult >> 1) & 0x3f;
 
-	parent_name = of_clk_get_parent_name(np, 0);
-	if (!parent_name) {
-		pr_err("PLL: %s must have a parent\n", np->name);
-		goto err_map;
+	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
+		mult = (mult & GENMASK(8, 1)) >> 1;
+	else
+		mult = (mult & GENMASK(6, 1)) >> 1;
+
+	for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
+		struct clk *clk;
+
+		snprintf(pll->div[i].name, sizeof(pll->div[i].name),
+			 "cg-pll%d-div%d", idx, i + 1);
+
+		clk = clk_register_fixed_factor(NULL,
+				pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
+		if (IS_ERR(clk)) {
+			pr_err("%s: %s: register failed %ld\n",
+			       __func__, pll->div[i].name, PTR_ERR(clk));
+			continue;
+		}
+
+		pll->div[i].clk = clk;
 	}
+}
+
+static void __init create_plls(struct clockgen *cg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
+		create_one_pll(cg, i);
+}
 
+static void __init legacy_pll_init(struct device_node *np, int idx)
+{
+	struct clockgen_pll *pll;
+	struct clk_onecell_data *onecell_data;
+	struct clk **subclks;
+	int count, rc;
+
+	legacy_init_clockgen(np);
+
+	pll = &clockgen.pll[idx];
 	count = of_property_count_strings(np, "clock-output-names");
-	if (count < 0 || count > 4) {
-		pr_err("%s: clock is not supported\n", np->name);
-		goto err_map;
-	}
 
-	subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
+	BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
+	subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
 	if (!subclks)
-		goto err_map;
+		return;
 
 	onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
 	if (!onecell_data)
 		goto err_clks;
 
-	for (i = 0; i < count; i++) {
-		rc = of_property_read_string_index(np, "clock-output-names",
-						   i, &clk_name);
-		if (rc) {
-			pr_err("%s: could not get clock names\n", np->name);
-			goto err_cell;
-		}
-
-		/*
-		 * when count == 4, there are 4 output clocks:
-		 * /1, /2, /3, /4 respectively
-		 * when count < 4, there are at least 2 output clocks:
-		 * /1, /2, (/4, if count == 3) respectively.
-		 */
-		if (count == 4)
-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
-					parent_name, 0, mult, 1 + i);
-		else
-
-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
-					parent_name, 0, mult, 1 << i);
-
-		if (IS_ERR(subclks[i])) {
-			pr_err("%s: could not register clock\n", clk_name);
-			goto err_cell;
-		}
+	if (count <= 3) {
+		subclks[0] = pll->div[0].clk;
+		subclks[1] = pll->div[1].clk;
+		subclks[2] = pll->div[3].clk;
+	} else {
+		subclks[0] = pll->div[0].clk;
+		subclks[1] = pll->div[1].clk;
+		subclks[2] = pll->div[2].clk;
+		subclks[3] = pll->div[3].clk;
 	}
 
 	onecell_data->clks = subclks;
@@ -233,125 +956,221 @@ static void __init core_pll_init(struct device_node *np)
 
 	rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
 	if (rc) {
-		pr_err("Could not register clk provider for node:%s\n",
-		       np->name);
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, rc);
 		goto err_cell;
 	}
 
-	iounmap(base);
 	return;
 err_cell:
 	kfree(onecell_data);
 err_clks:
 	kfree(subclks);
-err_map:
-	iounmap(base);
 }
 
-static void __init sysclk_init(struct device_node *node)
+/* Legacy node */
+static void __init pltfrm_pll_init(struct device_node *np)
 {
-	struct clk *clk;
-	const char *clk_name = node->name;
-	struct device_node *np = of_get_parent(node);
-	u32 rate;
+	legacy_pll_init(np, PLATFORM_PLL);
+}
 
-	if (!np) {
-		pr_err("could not get parent node\n");
+/* Legacy node */
+static void __init core_pll_init(struct device_node *np)
+{
+	struct resource res;
+	int idx;
+
+	if (of_address_to_resource(np, 0, &res))
 		return;
+
+	if ((res.start & 0xfff) == 0xc00) {
+		/*
+		 * ls1021a devtree labels the platform PLL
+		 * with the core PLL compatible
+		 */
+		pltfrm_pll_init(np);
+	} else {
+		idx = (res.start & 0xf0) >> 5;
+		legacy_pll_init(np, CGA_PLL1 + idx);
 	}
+}
 
-	if (of_property_read_u32(np, "clock-frequency", &rate)) {
-		of_node_put(node);
-		return;
+static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clockgen *cg = data;
+	struct clk *clk;
+	struct clockgen_pll *pll;
+	u32 type, idx;
+
+	if (clkspec->args_count < 2) {
+		pr_err("%s: insufficient phandle args\n", __func__);
+		return ERR_PTR(-EINVAL);
 	}
 
-	of_property_read_string(np, "clock-output-names", &clk_name);
+	type = clkspec->args[0];
+	idx = clkspec->args[1];
 
-	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
-	if (!IS_ERR(clk))
-		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	switch (type) {
+	case 0:
+		if (idx != 0)
+			goto bad_args;
+		clk = cg->sysclk;
+		break;
+	case 1:
+		if (idx >= ARRAY_SIZE(cg->cmux))
+			goto bad_args;
+		clk = cg->cmux[idx];
+		break;
+	case 2:
+		if (idx >= ARRAY_SIZE(cg->hwaccel))
+			goto bad_args;
+		clk = cg->hwaccel[idx];
+		break;
+	case 3:
+		if (idx >= ARRAY_SIZE(cg->fman))
+			goto bad_args;
+		clk = cg->fman[idx];
+		break;
+	case 4:
+		pll = &cg->pll[PLATFORM_PLL];
+		if (idx >= ARRAY_SIZE(pll->div))
+			goto bad_args;
+		clk = pll->div[idx].clk;
+		break;
+	default:
+		goto bad_args;
+	}
+
+	if (!clk)
+		return ERR_PTR(-ENOENT);
+	return clk;
+
+bad_args:
+	pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx);
+	return ERR_PTR(-EINVAL);
 }
 
-static void __init pltfrm_pll_init(struct device_node *np)
+#ifdef CONFIG_PPC
+#include <asm/mpc85xx.h>
+
+static const u32 a4510_svrs[] __initconst = {
+	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
+	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
+	(SVR_P2041 << 8) | 0x10,	/* P2041 1.0 */
+	(SVR_P2041 << 8) | 0x11,	/* P2041 1.1 */
+	(SVR_P3041 << 8) | 0x10,	/* P3041 1.0 */
+	(SVR_P3041 << 8) | 0x11,	/* P3041 1.1 */
+	(SVR_P4040 << 8) | 0x20,	/* P4040 2.0 */
+	(SVR_P4080 << 8) | 0x20,	/* P4080 2.0 */
+	(SVR_P5010 << 8) | 0x10,	/* P5010 1.0 */
+	(SVR_P5010 << 8) | 0x20,	/* P5010 2.0 */
+	(SVR_P5020 << 8) | 0x10,	/* P5020 1.0 */
+	(SVR_P5021 << 8) | 0x10,	/* P5021 1.0 */
+	(SVR_P5040 << 8) | 0x10,	/* P5040 1.0 */
+};
+
+#define SVR_SECURITY	0x80000	/* The Security (E) bit */
+
+static bool __init has_erratum_a4510(void)
 {
-	void __iomem *base;
-	uint32_t mult;
-	const char *parent_name, *clk_name;
-	int i, _errno;
-	struct clk_onecell_data *cod;
-
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
-		return;
+	u32 svr = mfspr(SPRN_SVR);
+	int i;
+
+	svr &= ~SVR_SECURITY;
+
+	for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
+		if (svr == a4510_svrs[i])
+			return true;
 	}
 
-	/* Get the multiple of PLL */
-	mult = ioread32be(base);
+	return false;
+}
+#else
+static bool __init has_erratum_a4510(void)
+{
+	return false;
+}
+#endif
 
-	iounmap(base);
+static void __init clockgen_init(struct device_node *np)
+{
+	int i, ret;
+	bool is_old_ls1021a = false;
 
-	/* Check if this PLL is disabled */
-	if (mult & PLL_KILL) {
-		pr_debug("%s(): %s: Disabled\n", __func__, np->name);
+	/* May have already been called by a legacy probe */
+	if (clockgen.node)
 		return;
-	}
-	mult = (mult & GENMASK(6, 1)) >> 1;
 
-	parent_name = of_clk_get_parent_name(np, 0);
-	if (!parent_name) {
-		pr_err("%s(): %s: of_clk_get_parent_name() failed\n",
-		       __func__, np->name);
+	clockgen.node = np;
+	clockgen.regs = of_iomap(np, 0);
+	if (!clockgen.regs &&
+	    of_device_is_compatible(of_root, "fsl,ls1021a")) {
+		/* Compatibility hack for old, broken device trees */
+		clockgen.regs = ioremap(0x1ee1000, 0x1000);
+		is_old_ls1021a = true;
+	}
+	if (!clockgen.regs) {
+		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
 		return;
 	}
 
-	i = of_property_count_strings(np, "clock-output-names");
-	if (i < 0) {
-		pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n",
-		       __func__, np->name, i);
-		return;
+	for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
+		if (of_device_is_compatible(np, chipinfo[i].compat))
+			break;
+		if (is_old_ls1021a &&
+		    !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
+			break;
 	}
 
-	cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL);
-	if (!cod)
-		return;
-	cod->clks = (struct clk **)(cod + 1);
-	cod->clk_num = i;
-
-	for (i = 0; i < cod->clk_num; i++) {
-		_errno = of_property_read_string_index(np, "clock-output-names",
-						       i, &clk_name);
-		if (_errno < 0) {
-			pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n",
-			       __func__, np->name, _errno);
-			goto return_clk_unregister;
-		}
+	if (i == ARRAY_SIZE(chipinfo)) {
+		pr_err("%s: unknown clockgen node %s\n", __func__,
+		       np->full_name);
+		goto err;
+	}
+	clockgen.info = chipinfo[i];
+
+	if (clockgen.info.guts_compat) {
+		struct device_node *guts;
 
-		cod->clks[i] = clk_register_fixed_factor(NULL, clk_name,
-					       parent_name, 0, mult, 1 + i);
-		if (IS_ERR(cod->clks[i])) {
-			pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n",
-			       __func__, np->name,
-			       clk_name, PTR_ERR(cod->clks[i]));
-			goto return_clk_unregister;
+		guts = of_find_compatible_node(NULL, NULL,
+					       clockgen.info.guts_compat);
+		if (guts) {
+			clockgen.guts = of_iomap(guts, 0);
+			if (!clockgen.guts) {
+				pr_err("%s: Couldn't map %s regs\n", __func__,
+				       guts->full_name);
+			}
 		}
+
 	}
 
-	_errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod);
-	if (_errno < 0) {
-		pr_err("%s(): %s: of_clk_add_provider() = %d\n",
-		       __func__, np->name, _errno);
-		goto return_clk_unregister;
+	if (has_erratum_a4510())
+		clockgen.info.flags |= CG_CMUX_GE_PLAT;
+
+	clockgen.sysclk = create_sysclk("cg-sysclk");
+	create_plls(&clockgen);
+	create_muxes(&clockgen);
+
+	if (clockgen.info.init_periph)
+		clockgen.info.init_periph(&clockgen);
+
+	ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
+	if (ret) {
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, ret);
 	}
 
 	return;
-
-return_clk_unregister:
-	while (--i >= 0)
-		clk_unregister(cod->clks[i]);
-	kfree(cod);
+err:
+	iounmap(clockgen.regs);
+	clockgen.regs = NULL;
 }
 
+CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+
+/* Legacy nodes */
 CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
 CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
 CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 2/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

The device tree should describe the chips (or chip-like subblocks) in
the system, but it generally does not describe individual registers --
it should identify, rather than describe, a programming interface.

This has not been the case with the QorIQ clockgen nodes.  The
knowledge of what each bit setting of CLKCnCSR means is encoded in
three places (binding, pll node, and mux node), and the last also needs
to know which options are valid on a particular chip.  All three of
these locations are considered stable ABI, making it difficult to fix
mistakes (of which I have found several), much less refactor the
abstraction to be able to address problems, limitations, or new chips.

Under the current binding, a pll clock specifier of 2 means that the
PLL is divided by 4 -- and the driver implements this, unless there
happen to be four clock-output-names rather than 3, in which case it
interprets it as PLL divided by 3.  This does not appear in the binding
documentation at all.  That hack is now considered stable ABI.

The current device tree nodes contain errors, such as saying that
T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options.
The current binding also ignores some restrictions on clock selection,
such as p5020's requirement that if a core uses the "wrong" PLL, that
PLL must be clocked lower than the "correct" PLL and be at most 80% of
the rated CPU frequency.

Possibly because of the lack of the ability to express such nuance in
the binding, some valid options are omitted from the device trees, such
as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from
PLL1 (again, only if they are at most 80% of rated CPU frequency).
This omission, combined with excessive caution in the cpufreq driver
(addressed in a subsequent patch), means that currently on a 1500 MHz
p4080 with typical PLL configuration, cpufreq can lower the frequency
to 1200 MHz on half the CPUs and do nothing on the others.  With this
patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a
rev3 p4080 half can be lowered to 750 MHz and the other half to 600
MHz.

The current binding only deals with CPU clocks.  To describe FMan in
the device tree, we need to describe its clock.  Some chips have
additional muxes that work like the CPU muxes, but are not described in
the device tree.  Others require inspecting the Reset Control Word to
determine which PLL is used.  Rather than continue to extend this mess,
replace it.  Have the driver bind to the chip-specific clockgen
compatible, and keep the detailed description of quirky chip variations
in the driver, where it can be easily fixed, refactored, and extended.

Older device trees will continue to work (including a workaround for
old ls1021a device trees that are missing compatible and reg in the
clockgen node, which even the old binding required).  The pll/mux
details in old device trees will be ignored, but "clocks" properties
pointing at the old nodes will still work, and be directed at the
corresponding new clock.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v2: was patch 3/5

Added missing initialization of hwc->cg.

 .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
 drivers/clk/clk-qoriq.c                            | 1261 ++++++++++++++++----
 2 files changed, 1090 insertions(+), 232 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
index df4a259..16a3ec4 100644
--- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
+++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
@@ -1,6 +1,6 @@
 * Clock Block on Freescale QorIQ Platforms
 
-Freescale qoriq chips take primary clocking input from the external
+Freescale QorIQ chips take primary clocking input from the external
 SYSCLK signal. The SYSCLK input (frequency) is multiplied using
 multiple phase locked loops (PLL) to create a variety of frequencies
 which can then be passed to a variety of internal logic, including
@@ -13,14 +13,16 @@ which the chip complies.
 Chassis Version		Example Chips
 ---------------		-------------
 1.0			p4080, p5020, p5040
-2.0			t4240, b4860, t1040
+2.0			t4240, b4860
 
 1. Clock Block Binding
 
 Required properties:
-- compatible: Should contain a specific clock block compatible string
-	and a single chassis clock compatible string.
-	Clock block strings include, but not limited to, one of the:
+- compatible: Should contain a chip-specific clock block compatible
+	string and (if applicable) may contain a chassis-version clock
+	compatible string.
+
+	Chip-specific strings are of the form "fsl,<chip>-clockgen", such as:
 	* "fsl,p2041-clockgen"
 	* "fsl,p3041-clockgen"
 	* "fsl,p4080-clockgen"
@@ -30,15 +32,14 @@ Required properties:
 	* "fsl,b4420-clockgen"
 	* "fsl,b4860-clockgen"
 	* "fsl,ls1021a-clockgen"
-	Chassis clock strings include:
+	Chassis-version clock strings include:
 	* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
 	* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
 - reg: Describes the address of the device's resources within the
 	address space defined by its parent bus, and resource zero
 	represents the clock register set
-- clock-frequency: Input system clock frequency
 
-Recommended properties:
+Optional properties:
 - ranges: Allows valid translation between child's address space and
 	parent's. Must be present if the device has sub-nodes.
 - #address-cells: Specifies the number of cells used to represent
@@ -47,8 +48,46 @@ Recommended properties:
 - #size-cells: Specifies the number of cells used to represent
 	the size of an address. Must be present if the device has
 	sub-nodes and set to 1 if present
+- clock-frequency: Input system clock frequency (SYSCLK)
+- clocks: If clock-frequency is not specified, sysclk may be provided
+	as an input clock.  Either clock-frequency or clocks must be
+	provided.
+
+2. Clock Provider
+
+The clockgen node should act as a clock provider, though in older device
+trees the children of the clockgen node are the clock providers.
+
+When the clockgen node is a clock provider, #clock-cells = <2>.
+The first cell of the clock specifier is the clock type, and the
+second cell is the clock index for the specified type.
+
+	Type#	Name		Index Cell
+	0	sysclk		must be 0
+	1	cmux		index (n in CLKCnCSR)
+	2	hwaccel		index (n in CLKCGnHWACSR)
+	3	fman		0 for fm1, 1 for fm2
+	4	platform pll	0=pll, 1=pll/2, 2=pll/3, 3=pll/4
+
+3. Example
+
+	clockgen: global-utilities at e1000 {
+		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+		clock-frequency = <133333333>;
+		reg = <0xe1000 0x1000>;
+		#clock-cells = <2>;
+	};
+
+	fman at 400000 {
+		...
+		clocks = <&clockgen 3 0>;
+		...
+	};
+}
+4. Legacy Child Nodes
 
-2. Clock Provider/Consumer Binding
+NOTE: These nodes are deprecated.  Kernels should continue to support
+device trees with these nodes, but new device trees should not use them.
 
 Most of the bindings are from the common clock binding[1].
  [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -82,7 +121,7 @@ Recommended properties:
 - reg: Should be the offset and length of clock block base address.
 	The length should be 4.
 
-Example for clock block and clock provider:
+Legacy Example:
 / {
 	clockgen: global-utilities at e1000 {
 		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
@@ -142,7 +181,7 @@ Example for clock block and clock provider:
 	};
 };
 
-Example for clock consumer:
+Example for legacy clock consumer:
 
 / {
 	cpu0: PowerPC,e5500 at 0 {
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index cda90a9..06281a3 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -10,7 +10,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/fsl/guts.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -19,213 +21,934 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
-struct cmux_clk {
+#define PLL_DIV1	0
+#define PLL_DIV2	1
+#define PLL_DIV3	2
+#define PLL_DIV4	3
+
+#define PLATFORM_PLL	0
+#define CGA_PLL1	1
+#define CGA_PLL2	2
+#define CGA_PLL3	3
+#define CGA_PLL4	4	/* only on clockgen-1.0, which lacks CGB */
+#define CGB_PLL1	4
+#define CGB_PLL2	5
+
+struct clockgen_pll_div {
+	struct clk *clk;
+	char name[32];
+};
+
+struct clockgen_pll {
+	struct clockgen_pll_div div[4];
+};
+
+#define CLKSEL_VALID	1
+#define CLKSEL_80PCT	2	/* Only allowed if PLL <= 80% of max cpu freq */
+
+struct clockgen_sourceinfo {
+	u32 flags;	/* CLKSEL_xxx */
+	int pll;	/* CGx_PLLn */
+	int div;	/* PLL_DIVn */
+};
+
+#define NUM_MUX_PARENTS	16
+
+struct clockgen_muxinfo {
+	struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
+};
+
+#define NUM_HWACCEL	5
+#define NUM_CMUX	8
+
+struct clockgen;
+
+/*
+ * cmux freq must be >= platform pll.
+ * If not set, cmux freq must be >= platform pll/2
+ */
+#define CG_CMUX_GE_PLAT		1
+#define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
+
+struct clockgen_chipinfo {
+	const char *compat, *guts_compat;
+	const struct clockgen_muxinfo *cmux_groups[2];
+	const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
+	void (*init_periph)(struct clockgen *cg);
+	int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
+	u32 pll_mask;	/* 1 << n bit set if PLL n is valid */
+	u32 flags;	/* CG_xxx */
+};
+
+struct clockgen {
+	struct device_node *node;
+	void __iomem *regs;
+	struct clockgen_chipinfo info; /* mutable copy */
+	struct clk *sysclk;
+	struct clockgen_pll pll[6];
+	struct clk *cmux[NUM_CMUX];
+	struct clk *hwaccel[NUM_HWACCEL];
+	struct clk *fman[2];
+	struct ccsr_guts __iomem *guts;
+};
+
+static struct clockgen clockgen;
+
+static const struct clockgen_muxinfo p2041_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p2041_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[4] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p5020_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p5040_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp1 = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		[8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
+	}
+};
+
+static const struct clockgen_muxinfo p4080_cmux_grp2 = {
+	{
+		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
+		[8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+		[9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+		[12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
+		[13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo t1023_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	}
+};
+
+static const struct clockgen_muxinfo t1040_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+	}
+};
+
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga = {
+	{
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
+	{
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
+	{
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+	},
+};
+
+static const struct clockgen_muxinfo t1023_hwa1 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t1023_hwa2 = {
+	{
+		[6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo t2080_hwa1 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t2080_hwa2 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa1 = {
+	{
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa4 = {
+	{
+		[2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		[3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+		[4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
+		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		[6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo t4240_hwa5 = {
+	{
+		[2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
+		[3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
+		[4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
+		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		[6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
+		[7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
+	},
+};
+
+#define RCWSR7_FM1_CLK_SEL	0x40000000
+#define RCWSR7_FM2_CLK_SEL	0x20000000
+#define RCWSR7_HWA_ASYNC_DIV	0x04000000
+
+static void __init p2041_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p4080_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+	if (reg & RCWSR7_FM2_CLK_SEL)
+		cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
+	else
+		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5020_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+	int div = PLL_DIV2;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+	if (reg & RCWSR7_HWA_ASYNC_DIV)
+		div = PLL_DIV4;
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init p5040_init_periph(struct clockgen *cg)
+{
+	u32 reg;
+	int div = PLL_DIV2;
+
+	reg = ioread32be(&cg->guts->rcwsr[7]);
+	if (reg & RCWSR7_HWA_ASYNC_DIV)
+		div = PLL_DIV4;
+
+	if (reg & RCWSR7_FM1_CLK_SEL)
+		cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
+	else
+		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+
+	if (reg & RCWSR7_FM2_CLK_SEL)
+		cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
+	else
+		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
+}
+
+static void __init t1023_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[1];
+}
+
+static void __init t1040_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
+}
+
+static void __init t2080_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[0];
+}
+
+static void __init t4240_init_periph(struct clockgen *cg)
+{
+	cg->fman[0] = cg->hwaccel[3];
+	cg->fman[1] = cg->hwaccel[4];
+}
+
+static const struct clockgen_chipinfo chipinfo[] = {
+	{
+		.compat = "fsl,b4420-clockgen",
+		.guts_compat = "fsl,b4860-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t2080_hwa1
+		},
+		.cmux_to_group = {
+			0, 1, 1, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,b4860-clockgen",
+		.guts_compat = "fsl,b4860-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t2080_hwa1
+		},
+		.cmux_to_group = {
+			0, 1, 1, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,ls1021a-clockgen",
+		.cmux_groups = {
+			&t1023_cmux
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x03,
+	},
+	{
+		.compat = "fsl,p2041-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p2041_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p3041-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p2041_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p4080-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p4080_init_periph,
+		.cmux_groups = {
+			&p4080_cmux_grp1, &p4080_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 0, 0, 1, 1, 1, 1
+		},
+		.pll_mask = 0x1f,
+	},
+	{
+		.compat = "fsl,p5020-clockgen",
+		.guts_compat = "fsl,qoriq-device-config-1.0",
+		.init_periph = p5020_init_periph,
+		.cmux_groups = {
+			&p2041_cmux_grp1, &p2041_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 1, -1
+		},
+		.pll_mask = 0x07,
+	},
+	{
+		.compat = "fsl,p5040-clockgen",
+		.guts_compat = "fsl,p5040-device-config",
+		.init_periph = p5040_init_periph,
+		.cmux_groups = {
+			&p5040_cmux_grp1, &p5040_cmux_grp2
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x0f,
+	},
+	{
+		.compat = "fsl,t1023-clockgen",
+		.guts_compat = "fsl,t1023-device-config",
+		.init_periph = t1023_init_periph,
+		.cmux_groups = {
+			&t1023_cmux
+		},
+		.hwaccel = {
+			&t1023_hwa1, &t1023_hwa2
+		},
+		.cmux_to_group = {
+			0, 0, -1
+		},
+		.pll_mask = 0x03,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t1040-clockgen",
+		.guts_compat = "fsl,t1040-device-config",
+		.init_periph = t1040_init_periph,
+		.cmux_groups = {
+			&t1040_cmux
+		},
+		.cmux_to_group = {
+			0, 0, 0, 0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t2080-clockgen",
+		.guts_compat = "fsl,t2080-device-config",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga12
+		},
+		.hwaccel = {
+			&t2080_hwa1, &t2080_hwa2
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,t4240-clockgen",
+		.guts_compat = "fsl,t4240-device-config",
+		.init_periph = t4240_init_periph,
+		.cmux_groups = {
+			&clockgen2_cmux_cga, &clockgen2_cmux_cgb
+		},
+		.hwaccel = {
+			&t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
+		},
+		.cmux_to_group = {
+			0, 0, 1, -1
+		},
+		.pll_mask = 0x3f,
+		.flags = CG_PLL_8BIT,
+	},
+	{},
+};
+
+struct mux_hwclock {
 	struct clk_hw hw;
-	void __iomem *reg;
-	unsigned int clk_per_pll;
-	u32 flags;
+	struct clockgen *cg;
+	const struct clockgen_muxinfo *info;
+	u32 __iomem *reg;
+	u8 parent_to_clksel[NUM_MUX_PARENTS];
+	s8 clksel_to_parent[NUM_MUX_PARENTS];
+	int num_parents;
 };
 
-#define PLL_KILL			BIT(31)
+#define to_mux_hwclock(p)	container_of(p, struct mux_hwclock, hw)
+#define CLKSEL_MASK		0x78000000
 #define	CLKSEL_SHIFT		27
-#define CLKSEL_ADJUST		BIT(0)
-#define to_cmux_clk(p)		container_of(p, struct cmux_clk, hw)
 
-static int cmux_set_parent(struct clk_hw *hw, u8 idx)
+static int mux_set_parent(struct clk_hw *hw, u8 idx)
 {
-	struct cmux_clk *clk = to_cmux_clk(hw);
+	struct mux_hwclock *hwc = to_mux_hwclock(hw);
 	u32 clksel;
 
-	clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll;
-	if (clk->flags & CLKSEL_ADJUST)
-		clksel += 8;
-	clksel = (clksel & 0xf) << CLKSEL_SHIFT;
-	iowrite32be(clksel, clk->reg);
+	if (idx >= hwc->num_parents)
+		return -EINVAL;
+
+	clksel = hwc->parent_to_clksel[idx];
+	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
 
 	return 0;
 }
 
-static u8 cmux_get_parent(struct clk_hw *hw)
+static u8 mux_get_parent(struct clk_hw *hw)
 {
-	struct cmux_clk *clk = to_cmux_clk(hw);
+	struct mux_hwclock *hwc = to_mux_hwclock(hw);
 	u32 clksel;
+	s8 ret;
 
-	clksel = ioread32be(clk->reg);
-	clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
-	if (clk->flags & CLKSEL_ADJUST)
-		clksel -= 8;
-	clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4;
+	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 
-	return clksel;
+	ret = hwc->clksel_to_parent[clksel];
+	if (ret < 0) {
+		pr_err("%s: mux@%p has bad clksel\n", __func__, hwc->reg);
+		return 0;
+	}
+
+	return ret;
 }
 
 static const struct clk_ops cmux_ops = {
-	.get_parent = cmux_get_parent,
-	.set_parent = cmux_set_parent,
+	.get_parent = mux_get_parent,
+	.set_parent = mux_set_parent,
 };
 
-static void __init core_mux_init(struct device_node *np)
+/*
+ * Don't allow setting for now, as the clock options haven't been
+ * sanitized for additional restrictions.
+ */
+static const struct clk_ops hwaccel_ops = {
+	.get_parent = mux_get_parent,
+};
+
+static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
+						  struct mux_hwclock *hwc,
+						  int idx)
 {
-	struct clk *clk;
-	struct clk_init_data init;
-	struct cmux_clk *cmux_clk;
-	struct device_node *node;
-	int rc, count, i;
-	u32	offset;
-	const char *clk_name;
-	const char **parent_names;
-	struct of_phandle_args clkspec;
+	int pll, div;
 
-	rc = of_property_read_u32(np, "reg", &offset);
-	if (rc) {
-		pr_err("%s: could not get reg property\n", np->name);
-		return;
-	}
+	if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
+		return NULL;
 
-	/* get the input clock source count */
-	count = of_property_count_strings(np, "clock-names");
-	if (count < 0) {
-		pr_err("%s: get clock count error\n", np->name);
-		return;
-	}
-	parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
-	if (!parent_names)
-		return;
+	pll = hwc->info->clksel[idx].pll;
+	div = hwc->info->clksel[idx].div;
 
-	for (i = 0; i < count; i++)
-		parent_names[i] = of_clk_get_parent_name(np, i);
+	return &cg->pll[pll].div[div];
+}
 
-	cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL);
-	if (!cmux_clk)
-		goto err_name;
+static struct clk * __init create_mux_common(struct clockgen *cg,
+					     struct mux_hwclock *hwc,
+					     const struct clk_ops *ops,
+					     unsigned long min_rate,
+					     unsigned long pct80_rate,
+					     const char *fmt, int idx)
+{
+	struct clk_init_data init = {};
+	struct clk *clk;
+	const struct clockgen_pll_div *div;
+	const char *parent_names[NUM_MUX_PARENTS];
+	char name[32];
+	int i, j;
 
-	cmux_clk->reg = of_iomap(np, 0);
-	if (!cmux_clk->reg) {
-		pr_err("%s: could not map register\n", __func__);
-		goto err_clk;
-	}
+	snprintf(name, sizeof(name), fmt, idx);
 
-	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
-					&clkspec);
-	if (rc) {
-		pr_err("%s: parse clock node error\n", __func__);
-		goto err_clk;
-	}
+	for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
+		unsigned long rate;
 
-	cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np,
-			"clock-output-names");
-	of_node_put(clkspec.np);
+		hwc->clksel_to_parent[i] = -1;
 
-	node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
-	if (node && (offset >= 0x80))
-		cmux_clk->flags = CLKSEL_ADJUST;
+		div = get_pll_div(cg, hwc, i);
+		if (!div)
+			continue;
 
-	rc = of_property_read_string_index(np, "clock-output-names",
-					   0, &clk_name);
-	if (rc) {
-		pr_err("%s: read clock names error\n", np->name);
-		goto err_clk;
+		rate = clk_get_rate(div->clk);
+
+		if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
+		    rate > pct80_rate)
+			continue;
+		if (rate < min_rate)
+			continue;
+
+		parent_names[j] = div->name;
+		hwc->parent_to_clksel[j] = i;
+		hwc->clksel_to_parent[i] = j;
+		j++;
 	}
 
-	init.name = clk_name;
-	init.ops = &cmux_ops;
+	init.name = name;
+	init.ops = ops;
 	init.parent_names = parent_names;
-	init.num_parents = count;
+	init.num_parents = hwc->num_parents = j;
 	init.flags = 0;
-	cmux_clk->hw.init = &init;
+	hwc->hw.init = &init;
+	hwc->cg = cg;
 
-	clk = clk_register(NULL, &cmux_clk->hw);
+	clk = clk_register(NULL, &hwc->hw);
 	if (IS_ERR(clk)) {
-		pr_err("%s: could not register clock\n", clk_name);
-		goto err_clk;
+		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+		       PTR_ERR(clk));
+		kfree(hwc);
+		return NULL;
+	}
+
+	return clk;
+}
+
+static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
+{
+	struct mux_hwclock *hwc;
+	const struct clockgen_pll_div *div;
+	unsigned long plat_rate, min_rate;
+	u64 pct80_rate;
+	u32 clksel;
+
+	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+	if (!hwc)
+		return NULL;
+
+	hwc->reg = cg->regs + 0x20 * idx;
+	hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
+
+	/*
+	 * Find the rate for the default clksel, and treat it as the
+	 * maximum rated core frequency.  If this is an incorrect
+	 * assumption, certain clock options (possibly including the
+	 * default clksel) may be inappropriately excluded on certain
+	 * chips.
+	 */
+	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	div = get_pll_div(cg, hwc, clksel);
+	if (!div)
+		return NULL;
+
+	pct80_rate = clk_get_rate(div->clk);
+	pct80_rate *= 8;
+	do_div(pct80_rate, 10);
+
+	plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
+
+	if (cg->info.flags & CG_CMUX_GE_PLAT)
+		min_rate = plat_rate;
+	else
+		min_rate = plat_rate / 2;
+
+	return create_mux_common(cg, hwc, &cmux_ops, min_rate,
+				 pct80_rate, "cg-cmux%d", idx);
+}
+
+static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
+{
+	struct mux_hwclock *hwc;
+
+	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+	if (!hwc)
+		return NULL;
+
+	hwc->reg = cg->regs + 0x20 * idx + 0x10;
+	hwc->info = cg->info.hwaccel[idx];
+
+	return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
+				 "cg-hwaccel%d", idx);
+}
+
+static void __init create_muxes(struct clockgen *cg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
+		if (cg->info.cmux_to_group[i] < 0)
+			break;
+		if (cg->info.cmux_to_group[i] >=
+		    ARRAY_SIZE(cg->info.cmux_groups)) {
+			WARN_ON_ONCE(1);
+			continue;
+		}
+
+		cg->cmux[i] = create_one_cmux(cg, i);
 	}
 
+	for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
+		if (!cg->info.hwaccel[i])
+			continue;
+
+		cg->hwaccel[i] = create_one_hwaccel(cg, i);
+	}
+}
+
+static void __init clockgen_init(struct device_node *np);
+
+/* Legacy nodes may get probed before the parent clockgen node */
+static void __init legacy_init_clockgen(struct device_node *np)
+{
+	if (!clockgen.node)
+		clockgen_init(of_get_parent(np));
+}
+
+/* Legacy node */
+static void __init core_mux_init(struct device_node *np)
+{
+	struct clk *clk;
+	struct resource res;
+	int idx, rc;
+
+	legacy_init_clockgen(np);
+
+	if (of_address_to_resource(np, 0, &res))
+		return;
+
+	idx = (res.start & 0xf0) >> 5;
+	clk = clockgen.cmux[idx];
+
 	rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
 	if (rc) {
-		pr_err("Could not register clock provider for node:%s\n",
-		       np->name);
-		goto err_clk;
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, rc);
+		return;
 	}
-	goto err_name;
+}
 
-err_clk:
-	kfree(cmux_clk);
-err_name:
-	/* free *_names because they are reallocated when registered */
-	kfree(parent_names);
+static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
+{
+	u32 rate;
+
+	if (of_property_read_u32(node, "clock-frequency", &rate))
+		return ERR_PTR(-ENODEV);
+
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
 }
 
-static void __init core_pll_init(struct device_node *np)
+static struct clk *sysclk_from_parent(const char *name)
+{
+	struct clk *clk;
+	const char *parent_name;
+
+	clk = of_clk_get(clockgen.node, 0);
+	if (IS_ERR(clk))
+		return clk;
+
+	/* Register the input clock under the desired name. */
+	parent_name = __clk_get_name(clk);
+	clk = clk_register_fixed_factor(NULL, name, parent_name,
+					0, 1, 1);
+	if (IS_ERR(clk))
+		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+		       PTR_ERR(clk));
+
+	return clk;
+}
+
+static struct clk * __init create_sysclk(const char *name)
+{
+	struct device_node *sysclk;
+	struct clk *clk;
+
+	clk = sysclk_from_fixed(clockgen.node, name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	clk = sysclk_from_parent(name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	sysclk = of_get_child_by_name(clockgen.node, "sysclk");
+	if (sysclk) {
+		clk = sysclk_from_fixed(sysclk, name);
+		if (!IS_ERR(clk))
+			return clk;
+	}
+
+	pr_err("%s: No input clock\n", __func__);
+	return NULL;
+}
+
+/* Legacy node */
+static void __init sysclk_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	legacy_init_clockgen(node);
+
+	clk = clockgen.sysclk;
+	if (clk)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+#define PLL_KILL BIT(31)
+
+static void __init create_one_pll(struct clockgen *cg, int idx)
 {
+	u32 __iomem *reg;
 	u32 mult;
-	int i, rc, count;
-	const char *clk_name, *parent_name;
-	struct clk_onecell_data *onecell_data;
-	struct clk      **subclks;
-	void __iomem *base;
+	struct clockgen_pll *pll = &cg->pll[idx];
+	int i;
 
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("iomap error\n");
+	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
-	}
 
-	/* get the multiple of PLL */
-	mult = ioread32be(base);
+	if (idx == PLATFORM_PLL)
+		reg = cg->regs + 0xc00;
+	else
+		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
 
-	/* check if this PLL is disabled */
+	/* Get the multiple of PLL */
+	mult = ioread32be(reg);
+
+	/* Check if this PLL is disabled */
 	if (mult & PLL_KILL) {
-		pr_debug("PLL:%s is disabled\n", np->name);
-		goto err_map;
+		pr_debug("%s(): pll %p disabled\n", __func__, reg);
+		return;
 	}
-	mult = (mult >> 1) & 0x3f;
 
-	parent_name = of_clk_get_parent_name(np, 0);
-	if (!parent_name) {
-		pr_err("PLL: %s must have a parent\n", np->name);
-		goto err_map;
+	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
+		mult = (mult & GENMASK(8, 1)) >> 1;
+	else
+		mult = (mult & GENMASK(6, 1)) >> 1;
+
+	for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
+		struct clk *clk;
+
+		snprintf(pll->div[i].name, sizeof(pll->div[i].name),
+			 "cg-pll%d-div%d", idx, i + 1);
+
+		clk = clk_register_fixed_factor(NULL,
+				pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
+		if (IS_ERR(clk)) {
+			pr_err("%s: %s: register failed %ld\n",
+			       __func__, pll->div[i].name, PTR_ERR(clk));
+			continue;
+		}
+
+		pll->div[i].clk = clk;
 	}
+}
+
+static void __init create_plls(struct clockgen *cg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
+		create_one_pll(cg, i);
+}
 
+static void __init legacy_pll_init(struct device_node *np, int idx)
+{
+	struct clockgen_pll *pll;
+	struct clk_onecell_data *onecell_data;
+	struct clk **subclks;
+	int count, rc;
+
+	legacy_init_clockgen(np);
+
+	pll = &clockgen.pll[idx];
 	count = of_property_count_strings(np, "clock-output-names");
-	if (count < 0 || count > 4) {
-		pr_err("%s: clock is not supported\n", np->name);
-		goto err_map;
-	}
 
-	subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
+	BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
+	subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
 	if (!subclks)
-		goto err_map;
+		return;
 
 	onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
 	if (!onecell_data)
 		goto err_clks;
 
-	for (i = 0; i < count; i++) {
-		rc = of_property_read_string_index(np, "clock-output-names",
-						   i, &clk_name);
-		if (rc) {
-			pr_err("%s: could not get clock names\n", np->name);
-			goto err_cell;
-		}
-
-		/*
-		 * when count == 4, there are 4 output clocks:
-		 * /1, /2, /3, /4 respectively
-		 * when count < 4, there are@least 2 output clocks:
-		 * /1, /2, (/4, if count == 3) respectively.
-		 */
-		if (count == 4)
-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
-					parent_name, 0, mult, 1 + i);
-		else
-
-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
-					parent_name, 0, mult, 1 << i);
-
-		if (IS_ERR(subclks[i])) {
-			pr_err("%s: could not register clock\n", clk_name);
-			goto err_cell;
-		}
+	if (count <= 3) {
+		subclks[0] = pll->div[0].clk;
+		subclks[1] = pll->div[1].clk;
+		subclks[2] = pll->div[3].clk;
+	} else {
+		subclks[0] = pll->div[0].clk;
+		subclks[1] = pll->div[1].clk;
+		subclks[2] = pll->div[2].clk;
+		subclks[3] = pll->div[3].clk;
 	}
 
 	onecell_data->clks = subclks;
@@ -233,125 +956,221 @@ static void __init core_pll_init(struct device_node *np)
 
 	rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
 	if (rc) {
-		pr_err("Could not register clk provider for node:%s\n",
-		       np->name);
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, rc);
 		goto err_cell;
 	}
 
-	iounmap(base);
 	return;
 err_cell:
 	kfree(onecell_data);
 err_clks:
 	kfree(subclks);
-err_map:
-	iounmap(base);
 }
 
-static void __init sysclk_init(struct device_node *node)
+/* Legacy node */
+static void __init pltfrm_pll_init(struct device_node *np)
 {
-	struct clk *clk;
-	const char *clk_name = node->name;
-	struct device_node *np = of_get_parent(node);
-	u32 rate;
+	legacy_pll_init(np, PLATFORM_PLL);
+}
 
-	if (!np) {
-		pr_err("could not get parent node\n");
+/* Legacy node */
+static void __init core_pll_init(struct device_node *np)
+{
+	struct resource res;
+	int idx;
+
+	if (of_address_to_resource(np, 0, &res))
 		return;
+
+	if ((res.start & 0xfff) == 0xc00) {
+		/*
+		 * ls1021a devtree labels the platform PLL
+		 * with the core PLL compatible
+		 */
+		pltfrm_pll_init(np);
+	} else {
+		idx = (res.start & 0xf0) >> 5;
+		legacy_pll_init(np, CGA_PLL1 + idx);
 	}
+}
 
-	if (of_property_read_u32(np, "clock-frequency", &rate)) {
-		of_node_put(node);
-		return;
+static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clockgen *cg = data;
+	struct clk *clk;
+	struct clockgen_pll *pll;
+	u32 type, idx;
+
+	if (clkspec->args_count < 2) {
+		pr_err("%s: insufficient phandle args\n", __func__);
+		return ERR_PTR(-EINVAL);
 	}
 
-	of_property_read_string(np, "clock-output-names", &clk_name);
+	type = clkspec->args[0];
+	idx = clkspec->args[1];
 
-	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
-	if (!IS_ERR(clk))
-		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	switch (type) {
+	case 0:
+		if (idx != 0)
+			goto bad_args;
+		clk = cg->sysclk;
+		break;
+	case 1:
+		if (idx >= ARRAY_SIZE(cg->cmux))
+			goto bad_args;
+		clk = cg->cmux[idx];
+		break;
+	case 2:
+		if (idx >= ARRAY_SIZE(cg->hwaccel))
+			goto bad_args;
+		clk = cg->hwaccel[idx];
+		break;
+	case 3:
+		if (idx >= ARRAY_SIZE(cg->fman))
+			goto bad_args;
+		clk = cg->fman[idx];
+		break;
+	case 4:
+		pll = &cg->pll[PLATFORM_PLL];
+		if (idx >= ARRAY_SIZE(pll->div))
+			goto bad_args;
+		clk = pll->div[idx].clk;
+		break;
+	default:
+		goto bad_args;
+	}
+
+	if (!clk)
+		return ERR_PTR(-ENOENT);
+	return clk;
+
+bad_args:
+	pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx);
+	return ERR_PTR(-EINVAL);
 }
 
-static void __init pltfrm_pll_init(struct device_node *np)
+#ifdef CONFIG_PPC
+#include <asm/mpc85xx.h>
+
+static const u32 a4510_svrs[] __initconst = {
+	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
+	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
+	(SVR_P2041 << 8) | 0x10,	/* P2041 1.0 */
+	(SVR_P2041 << 8) | 0x11,	/* P2041 1.1 */
+	(SVR_P3041 << 8) | 0x10,	/* P3041 1.0 */
+	(SVR_P3041 << 8) | 0x11,	/* P3041 1.1 */
+	(SVR_P4040 << 8) | 0x20,	/* P4040 2.0 */
+	(SVR_P4080 << 8) | 0x20,	/* P4080 2.0 */
+	(SVR_P5010 << 8) | 0x10,	/* P5010 1.0 */
+	(SVR_P5010 << 8) | 0x20,	/* P5010 2.0 */
+	(SVR_P5020 << 8) | 0x10,	/* P5020 1.0 */
+	(SVR_P5021 << 8) | 0x10,	/* P5021 1.0 */
+	(SVR_P5040 << 8) | 0x10,	/* P5040 1.0 */
+};
+
+#define SVR_SECURITY	0x80000	/* The Security (E) bit */
+
+static bool __init has_erratum_a4510(void)
 {
-	void __iomem *base;
-	uint32_t mult;
-	const char *parent_name, *clk_name;
-	int i, _errno;
-	struct clk_onecell_data *cod;
-
-	base = of_iomap(np, 0);
-	if (!base) {
-		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
-		return;
+	u32 svr = mfspr(SPRN_SVR);
+	int i;
+
+	svr &= ~SVR_SECURITY;
+
+	for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
+		if (svr == a4510_svrs[i])
+			return true;
 	}
 
-	/* Get the multiple of PLL */
-	mult = ioread32be(base);
+	return false;
+}
+#else
+static bool __init has_erratum_a4510(void)
+{
+	return false;
+}
+#endif
 
-	iounmap(base);
+static void __init clockgen_init(struct device_node *np)
+{
+	int i, ret;
+	bool is_old_ls1021a = false;
 
-	/* Check if this PLL is disabled */
-	if (mult & PLL_KILL) {
-		pr_debug("%s(): %s: Disabled\n", __func__, np->name);
+	/* May have already been called by a legacy probe */
+	if (clockgen.node)
 		return;
-	}
-	mult = (mult & GENMASK(6, 1)) >> 1;
 
-	parent_name = of_clk_get_parent_name(np, 0);
-	if (!parent_name) {
-		pr_err("%s(): %s: of_clk_get_parent_name() failed\n",
-		       __func__, np->name);
+	clockgen.node = np;
+	clockgen.regs = of_iomap(np, 0);
+	if (!clockgen.regs &&
+	    of_device_is_compatible(of_root, "fsl,ls1021a")) {
+		/* Compatibility hack for old, broken device trees */
+		clockgen.regs = ioremap(0x1ee1000, 0x1000);
+		is_old_ls1021a = true;
+	}
+	if (!clockgen.regs) {
+		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
 		return;
 	}
 
-	i = of_property_count_strings(np, "clock-output-names");
-	if (i < 0) {
-		pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n",
-		       __func__, np->name, i);
-		return;
+	for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
+		if (of_device_is_compatible(np, chipinfo[i].compat))
+			break;
+		if (is_old_ls1021a &&
+		    !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
+			break;
 	}
 
-	cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL);
-	if (!cod)
-		return;
-	cod->clks = (struct clk **)(cod + 1);
-	cod->clk_num = i;
-
-	for (i = 0; i < cod->clk_num; i++) {
-		_errno = of_property_read_string_index(np, "clock-output-names",
-						       i, &clk_name);
-		if (_errno < 0) {
-			pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n",
-			       __func__, np->name, _errno);
-			goto return_clk_unregister;
-		}
+	if (i == ARRAY_SIZE(chipinfo)) {
+		pr_err("%s: unknown clockgen node %s\n", __func__,
+		       np->full_name);
+		goto err;
+	}
+	clockgen.info = chipinfo[i];
+
+	if (clockgen.info.guts_compat) {
+		struct device_node *guts;
 
-		cod->clks[i] = clk_register_fixed_factor(NULL, clk_name,
-					       parent_name, 0, mult, 1 + i);
-		if (IS_ERR(cod->clks[i])) {
-			pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n",
-			       __func__, np->name,
-			       clk_name, PTR_ERR(cod->clks[i]));
-			goto return_clk_unregister;
+		guts = of_find_compatible_node(NULL, NULL,
+					       clockgen.info.guts_compat);
+		if (guts) {
+			clockgen.guts = of_iomap(guts, 0);
+			if (!clockgen.guts) {
+				pr_err("%s: Couldn't map %s regs\n", __func__,
+				       guts->full_name);
+			}
 		}
+
 	}
 
-	_errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod);
-	if (_errno < 0) {
-		pr_err("%s(): %s: of_clk_add_provider() = %d\n",
-		       __func__, np->name, _errno);
-		goto return_clk_unregister;
+	if (has_erratum_a4510())
+		clockgen.info.flags |= CG_CMUX_GE_PLAT;
+
+	clockgen.sysclk = create_sysclk("cg-sysclk");
+	create_plls(&clockgen);
+	create_muxes(&clockgen);
+
+	if (clockgen.info.init_periph)
+		clockgen.info.init_periph(&clockgen);
+
+	ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
+	if (ret) {
+		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
+		       __func__, np->name, ret);
 	}
 
 	return;
-
-return_clk_unregister:
-	while (--i >= 0)
-		clk_unregister(cod->clks[i]);
-	kfree(cod);
+err:
+	iounmap(clockgen.regs);
+	clockgen.regs = NULL;
 }
 
+CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+
+/* Legacy nodes */
 CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
 CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
 CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 3/5] clk: qoriq: Add ls2080a support.
  2015-09-20  4:29 ` Scott Wood
  (?)
@ 2015-09-20  4:29   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

LS2080A is the first implementation of the chassis 3 clockgen, which
has a different register layout than previous chips.  It is also little
endian, unlike previous chips.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/Kconfig     |  2 +-
 drivers/clk/clk-qoriq.c | 77 +++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 42f7120..9f1970c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -121,7 +121,7 @@ config COMMON_CLK_AXI_CLKGEN
 
 config CLK_QORIQ
 	bool "Clock driver for Freescale QorIQ platforms"
-	depends on (PPC_E500MC || ARM) && OF
+	depends on (PPC_E500MC || ARM || ARM64) && OF
 	---help---
 	  This adds the clock driver support for Freescale QorIQ platforms
 	  using common clock framework.
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 06281a3..8f9c93b 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -68,7 +68,10 @@ struct clockgen;
  * If not set, cmux freq must be >= platform pll/2
  */
 #define CG_CMUX_GE_PLAT		1
+
 #define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
+#define CG_VER3			4	/* version 3 cg: reg layout different */
+#define CG_LITTLE_ENDIAN	8
 
 struct clockgen_chipinfo {
 	const char *compat, *guts_compat;
@@ -94,6 +97,26 @@ struct clockgen {
 
 static struct clockgen clockgen;
 
+static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
+{
+	if (cg->info.flags & CG_LITTLE_ENDIAN)
+		iowrite32(val, reg);
+	else
+		iowrite32be(val, reg);
+}
+
+static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
+{
+	u32 val;
+
+	if (cg->info.flags & CG_LITTLE_ENDIAN)
+		val = ioread32(reg);
+	else
+		val = ioread32be(reg);
+
+	return val;
+}
+
 static const struct clockgen_muxinfo p2041_cmux_grp1 = {
 	{
 		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
@@ -429,6 +452,17 @@ static const struct clockgen_chipinfo chipinfo[] = {
 		.pll_mask = 0x03,
 	},
 	{
+		.compat = "fsl,ls2080a-clockgen",
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x37,
+		.flags = CG_VER3 | CG_LITTLE_ENDIAN,
+	},
+	{
 		.compat = "fsl,p2041-clockgen",
 		.guts_compat = "fsl,qoriq-device-config-1.0",
 		.init_periph = p2041_init_periph,
@@ -575,7 +609,7 @@ static int mux_set_parent(struct clk_hw *hw, u8 idx)
 		return -EINVAL;
 
 	clksel = hwc->parent_to_clksel[idx];
-	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
+	cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
 
 	return 0;
 }
@@ -586,7 +620,7 @@ static u8 mux_get_parent(struct clk_hw *hw)
 	u32 clksel;
 	s8 ret;
 
-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 
 	ret = hwc->clksel_to_parent[clksel];
 	if (ret < 0) {
@@ -705,7 +739,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
 	 * default clksel) may be inappropriately excluded on certain
 	 * chips.
 	 */
-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 	div = get_pll_div(cg, hwc, clksel);
 	if (!div)
 		return NULL;
@@ -874,13 +908,36 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
 
-	if (idx == PLATFORM_PLL)
-		reg = cg->regs + 0xc00;
-	else
-		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+	if (cg->info.flags & CG_VER3) {
+		switch (idx) {
+		case PLATFORM_PLL:
+			reg = cg->regs + 0x60080;
+			break;
+		case CGA_PLL1:
+			reg = cg->regs + 0x80;
+			break;
+		case CGA_PLL2:
+			reg = cg->regs + 0xa0;
+			break;
+		case CGB_PLL1:
+			reg = cg->regs + 0x10080;
+			break;
+		case CGB_PLL2:
+			reg = cg->regs + 0x100a0;
+			break;
+		default:
+			WARN_ONCE(1, "index %d\n", idx);
+			return;
+		}
+	} else {
+		if (idx == PLATFORM_PLL)
+			reg = cg->regs + 0xc00;
+		else
+			reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+	}
 
 	/* Get the multiple of PLL */
-	mult = ioread32be(reg);
+	mult = cg_in(cg, reg);
 
 	/* Check if this PLL is disabled */
 	if (mult & PLL_KILL) {
@@ -888,7 +945,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 		return;
 	}
 
-	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
+	if ((cg->info.flags & CG_VER3) ||
+	    ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
 		mult = (mult & GENMASK(8, 1)) >> 1;
 	else
 		mult = (mult & GENMASK(6, 1)) >> 1;
@@ -1169,6 +1227,7 @@ err:
 CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
 
 /* Legacy nodes */
 CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 3/5] clk: qoriq: Add ls2080a support.
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

LS2080A is the first implementation of the chassis 3 clockgen, which
has a different register layout than previous chips.  It is also little
endian, unlike previous chips.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/Kconfig     |  2 +-
 drivers/clk/clk-qoriq.c | 77 +++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 42f7120..9f1970c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -121,7 +121,7 @@ config COMMON_CLK_AXI_CLKGEN
 
 config CLK_QORIQ
 	bool "Clock driver for Freescale QorIQ platforms"
-	depends on (PPC_E500MC || ARM) && OF
+	depends on (PPC_E500MC || ARM || ARM64) && OF
 	---help---
 	  This adds the clock driver support for Freescale QorIQ platforms
 	  using common clock framework.
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 06281a3..8f9c93b 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -68,7 +68,10 @@ struct clockgen;
  * If not set, cmux freq must be >= platform pll/2
  */
 #define CG_CMUX_GE_PLAT		1
+
 #define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
+#define CG_VER3			4	/* version 3 cg: reg layout different */
+#define CG_LITTLE_ENDIAN	8
 
 struct clockgen_chipinfo {
 	const char *compat, *guts_compat;
@@ -94,6 +97,26 @@ struct clockgen {
 
 static struct clockgen clockgen;
 
+static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
+{
+	if (cg->info.flags & CG_LITTLE_ENDIAN)
+		iowrite32(val, reg);
+	else
+		iowrite32be(val, reg);
+}
+
+static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
+{
+	u32 val;
+
+	if (cg->info.flags & CG_LITTLE_ENDIAN)
+		val = ioread32(reg);
+	else
+		val = ioread32be(reg);
+
+	return val;
+}
+
 static const struct clockgen_muxinfo p2041_cmux_grp1 = {
 	{
 		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
@@ -429,6 +452,17 @@ static const struct clockgen_chipinfo chipinfo[] = {
 		.pll_mask = 0x03,
 	},
 	{
+		.compat = "fsl,ls2080a-clockgen",
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x37,
+		.flags = CG_VER3 | CG_LITTLE_ENDIAN,
+	},
+	{
 		.compat = "fsl,p2041-clockgen",
 		.guts_compat = "fsl,qoriq-device-config-1.0",
 		.init_periph = p2041_init_periph,
@@ -575,7 +609,7 @@ static int mux_set_parent(struct clk_hw *hw, u8 idx)
 		return -EINVAL;
 
 	clksel = hwc->parent_to_clksel[idx];
-	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
+	cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
 
 	return 0;
 }
@@ -586,7 +620,7 @@ static u8 mux_get_parent(struct clk_hw *hw)
 	u32 clksel;
 	s8 ret;
 
-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 
 	ret = hwc->clksel_to_parent[clksel];
 	if (ret < 0) {
@@ -705,7 +739,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
 	 * default clksel) may be inappropriately excluded on certain
 	 * chips.
 	 */
-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 	div = get_pll_div(cg, hwc, clksel);
 	if (!div)
 		return NULL;
@@ -874,13 +908,36 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
 
-	if (idx == PLATFORM_PLL)
-		reg = cg->regs + 0xc00;
-	else
-		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+	if (cg->info.flags & CG_VER3) {
+		switch (idx) {
+		case PLATFORM_PLL:
+			reg = cg->regs + 0x60080;
+			break;
+		case CGA_PLL1:
+			reg = cg->regs + 0x80;
+			break;
+		case CGA_PLL2:
+			reg = cg->regs + 0xa0;
+			break;
+		case CGB_PLL1:
+			reg = cg->regs + 0x10080;
+			break;
+		case CGB_PLL2:
+			reg = cg->regs + 0x100a0;
+			break;
+		default:
+			WARN_ONCE(1, "index %d\n", idx);
+			return;
+		}
+	} else {
+		if (idx == PLATFORM_PLL)
+			reg = cg->regs + 0xc00;
+		else
+			reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+	}
 
 	/* Get the multiple of PLL */
-	mult = ioread32be(reg);
+	mult = cg_in(cg, reg);
 
 	/* Check if this PLL is disabled */
 	if (mult & PLL_KILL) {
@@ -888,7 +945,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 		return;
 	}
 
-	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
+	if ((cg->info.flags & CG_VER3) ||
+	    ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
 		mult = (mult & GENMASK(8, 1)) >> 1;
 	else
 		mult = (mult & GENMASK(6, 1)) >> 1;
@@ -1169,6 +1227,7 @@ err:
 CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
 
 /* Legacy nodes */
 CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 3/5] clk: qoriq: Add ls2080a support.
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

LS2080A is the first implementation of the chassis 3 clockgen, which
has a different register layout than previous chips.  It is also little
endian, unlike previous chips.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/Kconfig     |  2 +-
 drivers/clk/clk-qoriq.c | 77 +++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 42f7120..9f1970c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -121,7 +121,7 @@ config COMMON_CLK_AXI_CLKGEN
 
 config CLK_QORIQ
 	bool "Clock driver for Freescale QorIQ platforms"
-	depends on (PPC_E500MC || ARM) && OF
+	depends on (PPC_E500MC || ARM || ARM64) && OF
 	---help---
 	  This adds the clock driver support for Freescale QorIQ platforms
 	  using common clock framework.
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 06281a3..8f9c93b 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -68,7 +68,10 @@ struct clockgen;
  * If not set, cmux freq must be >= platform pll/2
  */
 #define CG_CMUX_GE_PLAT		1
+
 #define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
+#define CG_VER3			4	/* version 3 cg: reg layout different */
+#define CG_LITTLE_ENDIAN	8
 
 struct clockgen_chipinfo {
 	const char *compat, *guts_compat;
@@ -94,6 +97,26 @@ struct clockgen {
 
 static struct clockgen clockgen;
 
+static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
+{
+	if (cg->info.flags & CG_LITTLE_ENDIAN)
+		iowrite32(val, reg);
+	else
+		iowrite32be(val, reg);
+}
+
+static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
+{
+	u32 val;
+
+	if (cg->info.flags & CG_LITTLE_ENDIAN)
+		val = ioread32(reg);
+	else
+		val = ioread32be(reg);
+
+	return val;
+}
+
 static const struct clockgen_muxinfo p2041_cmux_grp1 = {
 	{
 		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
@@ -429,6 +452,17 @@ static const struct clockgen_chipinfo chipinfo[] = {
 		.pll_mask = 0x03,
 	},
 	{
+		.compat = "fsl,ls2080a-clockgen",
+		.cmux_groups = {
+			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+		},
+		.cmux_to_group = {
+			0, 0, 1, 1, -1
+		},
+		.pll_mask = 0x37,
+		.flags = CG_VER3 | CG_LITTLE_ENDIAN,
+	},
+	{
 		.compat = "fsl,p2041-clockgen",
 		.guts_compat = "fsl,qoriq-device-config-1.0",
 		.init_periph = p2041_init_periph,
@@ -575,7 +609,7 @@ static int mux_set_parent(struct clk_hw *hw, u8 idx)
 		return -EINVAL;
 
 	clksel = hwc->parent_to_clksel[idx];
-	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
+	cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
 
 	return 0;
 }
@@ -586,7 +620,7 @@ static u8 mux_get_parent(struct clk_hw *hw)
 	u32 clksel;
 	s8 ret;
 
-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 
 	ret = hwc->clksel_to_parent[clksel];
 	if (ret < 0) {
@@ -705,7 +739,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
 	 * default clksel) may be inappropriately excluded on certain
 	 * chips.
 	 */
-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+	clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 	div = get_pll_div(cg, hwc, clksel);
 	if (!div)
 		return NULL;
@@ -874,13 +908,36 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
 
-	if (idx == PLATFORM_PLL)
-		reg = cg->regs + 0xc00;
-	else
-		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+	if (cg->info.flags & CG_VER3) {
+		switch (idx) {
+		case PLATFORM_PLL:
+			reg = cg->regs + 0x60080;
+			break;
+		case CGA_PLL1:
+			reg = cg->regs + 0x80;
+			break;
+		case CGA_PLL2:
+			reg = cg->regs + 0xa0;
+			break;
+		case CGB_PLL1:
+			reg = cg->regs + 0x10080;
+			break;
+		case CGB_PLL2:
+			reg = cg->regs + 0x100a0;
+			break;
+		default:
+			WARN_ONCE(1, "index %d\n", idx);
+			return;
+		}
+	} else {
+		if (idx == PLATFORM_PLL)
+			reg = cg->regs + 0xc00;
+		else
+			reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+	}
 
 	/* Get the multiple of PLL */
-	mult = ioread32be(reg);
+	mult = cg_in(cg, reg);
 
 	/* Check if this PLL is disabled */
 	if (mult & PLL_KILL) {
@@ -888,7 +945,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 		return;
 	}
 
-	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
+	if ((cg->info.flags & CG_VER3) ||
+	    ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
 		mult = (mult & GENMASK(8, 1)) >> 1;
 	else
 		mult = (mult & GENMASK(6, 1)) >> 1;
@@ -1169,6 +1227,7 @@ err:
 CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
 
 /* Legacy nodes */
 CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
  2015-09-20  4:29 ` Scott Wood
  (?)
@ 2015-09-20  4:29   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
__clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
true provider API versions that operate on struct clk_hw.

qoriq-cpufreq needs these functions in order to determine the options
it has for calling clk_set_parent() and thus populate the cpufreq
table, so revive them as legitimate consumer APIs.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/clk.c   | 19 +++++++++++++++++++
 include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 43e2c3a..9436356 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
+unsigned int clk_get_num_parents(struct clk *clk)
+{
+	return !clk ? 0 : clk->core->num_parents;
+}
+EXPORT_SYMBOL_GPL(clk_get_num_parents);
+
 unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
 {
 	return hw->core->num_parents;
@@ -359,6 +365,19 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
 		return core->parents[index];
 }
 
+struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
+{
+	struct clk_core *parent;
+
+	if (!clk)
+		return NULL;
+
+	parent = clk_core_get_parent_by_index(clk->core, index);
+
+	return !parent ? NULL : parent->hw->clk;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
+
 struct clk_hw *
 clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
 {
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0df4a51..937de0e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk *parent);
 struct clk *clk_get_parent(struct clk *clk);
 
 /**
+ * clk_get_parent_by_index - get a possible parent clock by index
+ * @clk: clock source
+ * @index: index into the array of possible parents of this clock
+ *
+ * Returns struct clk corresponding to the requested possible
+ * parent clock source, or NULL.
+ */
+struct clk *clk_get_parent_by_index(struct clk *clk,
+				    unsigned int index);
+
+/**
+ * clk_get_num_parents - get number of possible parents
+ * @clk: clock source
+ *
+ * Returns the number of possible parents of this clock,
+ * which can then be enumerated using clk_get_parent_by_index().
+ */
+unsigned int clk_get_num_parents(struct clk *clk);
+
+/**
  * clk_get_sys - get a clock based upon the device name
  * @dev_id: device name
  * @con_id: connection ID
@@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk *clk)
 	return NULL;
 }
 
+struct clk *clk_get_parent_by_index(struct clk *clk,
+				    unsigned int index)
+{
+	return NULL;
+}
+
+unsigned int clk_get_num_parents(struct clk *clk)
+{
+	return 0;
+}
+
 #endif
 
 /* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
__clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
true provider API versions that operate on struct clk_hw.

qoriq-cpufreq needs these functions in order to determine the options
it has for calling clk_set_parent() and thus populate the cpufreq
table, so revive them as legitimate consumer APIs.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/clk.c   | 19 +++++++++++++++++++
 include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 43e2c3a..9436356 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
+unsigned int clk_get_num_parents(struct clk *clk)
+{
+	return !clk ? 0 : clk->core->num_parents;
+}
+EXPORT_SYMBOL_GPL(clk_get_num_parents);
+
 unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
 {
 	return hw->core->num_parents;
@@ -359,6 +365,19 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
 		return core->parents[index];
 }
 
+struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
+{
+	struct clk_core *parent;
+
+	if (!clk)
+		return NULL;
+
+	parent = clk_core_get_parent_by_index(clk->core, index);
+
+	return !parent ? NULL : parent->hw->clk;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
+
 struct clk_hw *
 clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
 {
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0df4a51..937de0e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk *parent);
 struct clk *clk_get_parent(struct clk *clk);
 
 /**
+ * clk_get_parent_by_index - get a possible parent clock by index
+ * @clk: clock source
+ * @index: index into the array of possible parents of this clock
+ *
+ * Returns struct clk corresponding to the requested possible
+ * parent clock source, or NULL.
+ */
+struct clk *clk_get_parent_by_index(struct clk *clk,
+				    unsigned int index);
+
+/**
+ * clk_get_num_parents - get number of possible parents
+ * @clk: clock source
+ *
+ * Returns the number of possible parents of this clock,
+ * which can then be enumerated using clk_get_parent_by_index().
+ */
+unsigned int clk_get_num_parents(struct clk *clk);
+
+/**
  * clk_get_sys - get a clock based upon the device name
  * @dev_id: device name
  * @con_id: connection ID
@@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk *clk)
 	return NULL;
 }
 
+struct clk *clk_get_parent_by_index(struct clk *clk,
+				    unsigned int index)
+{
+	return NULL;
+}
+
+unsigned int clk_get_num_parents(struct clk *clk)
+{
+	return 0;
+}
+
 #endif
 
 /* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
__clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
true provider API versions that operate on struct clk_hw.

qoriq-cpufreq needs these functions in order to determine the options
it has for calling clk_set_parent() and thus populate the cpufreq
table, so revive them as legitimate consumer APIs.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/clk.c   | 19 +++++++++++++++++++
 include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 43e2c3a..9436356 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
+unsigned int clk_get_num_parents(struct clk *clk)
+{
+	return !clk ? 0 : clk->core->num_parents;
+}
+EXPORT_SYMBOL_GPL(clk_get_num_parents);
+
 unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
 {
 	return hw->core->num_parents;
@@ -359,6 +365,19 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
 		return core->parents[index];
 }
 
+struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
+{
+	struct clk_core *parent;
+
+	if (!clk)
+		return NULL;
+
+	parent = clk_core_get_parent_by_index(clk->core, index);
+
+	return !parent ? NULL : parent->hw->clk;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
+
 struct clk_hw *
 clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
 {
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0df4a51..937de0e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk *parent);
 struct clk *clk_get_parent(struct clk *clk);
 
 /**
+ * clk_get_parent_by_index - get a possible parent clock by index
+ * @clk: clock source
+ * @index: index into the array of possible parents of this clock
+ *
+ * Returns struct clk corresponding to the requested possible
+ * parent clock source, or NULL.
+ */
+struct clk *clk_get_parent_by_index(struct clk *clk,
+				    unsigned int index);
+
+/**
+ * clk_get_num_parents - get number of possible parents
+ * @clk: clock source
+ *
+ * Returns the number of possible parents of this clock,
+ * which can then be enumerated using clk_get_parent_by_index().
+ */
+unsigned int clk_get_num_parents(struct clk *clk);
+
+/**
  * clk_get_sys - get a clock based upon the device name
  * @dev_id: device name
  * @con_id: connection ID
@@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk *clk)
 	return NULL;
 }
 
+struct clk *clk_get_parent_by_index(struct clk *clk,
+				    unsigned int index)
+{
+	return NULL;
+}
+
+unsigned int clk_get_num_parents(struct clk *clk)
+{
+	return 0;
+}
+
 #endif
 
 /* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2015-09-20  4:29 ` Scott Wood
  (?)
@ 2015-09-20  4:29   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

Get the CPU clock's potential parent clocks from the clock interface
itself, rather than manually parsing the clocks property to find a
phandle, looking at the clock-names property of that, and assuming that
those are valid parent clocks for the cpu clock.

This is necessary now that the clocks are generated based on the clock
driver's knowledge of the chip rather than a fragile device-tree
description of the mux options.

We can now rely on the clock driver to ensure that the mux only exposes
options that are valid.  The cpufreq driver was currently being overly
conservative in some cases -- for example, the "min_cpufreq =
get_bus_freq()" restriction only applies to chips with erratum
A-004510, and whether the freq_mask used on p5020 is needed depends on
the actual frequencies of the PLLs (FWIW, p5040 has a similar
limitation but its .freq_mask was zero) -- and the frequency mask
mechanism made assumptions about particular parent clock indices that
are no longer valid.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
to clk api usage

 drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
 1 file changed, 40 insertions(+), 97 deletions(-)

diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 358f075..4f53fa2 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -35,53 +35,20 @@ struct cpu_data {
 	struct cpufreq_frequency_table *table;
 };
 
+/*
+ * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
+ * matched a more generic compatible.
+ */
+#define SOC_BLACKLIST		1
+
 /**
  * struct soc_data - SoC specific data
- * @freq_mask: mask the disallowed frequencies
- * @flag: unique flags
+ * @flags: SOC_xxx
  */
 struct soc_data {
-	u32 freq_mask[4];
-	u32 flag;
-};
-
-#define FREQ_MASK	1
-/* see hardware specification for the allowed frqeuencies */
-static const struct soc_data sdata[] = {
-	{ /* used by p2041 and p3041 */
-		.freq_mask = {0x8, 0x8, 0x2, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p5020 */
-		.freq_mask = {0x8, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p4080, p5040 */
-		.freq_mask = {0},
-		.flag = 0,
-	},
+	u32 flags;
 };
 
-/*
- * the minimum allowed core frequency, in Hz
- * for chassis v1.0, >= platform frequency
- * for chassis v2.0, >= platform frequency / 2
- */
-static u32 min_cpufreq;
-static const u32 *fmask;
-
-#if defined(CONFIG_ARM)
-static int get_cpu_physical_id(int cpu)
-{
-	return topology_core_id(cpu);
-}
-#else
-static int get_cpu_physical_id(int cpu)
-{
-	return get_hard_smp_processor_id(cpu);
-}
-#endif
-
 static u32 get_bus_freq(void)
 {
 	struct device_node *soc;
@@ -99,9 +66,10 @@ static u32 get_bus_freq(void)
 	return sysfreq;
 }
 
-static struct device_node *cpu_to_clk_node(int cpu)
+static struct clk *cpu_to_clk(int cpu)
 {
-	struct device_node *np, *clk_np;
+	struct device_node *np;
+	struct clk *clk;
 
 	if (!cpu_present(cpu))
 		return NULL;
@@ -110,37 +78,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
 	if (!np)
 		return NULL;
 
-	clk_np = of_parse_phandle(np, "clocks", 0);
-	if (!clk_np)
-		return NULL;
-
+	clk = of_clk_get(np, 0);
 	of_node_put(np);
-
-	return clk_np;
+	return clk;
 }
 
 /* traverse cpu nodes to get cpu mask of sharing clock wire */
 static void set_affected_cpus(struct cpufreq_policy *policy)
 {
-	struct device_node *np, *clk_np;
 	struct cpumask *dstp = policy->cpus;
+	struct clk *clk;
 	int i;
 
-	np = cpu_to_clk_node(policy->cpu);
-	if (!np)
-		return;
-
 	for_each_present_cpu(i) {
-		clk_np = cpu_to_clk_node(i);
-		if (!clk_np)
+		clk = cpu_to_clk(i);
+		if (IS_ERR(clk)) {
+			pr_err("%s: no clock for cpu %d\n", __func__, i);
 			continue;
+		}
 
-		if (clk_np == np)
+		if (clk_is_match(policy->clk, clk))
 			cpumask_set_cpu(i, dstp);
-
-		of_node_put(clk_np);
 	}
-	of_node_put(np);
 }
 
 /* reduce the duplicated frequencies in frequency table */
@@ -198,7 +157,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
 	struct device_node *np, *pnode;
 	int i, count, ret;
-	u32 freq, mask;
+	u32 freq;
 	struct clk *clk;
 	struct cpufreq_frequency_table *table;
 	struct cpu_data *data;
@@ -219,17 +178,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_nomem2;
 	}
 
-	pnode = of_parse_phandle(np, "clocks", 0);
-	if (!pnode) {
-		pr_err("%s: could not get clock information\n", __func__);
-		goto err_nomem2;
-	}
+	count = clk_get_num_parents(policy->clk);
 
-	count = of_property_count_strings(pnode, "clock-names");
 	data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
 	if (!data->pclk) {
 		pr_err("%s: no memory\n", __func__);
-		goto err_node;
+		goto err_nomem2;
 	}
 
 	table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
@@ -238,23 +192,11 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_pclk;
 	}
 
-	if (fmask)
-		mask = fmask[get_cpu_physical_id(cpu)];
-	else
-		mask = 0x0;
-
 	for (i = 0; i < count; i++) {
-		clk = of_clk_get(pnode, i);
+		clk = clk_get_parent_by_index(policy->clk, i);
 		data->pclk[i] = clk;
 		freq = clk_get_rate(clk);
-		/*
-		 * the clock is valid if its frequency is not masked
-		 * and large than minimum allowed frequency.
-		 */
-		if (freq < min_cpufreq || (mask & (1 << i)))
-			table[i].frequency = CPUFREQ_ENTRY_INVALID;
-		else
-			table[i].frequency = freq / 1000;
+		table[i].frequency = freq / 1000;
 		table[i].driver_data = i;
 	}
 	freq_table_redup(table, count);
@@ -288,10 +230,7 @@ err_nomem1:
 	kfree(table);
 err_pclk:
 	kfree(data->pclk);
-err_node:
-	of_node_put(pnode);
 err_nomem2:
-	policy->driver_data = NULL;
 	kfree(data);
 err_np:
 	of_node_put(np);
@@ -332,12 +271,20 @@ static struct cpufreq_driver qoriq_cpufreq_driver = {
 	.attr		= cpufreq_generic_attr,
 };
 
+static const struct soc_data blacklist = {
+	.flags = SOC_BLACKLIST,
+};
+
 static const struct of_device_id node_matches[] __initconst = {
-	{ .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
-	{ .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
-	{ .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
+	/* e6500 cannot use cpufreq due to erratum A-008083 */
+	{ .compatible = "fsl,b4420-clockgen", &blacklist },
+	{ .compatible = "fsl,b4860-clockgen", &blacklist },
+	{ .compatible = "fsl,t2080-clockgen", &blacklist },
+	{ .compatible = "fsl,t4240-clockgen", &blacklist },
+
+	{ .compatible = "fsl,ls1021a-clockgen", },
+	{ .compatible = "fsl,p4080-clockgen", },
+	{ .compatible = "fsl,qoriq-clockgen-1.0", },
 	{ .compatible = "fsl,qoriq-clockgen-2.0", },
 	{}
 };
@@ -355,16 +302,12 @@ static int __init qoriq_cpufreq_init(void)
 
 	match = of_match_node(node_matches, np);
 	data = match->data;
-	if (data) {
-		if (data->flag)
-			fmask = data->freq_mask;
-		min_cpufreq = get_bus_freq();
-	} else {
-		min_cpufreq = get_bus_freq() / 2;
-	}
 
 	of_node_put(np);
 
+	if (data && data->flags & SOC_BLACKLIST)
+		return -ENODEV;
+
 	ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
 	if (!ret)
 		pr_info("Freescale QorIQ CPU frequency scaling driver\n");
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Viresh Kumar,
	Russell King
  Cc: linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian, Scott Wood

Get the CPU clock's potential parent clocks from the clock interface
itself, rather than manually parsing the clocks property to find a
phandle, looking at the clock-names property of that, and assuming that
those are valid parent clocks for the cpu clock.

This is necessary now that the clocks are generated based on the clock
driver's knowledge of the chip rather than a fragile device-tree
description of the mux options.

We can now rely on the clock driver to ensure that the mux only exposes
options that are valid.  The cpufreq driver was currently being overly
conservative in some cases -- for example, the "min_cpufreq =
get_bus_freq()" restriction only applies to chips with erratum
A-004510, and whether the freq_mask used on p5020 is needed depends on
the actual frequencies of the PLLs (FWIW, p5040 has a similar
limitation but its .freq_mask was zero) -- and the frequency mask
mechanism made assumptions about particular parent clock indices that
are no longer valid.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
to clk api usage

 drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
 1 file changed, 40 insertions(+), 97 deletions(-)

diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 358f075..4f53fa2 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -35,53 +35,20 @@ struct cpu_data {
 	struct cpufreq_frequency_table *table;
 };
 
+/*
+ * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
+ * matched a more generic compatible.
+ */
+#define SOC_BLACKLIST		1
+
 /**
  * struct soc_data - SoC specific data
- * @freq_mask: mask the disallowed frequencies
- * @flag: unique flags
+ * @flags: SOC_xxx
  */
 struct soc_data {
-	u32 freq_mask[4];
-	u32 flag;
-};
-
-#define FREQ_MASK	1
-/* see hardware specification for the allowed frqeuencies */
-static const struct soc_data sdata[] = {
-	{ /* used by p2041 and p3041 */
-		.freq_mask = {0x8, 0x8, 0x2, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p5020 */
-		.freq_mask = {0x8, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p4080, p5040 */
-		.freq_mask = {0},
-		.flag = 0,
-	},
+	u32 flags;
 };
 
-/*
- * the minimum allowed core frequency, in Hz
- * for chassis v1.0, >= platform frequency
- * for chassis v2.0, >= platform frequency / 2
- */
-static u32 min_cpufreq;
-static const u32 *fmask;
-
-#if defined(CONFIG_ARM)
-static int get_cpu_physical_id(int cpu)
-{
-	return topology_core_id(cpu);
-}
-#else
-static int get_cpu_physical_id(int cpu)
-{
-	return get_hard_smp_processor_id(cpu);
-}
-#endif
-
 static u32 get_bus_freq(void)
 {
 	struct device_node *soc;
@@ -99,9 +66,10 @@ static u32 get_bus_freq(void)
 	return sysfreq;
 }
 
-static struct device_node *cpu_to_clk_node(int cpu)
+static struct clk *cpu_to_clk(int cpu)
 {
-	struct device_node *np, *clk_np;
+	struct device_node *np;
+	struct clk *clk;
 
 	if (!cpu_present(cpu))
 		return NULL;
@@ -110,37 +78,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
 	if (!np)
 		return NULL;
 
-	clk_np = of_parse_phandle(np, "clocks", 0);
-	if (!clk_np)
-		return NULL;
-
+	clk = of_clk_get(np, 0);
 	of_node_put(np);
-
-	return clk_np;
+	return clk;
 }
 
 /* traverse cpu nodes to get cpu mask of sharing clock wire */
 static void set_affected_cpus(struct cpufreq_policy *policy)
 {
-	struct device_node *np, *clk_np;
 	struct cpumask *dstp = policy->cpus;
+	struct clk *clk;
 	int i;
 
-	np = cpu_to_clk_node(policy->cpu);
-	if (!np)
-		return;
-
 	for_each_present_cpu(i) {
-		clk_np = cpu_to_clk_node(i);
-		if (!clk_np)
+		clk = cpu_to_clk(i);
+		if (IS_ERR(clk)) {
+			pr_err("%s: no clock for cpu %d\n", __func__, i);
 			continue;
+		}
 
-		if (clk_np == np)
+		if (clk_is_match(policy->clk, clk))
 			cpumask_set_cpu(i, dstp);
-
-		of_node_put(clk_np);
 	}
-	of_node_put(np);
 }
 
 /* reduce the duplicated frequencies in frequency table */
@@ -198,7 +157,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
 	struct device_node *np, *pnode;
 	int i, count, ret;
-	u32 freq, mask;
+	u32 freq;
 	struct clk *clk;
 	struct cpufreq_frequency_table *table;
 	struct cpu_data *data;
@@ -219,17 +178,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_nomem2;
 	}
 
-	pnode = of_parse_phandle(np, "clocks", 0);
-	if (!pnode) {
-		pr_err("%s: could not get clock information\n", __func__);
-		goto err_nomem2;
-	}
+	count = clk_get_num_parents(policy->clk);
 
-	count = of_property_count_strings(pnode, "clock-names");
 	data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
 	if (!data->pclk) {
 		pr_err("%s: no memory\n", __func__);
-		goto err_node;
+		goto err_nomem2;
 	}
 
 	table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
@@ -238,23 +192,11 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_pclk;
 	}
 
-	if (fmask)
-		mask = fmask[get_cpu_physical_id(cpu)];
-	else
-		mask = 0x0;
-
 	for (i = 0; i < count; i++) {
-		clk = of_clk_get(pnode, i);
+		clk = clk_get_parent_by_index(policy->clk, i);
 		data->pclk[i] = clk;
 		freq = clk_get_rate(clk);
-		/*
-		 * the clock is valid if its frequency is not masked
-		 * and large than minimum allowed frequency.
-		 */
-		if (freq < min_cpufreq || (mask & (1 << i)))
-			table[i].frequency = CPUFREQ_ENTRY_INVALID;
-		else
-			table[i].frequency = freq / 1000;
+		table[i].frequency = freq / 1000;
 		table[i].driver_data = i;
 	}
 	freq_table_redup(table, count);
@@ -288,10 +230,7 @@ err_nomem1:
 	kfree(table);
 err_pclk:
 	kfree(data->pclk);
-err_node:
-	of_node_put(pnode);
 err_nomem2:
-	policy->driver_data = NULL;
 	kfree(data);
 err_np:
 	of_node_put(np);
@@ -332,12 +271,20 @@ static struct cpufreq_driver qoriq_cpufreq_driver = {
 	.attr		= cpufreq_generic_attr,
 };
 
+static const struct soc_data blacklist = {
+	.flags = SOC_BLACKLIST,
+};
+
 static const struct of_device_id node_matches[] __initconst = {
-	{ .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
-	{ .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
-	{ .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
+	/* e6500 cannot use cpufreq due to erratum A-008083 */
+	{ .compatible = "fsl,b4420-clockgen", &blacklist },
+	{ .compatible = "fsl,b4860-clockgen", &blacklist },
+	{ .compatible = "fsl,t2080-clockgen", &blacklist },
+	{ .compatible = "fsl,t4240-clockgen", &blacklist },
+
+	{ .compatible = "fsl,ls1021a-clockgen", },
+	{ .compatible = "fsl,p4080-clockgen", },
+	{ .compatible = "fsl,qoriq-clockgen-1.0", },
 	{ .compatible = "fsl,qoriq-clockgen-2.0", },
 	{}
 };
@@ -355,16 +302,12 @@ static int __init qoriq_cpufreq_init(void)
 
 	match = of_match_node(node_matches, np);
 	data = match->data;
-	if (data) {
-		if (data->flag)
-			fmask = data->freq_mask;
-		min_cpufreq = get_bus_freq();
-	} else {
-		min_cpufreq = get_bus_freq() / 2;
-	}
 
 	of_node_put(np);
 
+	if (data && data->flags & SOC_BLACKLIST)
+		return -ENODEV;
+
 	ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
 	if (!ret)
 		pr_info("Freescale QorIQ CPU frequency scaling driver\n");
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-20  4:29   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-20  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

Get the CPU clock's potential parent clocks from the clock interface
itself, rather than manually parsing the clocks property to find a
phandle, looking at the clock-names property of that, and assuming that
those are valid parent clocks for the cpu clock.

This is necessary now that the clocks are generated based on the clock
driver's knowledge of the chip rather than a fragile device-tree
description of the mux options.

We can now rely on the clock driver to ensure that the mux only exposes
options that are valid.  The cpufreq driver was currently being overly
conservative in some cases -- for example, the "min_cpufreq =
get_bus_freq()" restriction only applies to chips with erratum
A-004510, and whether the freq_mask used on p5020 is needed depends on
the actual frequencies of the PLLs (FWIW, p5040 has a similar
limitation but its .freq_mask was zero) -- and the frequency mask
mechanism made assumptions about particular parent clock indices that
are no longer valid.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
to clk api usage

 drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
 1 file changed, 40 insertions(+), 97 deletions(-)

diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 358f075..4f53fa2 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -35,53 +35,20 @@ struct cpu_data {
 	struct cpufreq_frequency_table *table;
 };
 
+/*
+ * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
+ * matched a more generic compatible.
+ */
+#define SOC_BLACKLIST		1
+
 /**
  * struct soc_data - SoC specific data
- * @freq_mask: mask the disallowed frequencies
- * @flag: unique flags
+ * @flags: SOC_xxx
  */
 struct soc_data {
-	u32 freq_mask[4];
-	u32 flag;
-};
-
-#define FREQ_MASK	1
-/* see hardware specification for the allowed frqeuencies */
-static const struct soc_data sdata[] = {
-	{ /* used by p2041 and p3041 */
-		.freq_mask = {0x8, 0x8, 0x2, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p5020 */
-		.freq_mask = {0x8, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p4080, p5040 */
-		.freq_mask = {0},
-		.flag = 0,
-	},
+	u32 flags;
 };
 
-/*
- * the minimum allowed core frequency, in Hz
- * for chassis v1.0, >= platform frequency
- * for chassis v2.0, >= platform frequency / 2
- */
-static u32 min_cpufreq;
-static const u32 *fmask;
-
-#if defined(CONFIG_ARM)
-static int get_cpu_physical_id(int cpu)
-{
-	return topology_core_id(cpu);
-}
-#else
-static int get_cpu_physical_id(int cpu)
-{
-	return get_hard_smp_processor_id(cpu);
-}
-#endif
-
 static u32 get_bus_freq(void)
 {
 	struct device_node *soc;
@@ -99,9 +66,10 @@ static u32 get_bus_freq(void)
 	return sysfreq;
 }
 
-static struct device_node *cpu_to_clk_node(int cpu)
+static struct clk *cpu_to_clk(int cpu)
 {
-	struct device_node *np, *clk_np;
+	struct device_node *np;
+	struct clk *clk;
 
 	if (!cpu_present(cpu))
 		return NULL;
@@ -110,37 +78,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
 	if (!np)
 		return NULL;
 
-	clk_np = of_parse_phandle(np, "clocks", 0);
-	if (!clk_np)
-		return NULL;
-
+	clk = of_clk_get(np, 0);
 	of_node_put(np);
-
-	return clk_np;
+	return clk;
 }
 
 /* traverse cpu nodes to get cpu mask of sharing clock wire */
 static void set_affected_cpus(struct cpufreq_policy *policy)
 {
-	struct device_node *np, *clk_np;
 	struct cpumask *dstp = policy->cpus;
+	struct clk *clk;
 	int i;
 
-	np = cpu_to_clk_node(policy->cpu);
-	if (!np)
-		return;
-
 	for_each_present_cpu(i) {
-		clk_np = cpu_to_clk_node(i);
-		if (!clk_np)
+		clk = cpu_to_clk(i);
+		if (IS_ERR(clk)) {
+			pr_err("%s: no clock for cpu %d\n", __func__, i);
 			continue;
+		}
 
-		if (clk_np == np)
+		if (clk_is_match(policy->clk, clk))
 			cpumask_set_cpu(i, dstp);
-
-		of_node_put(clk_np);
 	}
-	of_node_put(np);
 }
 
 /* reduce the duplicated frequencies in frequency table */
@@ -198,7 +157,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
 	struct device_node *np, *pnode;
 	int i, count, ret;
-	u32 freq, mask;
+	u32 freq;
 	struct clk *clk;
 	struct cpufreq_frequency_table *table;
 	struct cpu_data *data;
@@ -219,17 +178,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_nomem2;
 	}
 
-	pnode = of_parse_phandle(np, "clocks", 0);
-	if (!pnode) {
-		pr_err("%s: could not get clock information\n", __func__);
-		goto err_nomem2;
-	}
+	count = clk_get_num_parents(policy->clk);
 
-	count = of_property_count_strings(pnode, "clock-names");
 	data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
 	if (!data->pclk) {
 		pr_err("%s: no memory\n", __func__);
-		goto err_node;
+		goto err_nomem2;
 	}
 
 	table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
@@ -238,23 +192,11 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_pclk;
 	}
 
-	if (fmask)
-		mask = fmask[get_cpu_physical_id(cpu)];
-	else
-		mask = 0x0;
-
 	for (i = 0; i < count; i++) {
-		clk = of_clk_get(pnode, i);
+		clk = clk_get_parent_by_index(policy->clk, i);
 		data->pclk[i] = clk;
 		freq = clk_get_rate(clk);
-		/*
-		 * the clock is valid if its frequency is not masked
-		 * and large than minimum allowed frequency.
-		 */
-		if (freq < min_cpufreq || (mask & (1 << i)))
-			table[i].frequency = CPUFREQ_ENTRY_INVALID;
-		else
-			table[i].frequency = freq / 1000;
+		table[i].frequency = freq / 1000;
 		table[i].driver_data = i;
 	}
 	freq_table_redup(table, count);
@@ -288,10 +230,7 @@ err_nomem1:
 	kfree(table);
 err_pclk:
 	kfree(data->pclk);
-err_node:
-	of_node_put(pnode);
 err_nomem2:
-	policy->driver_data = NULL;
 	kfree(data);
 err_np:
 	of_node_put(np);
@@ -332,12 +271,20 @@ static struct cpufreq_driver qoriq_cpufreq_driver = {
 	.attr		= cpufreq_generic_attr,
 };
 
+static const struct soc_data blacklist = {
+	.flags = SOC_BLACKLIST,
+};
+
 static const struct of_device_id node_matches[] __initconst = {
-	{ .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
-	{ .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
-	{ .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
+	/* e6500 cannot use cpufreq due to erratum A-008083 */
+	{ .compatible = "fsl,b4420-clockgen", &blacklist },
+	{ .compatible = "fsl,b4860-clockgen", &blacklist },
+	{ .compatible = "fsl,t2080-clockgen", &blacklist },
+	{ .compatible = "fsl,t4240-clockgen", &blacklist },
+
+	{ .compatible = "fsl,ls1021a-clockgen", },
+	{ .compatible = "fsl,p4080-clockgen", },
+	{ .compatible = "fsl,qoriq-clockgen-1.0", },
 	{ .compatible = "fsl,qoriq-clockgen-2.0", },
 	{}
 };
@@ -355,16 +302,12 @@ static int __init qoriq_cpufreq_init(void)
 
 	match = of_match_node(node_matches, np);
 	data = match->data;
-	if (data) {
-		if (data->flag)
-			fmask = data->freq_mask;
-		min_cpufreq = get_bus_freq();
-	} else {
-		min_cpufreq = get_bus_freq() / 2;
-	}
 
 	of_node_put(np);
 
+	if (data && data->flags & SOC_BLACKLIST)
+		return -ENODEV;
+
 	ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
 	if (!ret)
 		pr_info("Freescale QorIQ CPU frequency scaling driver\n");
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2015-09-20  4:29   ` Scott Wood
@ 2015-09-22 19:46     ` Viresh Kumar
  -1 siblings, 0 replies; 50+ messages in thread
From: Viresh Kumar @ 2015-09-22 19:46 UTC (permalink / raw)
  To: Scott Wood
  Cc: Michael Turquette, Stephen Boyd, Rafael J. Wysocki, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On 19-09-15, 23:29, Scott Wood wrote:
> Get the CPU clock's potential parent clocks from the clock interface
> itself, rather than manually parsing the clocks property to find a
> phandle, looking at the clock-names property of that, and assuming that
> those are valid parent clocks for the cpu clock.
> 
> This is necessary now that the clocks are generated based on the clock
> driver's knowledge of the chip rather than a fragile device-tree
> description of the mux options.
> 
> We can now rely on the clock driver to ensure that the mux only exposes
> options that are valid.  The cpufreq driver was currently being overly
> conservative in some cases -- for example, the "min_cpufreq =
> get_bus_freq()" restriction only applies to chips with erratum
> A-004510, and whether the freq_mask used on p5020 is needed depends on
> the actual frequencies of the PLLs (FWIW, p5040 has a similar
> limitation but its .freq_mask was zero) -- and the frequency mask
> mechanism made assumptions about particular parent clock indices that
> are no longer valid.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> to clk api usage
> 
>  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
>  1 file changed, 40 insertions(+), 97 deletions(-)

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

-- 
viresh

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-22 19:46     ` Viresh Kumar
  0 siblings, 0 replies; 50+ messages in thread
From: Viresh Kumar @ 2015-09-22 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 19-09-15, 23:29, Scott Wood wrote:
> Get the CPU clock's potential parent clocks from the clock interface
> itself, rather than manually parsing the clocks property to find a
> phandle, looking at the clock-names property of that, and assuming that
> those are valid parent clocks for the cpu clock.
> 
> This is necessary now that the clocks are generated based on the clock
> driver's knowledge of the chip rather than a fragile device-tree
> description of the mux options.
> 
> We can now rely on the clock driver to ensure that the mux only exposes
> options that are valid.  The cpufreq driver was currently being overly
> conservative in some cases -- for example, the "min_cpufreq =
> get_bus_freq()" restriction only applies to chips with erratum
> A-004510, and whether the freq_mask used on p5020 is needed depends on
> the actual frequencies of the PLLs (FWIW, p5040 has a similar
> limitation but its .freq_mask was zero) -- and the frequency mask
> mechanism made assumptions about particular parent clock indices that
> are no longer valid.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> to clk api usage
> 
>  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
>  1 file changed, 40 insertions(+), 97 deletions(-)

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

-- 
viresh

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2015-09-25 21:42       ` Rafael J. Wysocki
  (?)
@ 2015-09-25 21:17         ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-25 21:17 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Viresh Kumar, Michael Turquette, Stephen Boyd, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > On 19-09-15, 23:29, Scott Wood wrote:
> > > Get the CPU clock's potential parent clocks from the clock interface
> > > itself, rather than manually parsing the clocks property to find a
> > > phandle, looking at the clock-names property of that, and assuming that
> > > those are valid parent clocks for the cpu clock.
> > > 
> > > This is necessary now that the clocks are generated based on the clock
> > > driver's knowledge of the chip rather than a fragile device-tree
> > > description of the mux options.
> > > 
> > > We can now rely on the clock driver to ensure that the mux only exposes
> > > options that are valid.  The cpufreq driver was currently being overly
> > > conservative in some cases -- for example, the "min_cpufreq =
> > > get_bus_freq()" restriction only applies to chips with erratum
> > > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > mechanism made assumptions about particular parent clock indices that
> > > are no longer valid.
> > > 
> > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > ---
> > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > to clk api usage
> > > 
> > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
> > > -------
> > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > 
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> 
> I'm wondering who's supposed to be merging this set?

As I noted in the cover letter, I'm looking for acks so that I can apply 
these to a topic branch which can be pulled through the PPC and ARM trees, 
each of which will have patches that depend on it.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-25 21:17         ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-25 21:17 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Viresh Kumar, Michael Turquette, Stephen Boyd, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > On 19-09-15, 23:29, Scott Wood wrote:
> > > Get the CPU clock's potential parent clocks from the clock interface
> > > itself, rather than manually parsing the clocks property to find a
> > > phandle, looking at the clock-names property of that, and assuming that
> > > those are valid parent clocks for the cpu clock.
> > > 
> > > This is necessary now that the clocks are generated based on the clock
> > > driver's knowledge of the chip rather than a fragile device-tree
> > > description of the mux options.
> > > 
> > > We can now rely on the clock driver to ensure that the mux only exposes
> > > options that are valid.  The cpufreq driver was currently being overly
> > > conservative in some cases -- for example, the "min_cpufreq =
> > > get_bus_freq()" restriction only applies to chips with erratum
> > > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > mechanism made assumptions about particular parent clock indices that
> > > are no longer valid.
> > > 
> > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > ---
> > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > to clk api usage
> > > 
> > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
> > > -------
> > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > 
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> 
> I'm wondering who's supposed to be merging this set?

As I noted in the cover letter, I'm looking for acks so that I can apply 
these to a topic branch which can be pulled through the PPC and ARM trees, 
each of which will have patches that depend on it.

-Scott


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-25 21:17         ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-09-25 21:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > On 19-09-15, 23:29, Scott Wood wrote:
> > > Get the CPU clock's potential parent clocks from the clock interface
> > > itself, rather than manually parsing the clocks property to find a
> > > phandle, looking at the clock-names property of that, and assuming that
> > > those are valid parent clocks for the cpu clock.
> > > 
> > > This is necessary now that the clocks are generated based on the clock
> > > driver's knowledge of the chip rather than a fragile device-tree
> > > description of the mux options.
> > > 
> > > We can now rely on the clock driver to ensure that the mux only exposes
> > > options that are valid.  The cpufreq driver was currently being overly
> > > conservative in some cases -- for example, the "min_cpufreq =
> > > get_bus_freq()" restriction only applies to chips with erratum
> > > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > mechanism made assumptions about particular parent clock indices that
> > > are no longer valid.
> > > 
> > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > ---
> > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > to clk api usage
> > > 
> > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
> > > -------
> > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > 
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> 
> I'm wondering who's supposed to be merging this set?

As I noted in the cover letter, I'm looking for acks so that I can apply 
these to a topic branch which can be pulled through the PPC and ARM trees, 
each of which will have patches that depend on it.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2015-09-22 19:46     ` Viresh Kumar
@ 2015-09-25 21:42       ` Rafael J. Wysocki
  -1 siblings, 0 replies; 50+ messages in thread
From: Rafael J. Wysocki @ 2015-09-25 21:42 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Scott Wood, Michael Turquette, Stephen Boyd, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> On 19-09-15, 23:29, Scott Wood wrote:
> > Get the CPU clock's potential parent clocks from the clock interface
> > itself, rather than manually parsing the clocks property to find a
> > phandle, looking at the clock-names property of that, and assuming that
> > those are valid parent clocks for the cpu clock.
> > 
> > This is necessary now that the clocks are generated based on the clock
> > driver's knowledge of the chip rather than a fragile device-tree
> > description of the mux options.
> > 
> > We can now rely on the clock driver to ensure that the mux only exposes
> > options that are valid.  The cpufreq driver was currently being overly
> > conservative in some cases -- for example, the "min_cpufreq =
> > get_bus_freq()" restriction only applies to chips with erratum
> > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > limitation but its .freq_mask was zero) -- and the frequency mask
> > mechanism made assumptions about particular parent clock indices that
> > are no longer valid.
> > 
> > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > ---
> > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > to clk api usage
> > 
> >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
> >  1 file changed, 40 insertions(+), 97 deletions(-)
> 
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

I'm wondering who's supposed to be merging this set?

Rafael

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-25 21:42       ` Rafael J. Wysocki
  0 siblings, 0 replies; 50+ messages in thread
From: Rafael J. Wysocki @ 2015-09-25 21:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> On 19-09-15, 23:29, Scott Wood wrote:
> > Get the CPU clock's potential parent clocks from the clock interface
> > itself, rather than manually parsing the clocks property to find a
> > phandle, looking at the clock-names property of that, and assuming that
> > those are valid parent clocks for the cpu clock.
> > 
> > This is necessary now that the clocks are generated based on the clock
> > driver's knowledge of the chip rather than a fragile device-tree
> > description of the mux options.
> > 
> > We can now rely on the clock driver to ensure that the mux only exposes
> > options that are valid.  The cpufreq driver was currently being overly
> > conservative in some cases -- for example, the "min_cpufreq =
> > get_bus_freq()" restriction only applies to chips with erratum
> > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > limitation but its .freq_mask was zero) -- and the frequency mask
> > mechanism made assumptions about particular parent clock indices that
> > are no longer valid.
> > 
> > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > ---
> > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > to clk api usage
> > 
> >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++----------------------------
> >  1 file changed, 40 insertions(+), 97 deletions(-)
> 
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

I'm wondering who's supposed to be merging this set?

Rafael

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2015-09-25 21:17         ` Scott Wood
@ 2015-09-25 21:50           ` Rafael J. Wysocki
  -1 siblings, 0 replies; 50+ messages in thread
From: Rafael J. Wysocki @ 2015-09-25 21:50 UTC (permalink / raw)
  To: Scott Wood
  Cc: Viresh Kumar, Michael Turquette, Stephen Boyd, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > Get the CPU clock's potential parent clocks from the clock interface
> > > > itself, rather than manually parsing the clocks property to find a
> > > > phandle, looking at the clock-names property of that, and assuming that
> > > > those are valid parent clocks for the cpu clock.
> > > > 
> > > > This is necessary now that the clocks are generated based on the clock
> > > > driver's knowledge of the chip rather than a fragile device-tree
> > > > description of the mux options.
> > > > 
> > > > We can now rely on the clock driver to ensure that the mux only exposes
> > > > options that are valid.  The cpufreq driver was currently being overly
> > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > > mechanism made assumptions about particular parent clock indices that
> > > > are no longer valid.
> > > > 
> > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > ---
> > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > > to clk api usage
> > > > 
> > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
> > > > -------
> > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > 
> > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > 
> > I'm wondering who's supposed to be merging this set?
> 
> As I noted in the cover letter, I'm looking for acks so that I can apply 
> these to a topic branch which can be pulled through the PPC and ARM trees, 
> each of which will have patches that depend on it.

OK, so no objections from the cpufreq side and you have the ACK from Viresh.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2015-09-25 21:50           ` Rafael J. Wysocki
  0 siblings, 0 replies; 50+ messages in thread
From: Rafael J. Wysocki @ 2015-09-25 21:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > Get the CPU clock's potential parent clocks from the clock interface
> > > > itself, rather than manually parsing the clocks property to find a
> > > > phandle, looking at the clock-names property of that, and assuming that
> > > > those are valid parent clocks for the cpu clock.
> > > > 
> > > > This is necessary now that the clocks are generated based on the clock
> > > > driver's knowledge of the chip rather than a fragile device-tree
> > > > description of the mux options.
> > > > 
> > > > We can now rely on the clock driver to ensure that the mux only exposes
> > > > options that are valid.  The cpufreq driver was currently being overly
> > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > A-004510, and whether the freq_mask used on p5020 is needed depends on
> > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > > mechanism made assumptions about particular parent clock indices that
> > > > are no longer valid.
> > > > 
> > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > ---
> > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > > to clk api usage
> > > > 
> > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
> > > > -------
> > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > 
> > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > 
> > I'm wondering who's supposed to be merging this set?
> 
> As I noted in the cover letter, I'm looking for acks so that I can apply 
> these to a topic branch which can be pulled through the PPC and ARM trees, 
> each of which will have patches that depend on it.

OK, so no objections from the cpufreq side and you have the ACK from Viresh.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 2/5] clk: qoriq: Move chip-specific knowledge into driver
  2015-09-20  4:29   ` Scott Wood
@ 2015-10-15 19:53     ` Stephen Boyd
  -1 siblings, 0 replies; 50+ messages in thread
From: Stephen Boyd @ 2015-10-15 19:53 UTC (permalink / raw)
  To: Scott Wood
  Cc: Michael Turquette, Rafael J. Wysocki, Viresh Kumar, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On 09/19, Scott Wood wrote:
> The device tree should describe the chips (or chip-like subblocks) in
> the system, but it generally does not describe individual registers --
> it should identify, rather than describe, a programming interface.
> 
> This has not been the case with the QorIQ clockgen nodes.  The
> knowledge of what each bit setting of CLKCnCSR means is encoded in
> three places (binding, pll node, and mux node), and the last also needs
> to know which options are valid on a particular chip.  All three of
> these locations are considered stable ABI, making it difficult to fix
> mistakes (of which I have found several), much less refactor the
> abstraction to be able to address problems, limitations, or new chips.
> 
> Under the current binding, a pll clock specifier of 2 means that the
> PLL is divided by 4 -- and the driver implements this, unless there
> happen to be four clock-output-names rather than 3, in which case it
> interprets it as PLL divided by 3.  This does not appear in the binding
> documentation at all.  That hack is now considered stable ABI.
> 
> The current device tree nodes contain errors, such as saying that
> T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options.
> The current binding also ignores some restrictions on clock selection,
> such as p5020's requirement that if a core uses the "wrong" PLL, that
> PLL must be clocked lower than the "correct" PLL and be at most 80% of
> the rated CPU frequency.
> 
> Possibly because of the lack of the ability to express such nuance in
> the binding, some valid options are omitted from the device trees, such
> as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from
> PLL1 (again, only if they are at most 80% of rated CPU frequency).
> This omission, combined with excessive caution in the cpufreq driver
> (addressed in a subsequent patch), means that currently on a 1500 MHz
> p4080 with typical PLL configuration, cpufreq can lower the frequency
> to 1200 MHz on half the CPUs and do nothing on the others.  With this
> patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a
> rev3 p4080 half can be lowered to 750 MHz and the other half to 600
> MHz.
> 
> The current binding only deals with CPU clocks.  To describe FMan in
> the device tree, we need to describe its clock.  Some chips have
> additional muxes that work like the CPU muxes, but are not described in
> the device tree.  Others require inspecting the Reset Control Word to
> determine which PLL is used.  Rather than continue to extend this mess,
> replace it.  Have the driver bind to the chip-specific clockgen
> compatible, and keep the detailed description of quirky chip variations
> in the driver, where it can be easily fixed, refactored, and extended.
> 
> Older device trees will continue to work (including a workaround for
> old ls1021a device trees that are missing compatible and reg in the
> clockgen node, which even the old binding required).  The pll/mux
> details in old device trees will be ignored, but "clocks" properties
> pointing at the old nodes will still work, and be directed at the
> corresponding new clock.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 2/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-10-15 19:53     ` Stephen Boyd
  0 siblings, 0 replies; 50+ messages in thread
From: Stephen Boyd @ 2015-10-15 19:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/19, Scott Wood wrote:
> The device tree should describe the chips (or chip-like subblocks) in
> the system, but it generally does not describe individual registers --
> it should identify, rather than describe, a programming interface.
> 
> This has not been the case with the QorIQ clockgen nodes.  The
> knowledge of what each bit setting of CLKCnCSR means is encoded in
> three places (binding, pll node, and mux node), and the last also needs
> to know which options are valid on a particular chip.  All three of
> these locations are considered stable ABI, making it difficult to fix
> mistakes (of which I have found several), much less refactor the
> abstraction to be able to address problems, limitations, or new chips.
> 
> Under the current binding, a pll clock specifier of 2 means that the
> PLL is divided by 4 -- and the driver implements this, unless there
> happen to be four clock-output-names rather than 3, in which case it
> interprets it as PLL divided by 3.  This does not appear in the binding
> documentation at all.  That hack is now considered stable ABI.
> 
> The current device tree nodes contain errors, such as saying that
> T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options.
> The current binding also ignores some restrictions on clock selection,
> such as p5020's requirement that if a core uses the "wrong" PLL, that
> PLL must be clocked lower than the "correct" PLL and be at most 80% of
> the rated CPU frequency.
> 
> Possibly because of the lack of the ability to express such nuance in
> the binding, some valid options are omitted from the device trees, such
> as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from
> PLL1 (again, only if they are at most 80% of rated CPU frequency).
> This omission, combined with excessive caution in the cpufreq driver
> (addressed in a subsequent patch), means that currently on a 1500 MHz
> p4080 with typical PLL configuration, cpufreq can lower the frequency
> to 1200 MHz on half the CPUs and do nothing on the others.  With this
> patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a
> rev3 p4080 half can be lowered to 750 MHz and the other half to 600
> MHz.
> 
> The current binding only deals with CPU clocks.  To describe FMan in
> the device tree, we need to describe its clock.  Some chips have
> additional muxes that work like the CPU muxes, but are not described in
> the device tree.  Others require inspecting the Reset Control Word to
> determine which PLL is used.  Rather than continue to extend this mess,
> replace it.  Have the driver bind to the chip-specific clockgen
> compatible, and keep the detailed description of quirky chip variations
> in the driver, where it can be easily fixed, refactored, and extended.
> 
> Older device trees will continue to work (including a workaround for
> old ls1021a device trees that are missing compatible and reg in the
> clockgen node, which even the old binding required).  The pll/mux
> details in old device trees will be ignored, but "clocks" properties
> pointing at the old nodes will still work, and be directed at the
> corresponding new clock.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 3/5] clk: qoriq: Add ls2080a support.
  2015-09-20  4:29   ` Scott Wood
@ 2015-10-15 19:53     ` Stephen Boyd
  -1 siblings, 0 replies; 50+ messages in thread
From: Stephen Boyd @ 2015-10-15 19:53 UTC (permalink / raw)
  To: Scott Wood
  Cc: Michael Turquette, Rafael J. Wysocki, Viresh Kumar, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On 09/19, Scott Wood wrote:
> LS2080A is the first implementation of the chassis 3 clockgen, which
> has a different register layout than previous chips.  It is also little
> endian, unlike previous chips.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 3/5] clk: qoriq: Add ls2080a support.
@ 2015-10-15 19:53     ` Stephen Boyd
  0 siblings, 0 replies; 50+ messages in thread
From: Stephen Boyd @ 2015-10-15 19:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/19, Scott Wood wrote:
> LS2080A is the first implementation of the chassis 3 clockgen, which
> has a different register layout than previous chips.  It is also little
> endian, unlike previous chips.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
  2015-09-20  4:29   ` Scott Wood
  (?)
@ 2015-10-15 20:03     ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-10-15 20:03 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Rafael J. Wysocki, Viresh Kumar, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
> __clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
> true provider API versions that operate on struct clk_hw.
> 
> qoriq-cpufreq needs these functions in order to determine the options
> it has for calling clk_set_parent() and thus populate the cpufreq
> table, so revive them as legitimate consumer APIs.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v3: new patch
> 
>  drivers/clk/clk.c   | 19 +++++++++++++++++++
>  include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 50 insertions(+)

Russell, could you ACK this if there are no objections?

Thanks,
Scott

> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 43e2c3a..9436356 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(__clk_get_hw);
>  
> +unsigned int clk_get_num_parents(struct clk *clk)
> +{
> +     return !clk ? 0 : clk->core->num_parents;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_num_parents);
> +
>  unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
>  {
>       return hw->core->num_parents;
> @@ -359,6 +365,19 @@ static struct clk_core 
> *clk_core_get_parent_by_index(struct clk_core *core,
>               return core->parents[index];
>  }
>  
> +struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
> +{
> +     struct clk_core *parent;
> +
> +     if (!clk)
> +             return NULL;
> +
> +     parent = clk_core_get_parent_by_index(clk->core, index);
> +
> +     return !parent ? NULL : parent->hw->clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
> +
>  struct clk_hw *
>  clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
>  {
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 0df4a51..937de0e 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk 
> *parent);
>  struct clk *clk_get_parent(struct clk *clk);
>  
>  /**
> + * clk_get_parent_by_index - get a possible parent clock by index
> + * @clk: clock source
> + * @index: index into the array of possible parents of this clock
> + *
> + * Returns struct clk corresponding to the requested possible
> + * parent clock source, or NULL.
> + */
> +struct clk *clk_get_parent_by_index(struct clk *clk,
> +                                 unsigned int index);
> +
> +/**
> + * clk_get_num_parents - get number of possible parents
> + * @clk: clock source
> + *
> + * Returns the number of possible parents of this clock,
> + * which can then be enumerated using clk_get_parent_by_index().
> + */
> +unsigned int clk_get_num_parents(struct clk *clk);
> +
> +/**
>   * clk_get_sys - get a clock based upon the device name
>   * @dev_id: device name
>   * @con_id: connection ID
> @@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk 
> *clk)
>       return NULL;
>  }
>  
> +struct clk *clk_get_parent_by_index(struct clk *clk,
> +                                 unsigned int index)
> +{
> +     return NULL;
> +}
> +
> +unsigned int clk_get_num_parents(struct clk *clk)
> +{
> +     return 0;
> +}
> +
>  #endif
>  
>  /* clk_prepare_enable helps cases using clk_enable in non-atomic context. 
> */

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
@ 2015-10-15 20:03     ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-10-15 20:03 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Rafael J. Wysocki, Viresh Kumar, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
> __clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
> true provider API versions that operate on struct clk_hw.
> 
> qoriq-cpufreq needs these functions in order to determine the options
> it has for calling clk_set_parent() and thus populate the cpufreq
> table, so revive them as legitimate consumer APIs.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v3: new patch
> 
>  drivers/clk/clk.c   | 19 +++++++++++++++++++
>  include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 50 insertions(+)

Russell, could you ACK this if there are no objections?

Thanks,
Scott

> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 43e2c3a..9436356 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(__clk_get_hw);
>  
> +unsigned int clk_get_num_parents(struct clk *clk)
> +{
> +     return !clk ? 0 : clk->core->num_parents;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_num_parents);
> +
>  unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
>  {
>       return hw->core->num_parents;
> @@ -359,6 +365,19 @@ static struct clk_core 
> *clk_core_get_parent_by_index(struct clk_core *core,
>               return core->parents[index];
>  }
>  
> +struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
> +{
> +     struct clk_core *parent;
> +
> +     if (!clk)
> +             return NULL;
> +
> +     parent = clk_core_get_parent_by_index(clk->core, index);
> +
> +     return !parent ? NULL : parent->hw->clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
> +
>  struct clk_hw *
>  clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
>  {
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 0df4a51..937de0e 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk 
> *parent);
>  struct clk *clk_get_parent(struct clk *clk);
>  
>  /**
> + * clk_get_parent_by_index - get a possible parent clock by index
> + * @clk: clock source
> + * @index: index into the array of possible parents of this clock
> + *
> + * Returns struct clk corresponding to the requested possible
> + * parent clock source, or NULL.
> + */
> +struct clk *clk_get_parent_by_index(struct clk *clk,
> +                                 unsigned int index);
> +
> +/**
> + * clk_get_num_parents - get number of possible parents
> + * @clk: clock source
> + *
> + * Returns the number of possible parents of this clock,
> + * which can then be enumerated using clk_get_parent_by_index().
> + */
> +unsigned int clk_get_num_parents(struct clk *clk);
> +
> +/**
>   * clk_get_sys - get a clock based upon the device name
>   * @dev_id: device name
>   * @con_id: connection ID
> @@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk 
> *clk)
>       return NULL;
>  }
>  
> +struct clk *clk_get_parent_by_index(struct clk *clk,
> +                                 unsigned int index)
> +{
> +     return NULL;
> +}
> +
> +unsigned int clk_get_num_parents(struct clk *clk)
> +{
> +     return 0;
> +}
> +
>  #endif
>  
>  /* clk_prepare_enable helps cases using clk_enable in non-atomic context. 
> */

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
@ 2015-10-15 20:03     ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-10-15 20:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
> __clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
> true provider API versions that operate on struct clk_hw.
> 
> qoriq-cpufreq needs these functions in order to determine the options
> it has for calling clk_set_parent() and thus populate the cpufreq
> table, so revive them as legitimate consumer APIs.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v3: new patch
> 
>  drivers/clk/clk.c   | 19 +++++++++++++++++++
>  include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 50 insertions(+)

Russell, could you ACK this if there are no objections?

Thanks,
Scott

> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 43e2c3a..9436356 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(__clk_get_hw);
>  
> +unsigned int clk_get_num_parents(struct clk *clk)
> +{
> +     return !clk ? 0 : clk->core->num_parents;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_num_parents);
> +
>  unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
>  {
>       return hw->core->num_parents;
> @@ -359,6 +365,19 @@ static struct clk_core 
> *clk_core_get_parent_by_index(struct clk_core *core,
>               return core->parents[index];
>  }
>  
> +struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
> +{
> +     struct clk_core *parent;
> +
> +     if (!clk)
> +             return NULL;
> +
> +     parent = clk_core_get_parent_by_index(clk->core, index);
> +
> +     return !parent ? NULL : parent->hw->clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
> +
>  struct clk_hw *
>  clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
>  {
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 0df4a51..937de0e 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk 
> *parent);
>  struct clk *clk_get_parent(struct clk *clk);
>  
>  /**
> + * clk_get_parent_by_index - get a possible parent clock by index
> + * @clk: clock source
> + * @index: index into the array of possible parents of this clock
> + *
> + * Returns struct clk corresponding to the requested possible
> + * parent clock source, or NULL.
> + */
> +struct clk *clk_get_parent_by_index(struct clk *clk,
> +                                 unsigned int index);
> +
> +/**
> + * clk_get_num_parents - get number of possible parents
> + * @clk: clock source
> + *
> + * Returns the number of possible parents of this clock,
> + * which can then be enumerated using clk_get_parent_by_index().
> + */
> +unsigned int clk_get_num_parents(struct clk *clk);
> +
> +/**
>   * clk_get_sys - get a clock based upon the device name
>   * @dev_id: device name
>   * @con_id: connection ID
> @@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk 
> *clk)
>       return NULL;
>  }
>  
> +struct clk *clk_get_parent_by_index(struct clk *clk,
> +                                 unsigned int index)
> +{
> +     return NULL;
> +}
> +
> +unsigned int clk_get_num_parents(struct clk *clk)
> +{
> +     return 0;
> +}
> +
>  #endif
>  
>  /* clk_prepare_enable helps cases using clk_enable in non-atomic context. 
> */

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver
  2015-09-20  4:29 ` Scott Wood
  (?)
@ 2015-10-23 22:39   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-10-23 22:39 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: Rafael J. Wysocki, Viresh Kumar, Russell King, linux-clk,
	linux-pm, linuxppc-dev, linux-arm-kernel, Tang Yuantian, javier,
	Bhupesh Sharma, Russell King, Arnd Bergmann

On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> The existing device tree bindings are error-prone and inflexible. 
> Correct the mistake by moving the knowledge into the driver, which has
> more flexibility in describing the quirks of each chip.  This leaves the
> device tree to its proper role of identifying a programming interface
> rather than describing its individual registers.
> 
> For more detail, see the commit message of patch 2.
> 
> As there are both ARM and PPC patches that depend on this patchset, I'm
> requesting ACKs from clk and cpufreq in order to put this into a topic
> branch that both ARM and PPC can pull.
> 
> Scott Wood (5):
>   powerpc/fsl: Move fsl_guts.h out of arch/powerpc
>   clk: qoriq: Move chip-specific knowledge into driver
>   clk: qoriq: Add ls2080a support.
>   clk: Add consumer APIs for discovering possible parent clocks
>   cpufreq: qoriq: Don't look at clock implementation details

I've applied the first three patches plus 
http://patchwork.ozlabs.org/patch/534739/ to the clock branch of 
scottwood/linux.git to be used as a basis for PPC and ARM device tree patches.

Note that there is a trivial merge conflict with commit 
4a7748c3d6419bb8178748 ("clk: Allow drivers to build if COMPILE_TEST is 
enabled").  Another option is for these patches to go via the clk tree, and 
the device tree patches will ust go separately.  This would result in 
intermediate commits where the device tree contains clock information that 
the clock driver can't handle, but it would be resolved by -rc1 -- and it 
seems that one of the ARM device tree patches ("dts/ls2080a: Update DTSI to 
add support of various peripherals") was already merged without waiting for 
the clock driver patch.  I could still wait until next merge window to rip 
out the legacy stuff from existing device trees, so it would only affect new 
functionality.

Patch 4 is still waiting for an ack from Russell King, but it appears that 
patch 5 (which depends on patch 4) can probably wait until the next merge 
window.  Without those patches, qoriq-cpufreq should still mostly work, as 
long as the old device trees are used.  Patches 4 and 5 will be needed to 
make qoriq-cpufreq continue to work with device trees using the new binding.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-10-23 22:39   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-10-23 22:39 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: Rafael J. Wysocki, Viresh Kumar, Russell King, linux-clk,
	linux-pm, linuxppc-dev, linux-arm-kernel, Tang Yuantian, javier,
	Bhupesh Sharma

On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> The existing device tree bindings are error-prone and inflexible. 
> Correct the mistake by moving the knowledge into the driver, which has
> more flexibility in describing the quirks of each chip.  This leaves the
> device tree to its proper role of identifying a programming interface
> rather than describing its individual registers.
> 
> For more detail, see the commit message of patch 2.
> 
> As there are both ARM and PPC patches that depend on this patchset, I'm
> requesting ACKs from clk and cpufreq in order to put this into a topic
> branch that both ARM and PPC can pull.
> 
> Scott Wood (5):
>   powerpc/fsl: Move fsl_guts.h out of arch/powerpc
>   clk: qoriq: Move chip-specific knowledge into driver
>   clk: qoriq: Add ls2080a support.
>   clk: Add consumer APIs for discovering possible parent clocks
>   cpufreq: qoriq: Don't look at clock implementation details

I've applied the first three patches plus 
http://patchwork.ozlabs.org/patch/534739/ to the clock branch of 
scottwood/linux.git to be used as a basis for PPC and ARM device tree patches.

Note that there is a trivial merge conflict with commit 
4a7748c3d6419bb8178748 ("clk: Allow drivers to build if COMPILE_TEST is 
enabled").  Another option is for these patches to go via the clk tree, and 
the device tree patches will ust go separately.  This would result in 
intermediate commits where the device tree contains clock information that 
the clock driver can't handle, but it would be resolved by -rc1 -- and it 
seems that one of the ARM device tree patches ("dts/ls2080a: Update DTSI to 
add support of various peripherals") was already merged without waiting for 
the clock driver patch.  I could still wait until next merge window to rip 
out the legacy stuff from existing device trees, so it would only affect new 
functionality.

Patch 4 is still waiting for an ack from Russell King, but it appears that 
patch 5 (which depends on patch 4) can probably wait until the next merge 
window.  Without those patches, qoriq-cpufreq should still mostly work, as 
long as the old device trees are used.  Patches 4 and 5 will be needed to 
make qoriq-cpufreq continue to work with device trees using the new binding.

-Scott


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver
@ 2015-10-23 22:39   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-10-23 22:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> The existing device tree bindings are error-prone and inflexible. 
> Correct the mistake by moving the knowledge into the driver, which has
> more flexibility in describing the quirks of each chip.  This leaves the
> device tree to its proper role of identifying a programming interface
> rather than describing its individual registers.
> 
> For more detail, see the commit message of patch 2.
> 
> As there are both ARM and PPC patches that depend on this patchset, I'm
> requesting ACKs from clk and cpufreq in order to put this into a topic
> branch that both ARM and PPC can pull.
> 
> Scott Wood (5):
>   powerpc/fsl: Move fsl_guts.h out of arch/powerpc
>   clk: qoriq: Move chip-specific knowledge into driver
>   clk: qoriq: Add ls2080a support.
>   clk: Add consumer APIs for discovering possible parent clocks
>   cpufreq: qoriq: Don't look at clock implementation details

I've applied the first three patches plus 
http://patchwork.ozlabs.org/patch/534739/ to the clock branch of 
scottwood/linux.git to be used as a basis for PPC and ARM device tree patches.

Note that there is a trivial merge conflict with commit 
4a7748c3d6419bb8178748 ("clk: Allow drivers to build if COMPILE_TEST is 
enabled").  Another option is for these patches to go via the clk tree, and 
the device tree patches will ust go separately.  This would result in 
intermediate commits where the device tree contains clock information that 
the clock driver can't handle, but it would be resolved by -rc1 -- and it 
seems that one of the ARM device tree patches ("dts/ls2080a: Update DTSI to 
add support of various peripherals") was already merged without waiting for 
the clock driver patch.  I could still wait until next merge window to rip 
out the legacy stuff from existing device trees, so it would only affect new 
functionality.

Patch 4 is still waiting for an ack from Russell King, but it appears that 
patch 5 (which depends on patch 4) can probably wait until the next merge 
window.  Without those patches, qoriq-cpufreq should still mostly work, as 
long as the old device trees are used.  Patches 4 and 5 will be needed to 
make qoriq-cpufreq continue to work with device trees using the new binding.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
  2015-10-15 20:03     ` Scott Wood
  (?)
@ 2015-12-07 20:44       ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-12-07 20:44 UTC (permalink / raw)
  To: Russell King
  Cc: Stephen Boyd, Michael Turquette, Rafael J. Wysocki, Viresh Kumar,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Thu, 2015-10-15 at 15:03 -0500, Scott Wood wrote:
> On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> > Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
> > __clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
> > true provider API versions that operate on struct clk_hw.
> > 
> > qoriq-cpufreq needs these functions in order to determine the options
> > it has for calling clk_set_parent() and thus populate the cpufreq
> > table, so revive them as legitimate consumer APIs.
> > 
> > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > ---
> > v3: new patch
> > 
> >  drivers/clk/clk.c   | 19 +++++++++++++++++++
> >  include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
> >  2 files changed, 50 insertions(+)
> 
> Russell, could you ACK this if there are no objections?
> 
> Thanks,
> Scott

ping?

-Scott

> 
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 43e2c3a..9436356 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(__clk_get_hw);
> >  
> > +unsigned int clk_get_num_parents(struct clk *clk)
> > +{
> > +     return !clk ? 0 : clk->core->num_parents;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_num_parents);
> > +
> >  unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
> >  {
> >       return hw->core->num_parents;
> > @@ -359,6 +365,19 @@ static struct clk_core 
> > *clk_core_get_parent_by_index(struct clk_core *core,
> >               return core->parents[index];
> >  }
> >  
> > +struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
> > +{
> > +     struct clk_core *parent;
> > +
> > +     if (!clk)
> > +             return NULL;
> > +
> > +     parent = clk_core_get_parent_by_index(clk->core, index);
> > +
> > +     return !parent ? NULL : parent->hw->clk;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
> > +
> >  struct clk_hw *
> >  clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
> >  {
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 0df4a51..937de0e 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk 
> > *parent);
> >  struct clk *clk_get_parent(struct clk *clk);
> >  
> >  /**
> > + * clk_get_parent_by_index - get a possible parent clock by index
> > + * @clk: clock source
> > + * @index: index into the array of possible parents of this clock
> > + *
> > + * Returns struct clk corresponding to the requested possible
> > + * parent clock source, or NULL.
> > + */
> > +struct clk *clk_get_parent_by_index(struct clk *clk,
> > +                                 unsigned int index);
> > +
> > +/**
> > + * clk_get_num_parents - get number of possible parents
> > + * @clk: clock source
> > + *
> > + * Returns the number of possible parents of this clock,
> > + * which can then be enumerated using clk_get_parent_by_index().
> > + */
> > +unsigned int clk_get_num_parents(struct clk *clk);
> > +
> > +/**
> >   * clk_get_sys - get a clock based upon the device name
> >   * @dev_id: device name
> >   * @con_id: connection ID
> > @@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk 
> > *clk)
> >       return NULL;
> >  }
> >  
> > +struct clk *clk_get_parent_by_index(struct clk *clk,
> > +                                 unsigned int index)
> > +{
> > +     return NULL;
> > +}
> > +
> > +unsigned int clk_get_num_parents(struct clk *clk)
> > +{
> > +     return 0;
> > +}
> > +
> >  #endif
> >  
> >  /* clk_prepare_enable helps cases using clk_enable in non-atomic context.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
@ 2015-12-07 20:44       ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-12-07 20:44 UTC (permalink / raw)
  To: Russell King
  Cc: Stephen Boyd, Michael Turquette, Rafael J. Wysocki, Viresh Kumar,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Thu, 2015-10-15 at 15:03 -0500, Scott Wood wrote:
> On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> > Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
> > __clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
> > true provider API versions that operate on struct clk_hw.
> > 
> > qoriq-cpufreq needs these functions in order to determine the options
> > it has for calling clk_set_parent() and thus populate the cpufreq
> > table, so revive them as legitimate consumer APIs.
> > 
> > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > ---
> > v3: new patch
> > 
> >  drivers/clk/clk.c   | 19 +++++++++++++++++++
> >  include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
> >  2 files changed, 50 insertions(+)
> 
> Russell, could you ACK this if there are no objections?
> 
> Thanks,
> Scott

ping?

-Scott

> 
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 43e2c3a..9436356 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(__clk_get_hw);
> >  
> > +unsigned int clk_get_num_parents(struct clk *clk)
> > +{
> > +     return !clk ? 0 : clk->core->num_parents;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_num_parents);
> > +
> >  unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
> >  {
> >       return hw->core->num_parents;
> > @@ -359,6 +365,19 @@ static struct clk_core 
> > *clk_core_get_parent_by_index(struct clk_core *core,
> >               return core->parents[index];
> >  }
> >  
> > +struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
> > +{
> > +     struct clk_core *parent;
> > +
> > +     if (!clk)
> > +             return NULL;
> > +
> > +     parent = clk_core_get_parent_by_index(clk->core, index);
> > +
> > +     return !parent ? NULL : parent->hw->clk;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
> > +
> >  struct clk_hw *
> >  clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
> >  {
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 0df4a51..937de0e 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk 
> > *parent);
> >  struct clk *clk_get_parent(struct clk *clk);
> >  
> >  /**
> > + * clk_get_parent_by_index - get a possible parent clock by index
> > + * @clk: clock source
> > + * @index: index into the array of possible parents of this clock
> > + *
> > + * Returns struct clk corresponding to the requested possible
> > + * parent clock source, or NULL.
> > + */
> > +struct clk *clk_get_parent_by_index(struct clk *clk,
> > +                                 unsigned int index);
> > +
> > +/**
> > + * clk_get_num_parents - get number of possible parents
> > + * @clk: clock source
> > + *
> > + * Returns the number of possible parents of this clock,
> > + * which can then be enumerated using clk_get_parent_by_index().
> > + */
> > +unsigned int clk_get_num_parents(struct clk *clk);
> > +
> > +/**
> >   * clk_get_sys - get a clock based upon the device name
> >   * @dev_id: device name
> >   * @con_id: connection ID
> > @@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk 
> > *clk)
> >       return NULL;
> >  }
> >  
> > +struct clk *clk_get_parent_by_index(struct clk *clk,
> > +                                 unsigned int index)
> > +{
> > +     return NULL;
> > +}
> > +
> > +unsigned int clk_get_num_parents(struct clk *clk)
> > +{
> > +     return 0;
> > +}
> > +
> >  #endif
> >  
> >  /* clk_prepare_enable helps cases using clk_enable in non-atomic context.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks
@ 2015-12-07 20:44       ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2015-12-07 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2015-10-15 at 15:03 -0500, Scott Wood wrote:
> On Sat, 2015-09-19 at 23:29 -0500, Scott Wood wrote:
> > Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
> > __clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
> > true provider API versions that operate on struct clk_hw.
> > 
> > qoriq-cpufreq needs these functions in order to determine the options
> > it has for calling clk_set_parent() and thus populate the cpufreq
> > table, so revive them as legitimate consumer APIs.
> > 
> > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > ---
> > v3: new patch
> > 
> >  drivers/clk/clk.c   | 19 +++++++++++++++++++
> >  include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
> >  2 files changed, 50 insertions(+)
> 
> Russell, could you ACK this if there are no objections?
> 
> Thanks,
> Scott

ping?

-Scott

> 
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 43e2c3a..9436356 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -290,6 +290,12 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(__clk_get_hw);
> >  
> > +unsigned int clk_get_num_parents(struct clk *clk)
> > +{
> > +     return !clk ? 0 : clk->core->num_parents;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_num_parents);
> > +
> >  unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
> >  {
> >       return hw->core->num_parents;
> > @@ -359,6 +365,19 @@ static struct clk_core 
> > *clk_core_get_parent_by_index(struct clk_core *core,
> >               return core->parents[index];
> >  }
> >  
> > +struct clk *clk_get_parent_by_index(struct clk *clk, unsigned int index)
> > +{
> > +     struct clk_core *parent;
> > +
> > +     if (!clk)
> > +             return NULL;
> > +
> > +     parent = clk_core_get_parent_by_index(clk->core, index);
> > +
> > +     return !parent ? NULL : parent->hw->clk;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
> > +
> >  struct clk_hw *
> >  clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
> >  {
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 0df4a51..937de0e 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -392,6 +392,26 @@ int clk_set_parent(struct clk *clk, struct clk 
> > *parent);
> >  struct clk *clk_get_parent(struct clk *clk);
> >  
> >  /**
> > + * clk_get_parent_by_index - get a possible parent clock by index
> > + * @clk: clock source
> > + * @index: index into the array of possible parents of this clock
> > + *
> > + * Returns struct clk corresponding to the requested possible
> > + * parent clock source, or NULL.
> > + */
> > +struct clk *clk_get_parent_by_index(struct clk *clk,
> > +                                 unsigned int index);
> > +
> > +/**
> > + * clk_get_num_parents - get number of possible parents
> > + * @clk: clock source
> > + *
> > + * Returns the number of possible parents of this clock,
> > + * which can then be enumerated using clk_get_parent_by_index().
> > + */
> > +unsigned int clk_get_num_parents(struct clk *clk);
> > +
> > +/**
> >   * clk_get_sys - get a clock based upon the device name
> >   * @dev_id: device name
> >   * @con_id: connection ID
> > @@ -461,6 +481,17 @@ static inline struct clk *clk_get_parent(struct clk 
> > *clk)
> >       return NULL;
> >  }
> >  
> > +struct clk *clk_get_parent_by_index(struct clk *clk,
> > +                                 unsigned int index)
> > +{
> > +     return NULL;
> > +}
> > +
> > +unsigned int clk_get_num_parents(struct clk *clk)
> > +{
> > +     return 0;
> > +}
> > +
> >  #endif
> >  
> >  /* clk_prepare_enable helps cases using clk_enable in non-atomic context.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2015-09-25 21:50           ` Rafael J. Wysocki
@ 2016-02-26 18:14             ` Li Yang
  -1 siblings, 0 replies; 50+ messages in thread
From: Li Yang @ 2016-02-26 18:14 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Scott Wood, Viresh Kumar, Michael Turquette, Stephen Boyd,
	Russell King, linux-clk, linux-pm, linuxppc-dev,
	linux-arm-kernel, Tang Yuantian

On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
>> On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
>> > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
>> > > On 19-09-15, 23:29, Scott Wood wrote:
>> > > > Get the CPU clock's potential parent clocks from the clock interface
>> > > > itself, rather than manually parsing the clocks property to find a
>> > > > phandle, looking at the clock-names property of that, and assuming that
>> > > > those are valid parent clocks for the cpu clock.
>> > > >
>> > > > This is necessary now that the clocks are generated based on the clock
>> > > > driver's knowledge of the chip rather than a fragile device-tree
>> > > > description of the mux options.
>> > > >
>> > > > We can now rely on the clock driver to ensure that the mux only exposes
>> > > > options that are valid.  The cpufreq driver was currently being overly
>> > > > conservative in some cases -- for example, the "min_cpufreq =
>> > > > get_bus_freq()" restriction only applies to chips with erratum
>> > > > A-004510, and whether the freq_mask used on p5020 is needed depends on
>> > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
>> > > > limitation but its .freq_mask was zero) -- and the frequency mask
>> > > > mechanism made assumptions about particular parent clock indices that
>> > > > are no longer valid.
>> > > >
>> > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
>> > > > ---
>> > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
>> > > > to clk api usage
>> > > >
>> > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
>> > > > -------
>> > > >  1 file changed, 40 insertions(+), 97 deletions(-)
>> > >
>> > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> >
>> > I'm wondering who's supposed to be merging this set?
>>
>> As I noted in the cover letter, I'm looking for acks so that I can apply
>> these to a topic branch which can be pulled through the PPC and ARM trees,
>> each of which will have patches that depend on it.
>
> OK, so no objections from the cpufreq side and you have the ACK from Viresh.

Hi Scott,

Did you drop this patch later?  I can not find it in 4.5-rc still.

Regards,
Leo

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2016-02-26 18:14             ` Li Yang
  0 siblings, 0 replies; 50+ messages in thread
From: Li Yang @ 2016-02-26 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
>> On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
>> > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
>> > > On 19-09-15, 23:29, Scott Wood wrote:
>> > > > Get the CPU clock's potential parent clocks from the clock interface
>> > > > itself, rather than manually parsing the clocks property to find a
>> > > > phandle, looking at the clock-names property of that, and assuming that
>> > > > those are valid parent clocks for the cpu clock.
>> > > >
>> > > > This is necessary now that the clocks are generated based on the clock
>> > > > driver's knowledge of the chip rather than a fragile device-tree
>> > > > description of the mux options.
>> > > >
>> > > > We can now rely on the clock driver to ensure that the mux only exposes
>> > > > options that are valid.  The cpufreq driver was currently being overly
>> > > > conservative in some cases -- for example, the "min_cpufreq =
>> > > > get_bus_freq()" restriction only applies to chips with erratum
>> > > > A-004510, and whether the freq_mask used on p5020 is needed depends on
>> > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
>> > > > limitation but its .freq_mask was zero) -- and the frequency mask
>> > > > mechanism made assumptions about particular parent clock indices that
>> > > > are no longer valid.
>> > > >
>> > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
>> > > > ---
>> > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
>> > > > to clk api usage
>> > > >
>> > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------------
>> > > > -------
>> > > >  1 file changed, 40 insertions(+), 97 deletions(-)
>> > >
>> > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> >
>> > I'm wondering who's supposed to be merging this set?
>>
>> As I noted in the cover letter, I'm looking for acks so that I can apply
>> these to a topic branch which can be pulled through the PPC and ARM trees,
>> each of which will have patches that depend on it.
>
> OK, so no objections from the cpufreq side and you have the ACK from Viresh.

Hi Scott,

Did you drop this patch later?  I can not find it in 4.5-rc still.

Regards,
Leo

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2016-02-26 18:14             ` Li Yang
  (?)
@ 2016-02-26 18:16               ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2016-02-26 18:16 UTC (permalink / raw)
  To: Li Yang, Rafael J. Wysocki
  Cc: Viresh Kumar, Michael Turquette, Stephen Boyd, Russell King,
	linux-clk, linux-pm, linuxppc-dev, linux-arm-kernel,
	Tang Yuantian

On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
> On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
> wrote:
> > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > > > Get the CPU clock's potential parent clocks from the clock
> > > > > > interface
> > > > > > itself, rather than manually parsing the clocks property to find a
> > > > > > phandle, looking at the clock-names property of that, and assuming
> > > > > > that
> > > > > > those are valid parent clocks for the cpu clock.
> > > > > > 
> > > > > > This is necessary now that the clocks are generated based on the
> > > > > > clock
> > > > > > driver's knowledge of the chip rather than a fragile device-tree
> > > > > > description of the mux options.
> > > > > > 
> > > > > > We can now rely on the clock driver to ensure that the mux only
> > > > > > exposes
> > > > > > options that are valid.  The cpufreq driver was currently being
> > > > > > overly
> > > > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > > > A-004510, and whether the freq_mask used on p5020 is needed
> > > > > > depends on
> > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > > > > mechanism made assumptions about particular parent clock indices
> > > > > > that
> > > > > > are no longer valid.
> > > > > > 
> > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > > > ---
> > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > > > > to clk api usage
> > > > > > 
> > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------
> > > > > > ------
> > > > > > -------
> > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > > > 
> > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > > 
> > > > I'm wondering who's supposed to be merging this set?
> > > 
> > > As I noted in the cover letter, I'm looking for acks so that I can apply
> > > these to a topic branch which can be pulled through the PPC and ARM
> > > trees,
> > > each of which will have patches that depend on it.
> > 
> > OK, so no objections from the cpufreq side and you have the ACK from
> > Viresh.
> 
> Hi Scott,
> 
> Did you drop this patch later?  I can not find it in 4.5-rc still.

I was asked to get an ack from Russell King patch 4/5, which this patch
requires.  Despite repeated pings, I could not get a reply from Russell King.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2016-02-26 18:16               ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2016-02-26 18:16 UTC (permalink / raw)
  To: Li Yang, Rafael J. Wysocki
  Cc: Russell King, linux-pm, Viresh Kumar, Michael Turquette,
	Stephen Boyd, Tang Yuantian, linuxppc-dev, linux-clk,
	linux-arm-kernel

On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
> On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
> wrote:
> > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > > > Get the CPU clock's potential parent clocks from the clock
> > > > > > interface
> > > > > > itself, rather than manually parsing the clocks property to find a
> > > > > > phandle, looking at the clock-names property of that, and assuming
> > > > > > that
> > > > > > those are valid parent clocks for the cpu clock.
> > > > > > 
> > > > > > This is necessary now that the clocks are generated based on the
> > > > > > clock
> > > > > > driver's knowledge of the chip rather than a fragile device-tree
> > > > > > description of the mux options.
> > > > > > 
> > > > > > We can now rely on the clock driver to ensure that the mux only
> > > > > > exposes
> > > > > > options that are valid.  The cpufreq driver was currently being
> > > > > > overly
> > > > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > > > A-004510, and whether the freq_mask used on p5020 is needed
> > > > > > depends on
> > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > > > > mechanism made assumptions about particular parent clock indices
> > > > > > that
> > > > > > are no longer valid.
> > > > > > 
> > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > > > ---
> > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > > > > to clk api usage
> > > > > > 
> > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------
> > > > > > ------
> > > > > > -------
> > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > > > 
> > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > > 
> > > > I'm wondering who's supposed to be merging this set?
> > > 
> > > As I noted in the cover letter, I'm looking for acks so that I can apply
> > > these to a topic branch which can be pulled through the PPC and ARM
> > > trees,
> > > each of which will have patches that depend on it.
> > 
> > OK, so no objections from the cpufreq side and you have the ACK from
> > Viresh.
> 
> Hi Scott,
> 
> Did you drop this patch later?  I can not find it in 4.5-rc still.

I was asked to get an ack from Russell King patch 4/5, which this patch
requires.  Despite repeated pings, I could not get a reply from Russell King.

-Scott

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2016-02-26 18:16               ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2016-02-26 18:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
> On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
> wrote:
> > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > > > Get the CPU clock's potential parent clocks from the clock
> > > > > > interface
> > > > > > itself, rather than manually parsing the clocks property to find a
> > > > > > phandle, looking at the clock-names property of that, and assuming
> > > > > > that
> > > > > > those are valid parent clocks for the cpu clock.
> > > > > > 
> > > > > > This is necessary now that the clocks are generated based on the
> > > > > > clock
> > > > > > driver's knowledge of the chip rather than a fragile device-tree
> > > > > > description of the mux options.
> > > > > > 
> > > > > > We can now rely on the clock driver to ensure that the mux only
> > > > > > exposes
> > > > > > options that are valid.  The cpufreq driver was currently being
> > > > > > overly
> > > > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > > > A-004510, and whether the freq_mask used on p5020 is needed
> > > > > > depends on
> > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > > > limitation but its .freq_mask was zero) -- and the frequency mask
> > > > > > mechanism made assumptions about particular parent clock indices
> > > > > > that
> > > > > > are no longer valid.
> > > > > > 
> > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > > > ---
> > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
> > > > > > to clk api usage
> > > > > > 
> > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------
> > > > > > ------
> > > > > > -------
> > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > > > 
> > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > > 
> > > > I'm wondering who's supposed to be merging this set?
> > > 
> > > As I noted in the cover letter, I'm looking for acks so that I can apply
> > > these to a topic branch which can be pulled through the PPC and ARM
> > > trees,
> > > each of which will have patches that depend on it.
> > 
> > OK, so no objections from the cpufreq side and you have the ACK from
> > Viresh.
> 
> Hi Scott,
> 
> Did you drop this patch later?  I can not find it in 4.5-rc still.

I was asked to get an ack from Russell King patch 4/5, which this patch
requires.  Despite repeated pings, I could not get a reply from Russell King.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2016-02-26 18:16               ` Scott Wood
@ 2016-02-26 21:01                 ` Li Yang
  -1 siblings, 0 replies; 50+ messages in thread
From: Li Yang @ 2016-02-26 21:01 UTC (permalink / raw)
  To: Scott Wood
  Cc: Rafael J. Wysocki, Russell King, linux-pm, Viresh Kumar,
	Michael Turquette, Stephen Boyd, Tang Yuantian, linuxppc-dev,
	linux-clk, linux-arm-kernel

On Fri, Feb 26, 2016 at 12:16 PM, Scott Wood <oss@buserror.net> wrote:
> On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
>> On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
>> wrote:
>> > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
>> > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
>> > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
>> > > > > On 19-09-15, 23:29, Scott Wood wrote:
>> > > > > > Get the CPU clock's potential parent clocks from the clock
>> > > > > > interface
>> > > > > > itself, rather than manually parsing the clocks property to find a
>> > > > > > phandle, looking at the clock-names property of that, and assuming
>> > > > > > that
>> > > > > > those are valid parent clocks for the cpu clock.
>> > > > > >
>> > > > > > This is necessary now that the clocks are generated based on the
>> > > > > > clock
>> > > > > > driver's knowledge of the chip rather than a fragile device-tree
>> > > > > > description of the mux options.
>> > > > > >
>> > > > > > We can now rely on the clock driver to ensure that the mux only
>> > > > > > exposes
>> > > > > > options that are valid.  The cpufreq driver was currently being
>> > > > > > overly
>> > > > > > conservative in some cases -- for example, the "min_cpufreq =
>> > > > > > get_bus_freq()" restriction only applies to chips with erratum
>> > > > > > A-004510, and whether the freq_mask used on p5020 is needed
>> > > > > > depends on
>> > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
>> > > > > > limitation but its .freq_mask was zero) -- and the frequency mask
>> > > > > > mechanism made assumptions about particular parent clock indices
>> > > > > > that
>> > > > > > are no longer valid.
>> > > > > >
>> > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
>> > > > > > ---
>> > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
>> > > > > > to clk api usage
>> > > > > >
>> > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------
>> > > > > > ------
>> > > > > > -------
>> > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
>> > > > >
>> > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> > > >
>> > > > I'm wondering who's supposed to be merging this set?
>> > >
>> > > As I noted in the cover letter, I'm looking for acks so that I can apply
>> > > these to a topic branch which can be pulled through the PPC and ARM
>> > > trees,
>> > > each of which will have patches that depend on it.
>> >
>> > OK, so no objections from the cpufreq side and you have the ACK from
>> > Viresh.
>>
>> Hi Scott,
>>
>> Did you drop this patch later?  I can not find it in 4.5-rc still.
>
> I was asked to get an ack from Russell King patch 4/5, which this patch
> requires.  Despite repeated pings, I could not get a reply from Russell King.

This patch?   I think you should try to get ACK from clock maintainers
instead of Russell.

Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
__clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
true provider API versions that operate on struct clk_hw.

qoriq-cpufreq needs these functions in order to determine the options
it has for calling clk_set_parent() and thus populate the cpufreq
table, so revive them as legitimate consumer APIs.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/clk.c   | 19 +++++++++++++++++++
 include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

Regards,
Leo

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2016-02-26 21:01                 ` Li Yang
  0 siblings, 0 replies; 50+ messages in thread
From: Li Yang @ 2016-02-26 21:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 26, 2016 at 12:16 PM, Scott Wood <oss@buserror.net> wrote:
> On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
>> On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
>> wrote:
>> > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
>> > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
>> > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
>> > > > > On 19-09-15, 23:29, Scott Wood wrote:
>> > > > > > Get the CPU clock's potential parent clocks from the clock
>> > > > > > interface
>> > > > > > itself, rather than manually parsing the clocks property to find a
>> > > > > > phandle, looking at the clock-names property of that, and assuming
>> > > > > > that
>> > > > > > those are valid parent clocks for the cpu clock.
>> > > > > >
>> > > > > > This is necessary now that the clocks are generated based on the
>> > > > > > clock
>> > > > > > driver's knowledge of the chip rather than a fragile device-tree
>> > > > > > description of the mux options.
>> > > > > >
>> > > > > > We can now rely on the clock driver to ensure that the mux only
>> > > > > > exposes
>> > > > > > options that are valid.  The cpufreq driver was currently being
>> > > > > > overly
>> > > > > > conservative in some cases -- for example, the "min_cpufreq =
>> > > > > > get_bus_freq()" restriction only applies to chips with erratum
>> > > > > > A-004510, and whether the freq_mask used on p5020 is needed
>> > > > > > depends on
>> > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
>> > > > > > limitation but its .freq_mask was zero) -- and the frequency mask
>> > > > > > mechanism made assumptions about particular parent clock indices
>> > > > > > that
>> > > > > > are no longer valid.
>> > > > > >
>> > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
>> > > > > > ---
>> > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and changes
>> > > > > > to clk api usage
>> > > > > >
>> > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++---------------
>> > > > > > ------
>> > > > > > -------
>> > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
>> > > > >
>> > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> > > >
>> > > > I'm wondering who's supposed to be merging this set?
>> > >
>> > > As I noted in the cover letter, I'm looking for acks so that I can apply
>> > > these to a topic branch which can be pulled through the PPC and ARM
>> > > trees,
>> > > each of which will have patches that depend on it.
>> >
>> > OK, so no objections from the cpufreq side and you have the ACK from
>> > Viresh.
>>
>> Hi Scott,
>>
>> Did you drop this patch later?  I can not find it in 4.5-rc still.
>
> I was asked to get an ack from Russell King patch 4/5, which this patch
> requires.  Despite repeated pings, I could not get a reply from Russell King.

This patch?   I think you should try to get ACK from clock maintainers
instead of Russell.

Commit fc4a05d4b0eb ("clk: Remove unused provider APIs") removed
__clk_get_num_parents() and clk_hw_get_parent_by_index(), leaving only
true provider API versions that operate on struct clk_hw.

qoriq-cpufreq needs these functions in order to determine the options
it has for calling clk_set_parent() and thus populate the cpufreq
table, so revive them as legitimate consumer APIs.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
v3: new patch

 drivers/clk/clk.c   | 19 +++++++++++++++++++
 include/linux/clk.h | 31 +++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

Regards,
Leo

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
  2016-02-26 21:01                 ` Li Yang
  (?)
@ 2016-02-26 21:46                   ` Scott Wood
  -1 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2016-02-26 21:46 UTC (permalink / raw)
  To: Li Yang
  Cc: Rafael J. Wysocki, Russell King, linux-pm, Viresh Kumar,
	Michael Turquette, Stephen Boyd, Tang Yuantian, linuxppc-dev,
	linux-clk, linux-arm-kernel

On Fri, 2016-02-26 at 15:01 -0600, Li Yang wrote:
> On Fri, Feb 26, 2016 at 12:16 PM, Scott Wood <oss@buserror.net> wrote:
> > On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
> > > On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
> > > wrote:
> > > > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> > > > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > > > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > > > > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > > > > > Get the CPU clock's potential parent clocks from the clock
> > > > > > > > interface
> > > > > > > > itself, rather than manually parsing the clocks property to
> > > > > > > > find a
> > > > > > > > phandle, looking at the clock-names property of that, and
> > > > > > > > assuming
> > > > > > > > that
> > > > > > > > those are valid parent clocks for the cpu clock.
> > > > > > > > 
> > > > > > > > This is necessary now that the clocks are generated based on
> > > > > > > > the
> > > > > > > > clock
> > > > > > > > driver's knowledge of the chip rather than a fragile device
> > > > > > > > -tree
> > > > > > > > description of the mux options.
> > > > > > > > 
> > > > > > > > We can now rely on the clock driver to ensure that the mux
> > > > > > > > only
> > > > > > > > exposes
> > > > > > > > options that are valid.  The cpufreq driver was currently
> > > > > > > > being
> > > > > > > > overly
> > > > > > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > > > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > > > > > A-004510, and whether the freq_mask used on p5020 is needed
> > > > > > > > depends on
> > > > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > > > > > limitation but its .freq_mask was zero) -- and the frequency
> > > > > > > > mask
> > > > > > > > mechanism made assumptions about particular parent clock
> > > > > > > > indices
> > > > > > > > that
> > > > > > > > are no longer valid.
> > > > > > > > 
> > > > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > > > > > ---
> > > > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and
> > > > > > > > changes
> > > > > > > > to clk api usage
> > > > > > > > 
> > > > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++-----------
> > > > > > > > ----
> > > > > > > > ------
> > > > > > > > -------
> > > > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > > > > > 
> > > > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > > > > 
> > > > > > I'm wondering who's supposed to be merging this set?
> > > > > 
> > > > > As I noted in the cover letter, I'm looking for acks so that I can
> > > > > apply
> > > > > these to a topic branch which can be pulled through the PPC and ARM
> > > > > trees,
> > > > > each of which will have patches that depend on it.
> > > > 
> > > > OK, so no objections from the cpufreq side and you have the ACK from
> > > > Viresh.
> > > 
> > > Hi Scott,
> > > 
> > > Did you drop this patch later?  I can not find it in 4.5-rc still.
> > 
> > I was asked to get an ack from Russell King patch 4/5, which this patch
> > requires.  Despite repeated pings, I could not get a reply from Russell
> > King.
> 
> This patch?   I think you should try to get ACK from clock maintainers
> instead of Russell.

A clock maintainer was who asked me to get an ACK from Russell.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2016-02-26 21:46                   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2016-02-26 21:46 UTC (permalink / raw)
  To: Li Yang
  Cc: Rafael J. Wysocki, Russell King, linux-pm, Viresh Kumar,
	Michael Turquette, Stephen Boyd, Tang Yuantian, linuxppc-dev,
	linux-clk, linux-arm-kernel

On Fri, 2016-02-26 at 15:01 -0600, Li Yang wrote:
> On Fri, Feb 26, 2016 at 12:16 PM, Scott Wood <oss@buserror.net> wrote:
> > On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
> > > On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
> > > wrote:
> > > > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> > > > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > > > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > > > > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > > > > > Get the CPU clock's potential parent clocks from the clock
> > > > > > > > interface
> > > > > > > > itself, rather than manually parsing the clocks property to
> > > > > > > > find a
> > > > > > > > phandle, looking at the clock-names property of that, and
> > > > > > > > assuming
> > > > > > > > that
> > > > > > > > those are valid parent clocks for the cpu clock.
> > > > > > > > 
> > > > > > > > This is necessary now that the clocks are generated based on
> > > > > > > > the
> > > > > > > > clock
> > > > > > > > driver's knowledge of the chip rather than a fragile device
> > > > > > > > -tree
> > > > > > > > description of the mux options.
> > > > > > > > 
> > > > > > > > We can now rely on the clock driver to ensure that the mux
> > > > > > > > only
> > > > > > > > exposes
> > > > > > > > options that are valid.  The cpufreq driver was currently
> > > > > > > > being
> > > > > > > > overly
> > > > > > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > > > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > > > > > A-004510, and whether the freq_mask used on p5020 is needed
> > > > > > > > depends on
> > > > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > > > > > limitation but its .freq_mask was zero) -- and the frequency
> > > > > > > > mask
> > > > > > > > mechanism made assumptions about particular parent clock
> > > > > > > > indices
> > > > > > > > that
> > > > > > > > are no longer valid.
> > > > > > > > 
> > > > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > > > > > ---
> > > > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and
> > > > > > > > changes
> > > > > > > > to clk api usage
> > > > > > > > 
> > > > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++-----------
> > > > > > > > ----
> > > > > > > > ------
> > > > > > > > -------
> > > > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > > > > > 
> > > > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > > > > 
> > > > > > I'm wondering who's supposed to be merging this set?
> > > > > 
> > > > > As I noted in the cover letter, I'm looking for acks so that I can
> > > > > apply
> > > > > these to a topic branch which can be pulled through the PPC and ARM
> > > > > trees,
> > > > > each of which will have patches that depend on it.
> > > > 
> > > > OK, so no objections from the cpufreq side and you have the ACK from
> > > > Viresh.
> > > 
> > > Hi Scott,
> > > 
> > > Did you drop this patch later?  I can not find it in 4.5-rc still.
> > 
> > I was asked to get an ack from Russell King patch 4/5, which this patch
> > requires.  Despite repeated pings, I could not get a reply from Russell
> > King.
> 
> This patch?   I think you should try to get ACK from clock maintainers
> instead of Russell.

A clock maintainer was who asked me to get an ACK from Russell.

-Scott


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details
@ 2016-02-26 21:46                   ` Scott Wood
  0 siblings, 0 replies; 50+ messages in thread
From: Scott Wood @ 2016-02-26 21:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2016-02-26 at 15:01 -0600, Li Yang wrote:
> On Fri, Feb 26, 2016 at 12:16 PM, Scott Wood <oss@buserror.net> wrote:
> > On Fri, 2016-02-26 at 12:14 -0600, Li Yang wrote:
> > > On Fri, Sep 25, 2015 at 4:50 PM, Rafael J. Wysocki <rjw@rjwysocki.net>
> > > wrote:
> > > > On Friday, September 25, 2015 04:17:07 PM Scott Wood wrote:
> > > > > On Fri, 2015-09-25 at 23:42 +0200, Rafael J. Wysocki wrote:
> > > > > > On Tuesday, September 22, 2015 12:46:54 PM Viresh Kumar wrote:
> > > > > > > On 19-09-15, 23:29, Scott Wood wrote:
> > > > > > > > Get the CPU clock's potential parent clocks from the clock
> > > > > > > > interface
> > > > > > > > itself, rather than manually parsing the clocks property to
> > > > > > > > find a
> > > > > > > > phandle, looking at the clock-names property of that, and
> > > > > > > > assuming
> > > > > > > > that
> > > > > > > > those are valid parent clocks for the cpu clock.
> > > > > > > > 
> > > > > > > > This is necessary now that the clocks are generated based on
> > > > > > > > the
> > > > > > > > clock
> > > > > > > > driver's knowledge of the chip rather than a fragile device
> > > > > > > > -tree
> > > > > > > > description of the mux options.
> > > > > > > > 
> > > > > > > > We can now rely on the clock driver to ensure that the mux
> > > > > > > > only
> > > > > > > > exposes
> > > > > > > > options that are valid.  The cpufreq driver was currently
> > > > > > > > being
> > > > > > > > overly
> > > > > > > > conservative in some cases -- for example, the "min_cpufreq =
> > > > > > > > get_bus_freq()" restriction only applies to chips with erratum
> > > > > > > > A-004510, and whether the freq_mask used on p5020 is needed
> > > > > > > > depends on
> > > > > > > > the actual frequencies of the PLLs (FWIW, p5040 has a similar
> > > > > > > > limitation but its .freq_mask was zero) -- and the frequency
> > > > > > > > mask
> > > > > > > > mechanism made assumptions about particular parent clock
> > > > > > > > indices
> > > > > > > > that
> > > > > > > > are no longer valid.
> > > > > > > > 
> > > > > > > > Signed-off-by: Scott Wood <scottwood@freescale.com>
> > > > > > > > ---
> > > > > > > > v3: was patch 1/5 and patch 4/5, plus blacklist e6500 and
> > > > > > > > changes
> > > > > > > > to clk api usage
> > > > > > > > 
> > > > > > > >  drivers/cpufreq/qoriq-cpufreq.c | 137 ++++++++++++-----------
> > > > > > > > ----
> > > > > > > > ------
> > > > > > > > -------
> > > > > > > >  1 file changed, 40 insertions(+), 97 deletions(-)
> > > > > > > 
> > > > > > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > > > > 
> > > > > > I'm wondering who's supposed to be merging this set?
> > > > > 
> > > > > As I noted in the cover letter, I'm looking for acks so that I can
> > > > > apply
> > > > > these to a topic branch which can be pulled through the PPC and ARM
> > > > > trees,
> > > > > each of which will have patches that depend on it.
> > > > 
> > > > OK, so no objections from the cpufreq side and you have the ACK from
> > > > Viresh.
> > > 
> > > Hi Scott,
> > > 
> > > Did you drop this patch later?  I can not find it in 4.5-rc still.
> > 
> > I was asked to get an ack from Russell King patch 4/5, which this patch
> > requires.  Despite repeated pings, I could not get a reply from Russell
> > King.
> 
> This patch?   I think you should try to get ACK from clock maintainers
> instead of Russell.

A clock maintainer was who asked me to get an ACK from Russell.

-Scott

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2016-02-26 21:46 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-20  4:29 [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver Scott Wood
2015-09-20  4:29 ` Scott Wood
2015-09-20  4:29 ` Scott Wood
2015-09-20  4:29 ` [PATCH v3 1/5] powerpc/fsl: Move fsl_guts.h out of arch/powerpc Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-20  4:29 ` [PATCH v3 2/5] clk: qoriq: Move chip-specific knowledge into driver Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-10-15 19:53   ` Stephen Boyd
2015-10-15 19:53     ` Stephen Boyd
2015-09-20  4:29 ` [PATCH v3 3/5] clk: qoriq: Add ls2080a support Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-10-15 19:53   ` Stephen Boyd
2015-10-15 19:53     ` Stephen Boyd
2015-09-20  4:29 ` [PATCH v3 4/5] clk: Add consumer APIs for discovering possible parent clocks Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-10-15 20:03   ` Scott Wood
2015-10-15 20:03     ` Scott Wood
2015-10-15 20:03     ` Scott Wood
2015-12-07 20:44     ` Scott Wood
2015-12-07 20:44       ` Scott Wood
2015-12-07 20:44       ` Scott Wood
2015-09-20  4:29 ` [PATCH v3 5/5] cpufreq: qoriq: Don't look at clock implementation details Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-20  4:29   ` Scott Wood
2015-09-22 19:46   ` Viresh Kumar
2015-09-22 19:46     ` Viresh Kumar
2015-09-25 21:42     ` Rafael J. Wysocki
2015-09-25 21:42       ` Rafael J. Wysocki
2015-09-25 21:17       ` Scott Wood
2015-09-25 21:17         ` Scott Wood
2015-09-25 21:17         ` Scott Wood
2015-09-25 21:50         ` Rafael J. Wysocki
2015-09-25 21:50           ` Rafael J. Wysocki
2016-02-26 18:14           ` Li Yang
2016-02-26 18:14             ` Li Yang
2016-02-26 18:16             ` Scott Wood
2016-02-26 18:16               ` Scott Wood
2016-02-26 18:16               ` Scott Wood
2016-02-26 21:01               ` Li Yang
2016-02-26 21:01                 ` Li Yang
2016-02-26 21:46                 ` Scott Wood
2016-02-26 21:46                   ` Scott Wood
2016-02-26 21:46                   ` Scott Wood
2015-10-23 22:39 ` [PATCH v3 0/5] clk: qoriq: Move chip-specific knowledge into driver Scott Wood
2015-10-23 22:39   ` Scott Wood
2015-10-23 22:39   ` Scott Wood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.