All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] Broadcom XLP changes for 3.16
@ 2014-04-29 14:37 ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

The changes in the patchset are:
 * add support for the on chip SATA interfaces of XLP and XLPII
 * add MSI/MSIX support for the XLP9xx processors
 * add support for the new XLP5xx processors
 * update frequency calculation logic for core and PIC
 * many fixes and improvements

Patch 01/17 is to support upto 256 CPUs on mips, which is needed for
multi-node XLP9xx configuration. The rest of the changes are to Broadcom
XLR/XLP specific code.

This is for 3.16, please let me know if there are any comments.

Thanks,
JC.


Ganesan Ramalingam (4):
  MIPS: Netlogic: PIC freq calculation for XLP 9XX/2XX
  MIPS: Add MSI support for XLP9XX
  MIPS: Netlogic: Support for XLP3XX on-chip SATA
  MIPS: Netlogic: XLP9XX on-chip SATA support

Jayachandran C (12):
  MIPS: Support upto 256 CPUs
  MIPS: Netlogic: Fix uniprocessor compilation
  MIPS: Netlogic: Move coremask setup to nlm_node_init
  MIPS: Netlogic: Warn on invalid irq
  MIPS: Netlogic: Update function to read DRAM BARs
  MIPS: Netlogic: Use cpumask_scnprintf for wakup_mask
  MIPS: Netlogic: Reduce size of reset code
  MIPS: Netlogic: Enable access to more than 64GB
  MIPS: Netlogic: IRQ mapping for some more SoC blocks
  MIPS: Netlogic: Use PRID_IMP_MASK macro
  MIPS: Netlogic: Fix XLP9XX pic entry
  MIPS: Netlogic: Update XLP9XX/2XX core freq calculation

Yonghong Song (1):
  MIPS: Netlogic: Add support for XLP5XX

 arch/mips/Kconfig                               |    4 +-
 arch/mips/include/asm/cpu.h                     |    1 +
 arch/mips/include/asm/mach-netlogic/topology.h  |    2 +
 arch/mips/include/asm/netlogic/mips-extns.h     |    5 +-
 arch/mips/include/asm/netlogic/xlp-hal/iomap.h  |   18 +-
 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |   14 +
 arch/mips/include/asm/netlogic/xlp-hal/pic.h    |    4 +
 arch/mips/include/asm/netlogic/xlp-hal/sys.h    |   35 +++
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h    |   21 +-
 arch/mips/kernel/cpu-probe.c                    |    1 +
 arch/mips/netlogic/common/irq.c                 |    2 +
 arch/mips/netlogic/common/reset.S               |   39 ++-
 arch/mips/netlogic/common/smp.c                 |    7 +-
 arch/mips/netlogic/common/smpboot.S             |    6 +-
 arch/mips/netlogic/common/time.c                |    5 +-
 arch/mips/netlogic/dts/xlp_gvp.dts              |    5 +-
 arch/mips/netlogic/xlp/Makefile                 |    2 +
 arch/mips/netlogic/xlp/ahci-init-xlp2.c         |  378 +++++++++++++++++++++++
 arch/mips/netlogic/xlp/ahci-init.c              |  209 +++++++++++++
 arch/mips/netlogic/xlp/dt.c                     |    3 +-
 arch/mips/netlogic/xlp/nlm_hal.c                |  295 +++++++++++++-----
 arch/mips/netlogic/xlp/setup.c                  |    5 +-
 arch/mips/netlogic/xlp/wakeup.c                 |   16 +-
 arch/mips/pci/msi-xlp.c                         |  178 ++++++++---
 24 files changed, 1079 insertions(+), 176 deletions(-)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init-xlp2.c
 create mode 100644 arch/mips/netlogic/xlp/ahci-init.c

-- 
1.7.9.5

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

* [PATCH 00/17] Broadcom XLP changes for 3.16
@ 2014-04-29 14:37 ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

The changes in the patchset are:
 * add support for the on chip SATA interfaces of XLP and XLPII
 * add MSI/MSIX support for the XLP9xx processors
 * add support for the new XLP5xx processors
 * update frequency calculation logic for core and PIC
 * many fixes and improvements

Patch 01/17 is to support upto 256 CPUs on mips, which is needed for
multi-node XLP9xx configuration. The rest of the changes are to Broadcom
XLR/XLP specific code.

This is for 3.16, please let me know if there are any comments.

Thanks,
JC.


Ganesan Ramalingam (4):
  MIPS: Netlogic: PIC freq calculation for XLP 9XX/2XX
  MIPS: Add MSI support for XLP9XX
  MIPS: Netlogic: Support for XLP3XX on-chip SATA
  MIPS: Netlogic: XLP9XX on-chip SATA support

Jayachandran C (12):
  MIPS: Support upto 256 CPUs
  MIPS: Netlogic: Fix uniprocessor compilation
  MIPS: Netlogic: Move coremask setup to nlm_node_init
  MIPS: Netlogic: Warn on invalid irq
  MIPS: Netlogic: Update function to read DRAM BARs
  MIPS: Netlogic: Use cpumask_scnprintf for wakup_mask
  MIPS: Netlogic: Reduce size of reset code
  MIPS: Netlogic: Enable access to more than 64GB
  MIPS: Netlogic: IRQ mapping for some more SoC blocks
  MIPS: Netlogic: Use PRID_IMP_MASK macro
  MIPS: Netlogic: Fix XLP9XX pic entry
  MIPS: Netlogic: Update XLP9XX/2XX core freq calculation

Yonghong Song (1):
  MIPS: Netlogic: Add support for XLP5XX

 arch/mips/Kconfig                               |    4 +-
 arch/mips/include/asm/cpu.h                     |    1 +
 arch/mips/include/asm/mach-netlogic/topology.h  |    2 +
 arch/mips/include/asm/netlogic/mips-extns.h     |    5 +-
 arch/mips/include/asm/netlogic/xlp-hal/iomap.h  |   18 +-
 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |   14 +
 arch/mips/include/asm/netlogic/xlp-hal/pic.h    |    4 +
 arch/mips/include/asm/netlogic/xlp-hal/sys.h    |   35 +++
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h    |   21 +-
 arch/mips/kernel/cpu-probe.c                    |    1 +
 arch/mips/netlogic/common/irq.c                 |    2 +
 arch/mips/netlogic/common/reset.S               |   39 ++-
 arch/mips/netlogic/common/smp.c                 |    7 +-
 arch/mips/netlogic/common/smpboot.S             |    6 +-
 arch/mips/netlogic/common/time.c                |    5 +-
 arch/mips/netlogic/dts/xlp_gvp.dts              |    5 +-
 arch/mips/netlogic/xlp/Makefile                 |    2 +
 arch/mips/netlogic/xlp/ahci-init-xlp2.c         |  378 +++++++++++++++++++++++
 arch/mips/netlogic/xlp/ahci-init.c              |  209 +++++++++++++
 arch/mips/netlogic/xlp/dt.c                     |    3 +-
 arch/mips/netlogic/xlp/nlm_hal.c                |  295 +++++++++++++-----
 arch/mips/netlogic/xlp/setup.c                  |    5 +-
 arch/mips/netlogic/xlp/wakeup.c                 |   16 +-
 arch/mips/pci/msi-xlp.c                         |  178 ++++++++---
 24 files changed, 1079 insertions(+), 176 deletions(-)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init-xlp2.c
 create mode 100644 arch/mips/netlogic/xlp/ahci-init.c

-- 
1.7.9.5

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

* [PATCH 01/17] MIPS: Support upto 256 CPUs
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

This is needed for two node XLP9xx configurations.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/Kconfig |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index a91f688..d0bcfce 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2297,8 +2297,8 @@ config NR_CPUS_DEFAULT_64
 	bool
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-64)"
-	range 2 64
+	int "Maximum number of CPUs (2-256)"
+	range 2 256
 	depends on SMP
 	default "4" if NR_CPUS_DEFAULT_4
 	default "8" if NR_CPUS_DEFAULT_8
-- 
1.7.9.5

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

* [PATCH 01/17] MIPS: Support upto 256 CPUs
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

This is needed for two node XLP9xx configurations.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/Kconfig |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index a91f688..d0bcfce 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2297,8 +2297,8 @@ config NR_CPUS_DEFAULT_64
 	bool
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-64)"
-	range 2 64
+	int "Maximum number of CPUs (2-256)"
+	range 2 256
 	depends on SMP
 	default "4" if NR_CPUS_DEFAULT_4
 	default "8" if NR_CPUS_DEFAULT_8
-- 
1.7.9.5

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

* [PATCH 02/17] MIPS: Netlogic: Fix uniprocessor compilation
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

The macros in topology.h need CONFIG_SMP, and the uniprocessor compilation
fails due to this. Wrap the macros in an ifdef so that uniprocessor works.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/mach-netlogic/topology.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/include/asm/mach-netlogic/topology.h b/arch/mips/include/asm/mach-netlogic/topology.h
index 0da99fa..ceeb1f5 100644
--- a/arch/mips/include/asm/mach-netlogic/topology.h
+++ b/arch/mips/include/asm/mach-netlogic/topology.h
@@ -10,10 +10,12 @@
 
 #include <asm/mach-netlogic/multi-node.h>
 
+#ifdef CONFIG_SMP
 #define topology_physical_package_id(cpu)	cpu_to_node(cpu)
 #define topology_core_id(cpu)	(cpu_logical_map(cpu) / NLM_THREADS_PER_CORE)
 #define topology_thread_cpumask(cpu)		(&cpu_sibling_map[cpu])
 #define topology_core_cpumask(cpu)	cpumask_of_node(cpu_to_node(cpu))
+#endif
 
 #include <asm-generic/topology.h>
 
-- 
1.7.9.5

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

* [PATCH 02/17] MIPS: Netlogic: Fix uniprocessor compilation
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

The macros in topology.h need CONFIG_SMP, and the uniprocessor compilation
fails due to this. Wrap the macros in an ifdef so that uniprocessor works.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/mach-netlogic/topology.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/include/asm/mach-netlogic/topology.h b/arch/mips/include/asm/mach-netlogic/topology.h
index 0da99fa..ceeb1f5 100644
--- a/arch/mips/include/asm/mach-netlogic/topology.h
+++ b/arch/mips/include/asm/mach-netlogic/topology.h
@@ -10,10 +10,12 @@
 
 #include <asm/mach-netlogic/multi-node.h>
 
+#ifdef CONFIG_SMP
 #define topology_physical_package_id(cpu)	cpu_to_node(cpu)
 #define topology_core_id(cpu)	(cpu_logical_map(cpu) / NLM_THREADS_PER_CORE)
 #define topology_thread_cpumask(cpu)		(&cpu_sibling_map[cpu])
 #define topology_core_cpumask(cpu)	cpumask_of_node(cpu_to_node(cpu))
+#endif
 
 #include <asm-generic/topology.h>
 
-- 
1.7.9.5

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

* [PATCH 03/17] MIPS: Netlogic: Move coremask setup to nlm_node_init
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

This is needed for nlm_node_present(0) to work on uniprocessor compile.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/xlp/nlm_hal.c |    2 ++
 arch/mips/netlogic/xlp/wakeup.c  |    4 ----
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 997cd9e..7b277cd 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -54,6 +54,8 @@ void nlm_node_init(int node)
 	struct nlm_soc_info *nodep;
 
 	nodep = nlm_get_node(node);
+	if (node == 0)
+		nodep->coremask = 1;	/* node 0, boot cpu */
 	nodep->sysbase = nlm_get_sys_regbase(node);
 	nodep->picbase = nlm_get_pic_regbase(node);
 	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 9a92617..7589238 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -159,10 +159,6 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
 		 */
 		syscoremask = (1 << hweight32(~fusemask & mask)) - 1;
 
-		/* The boot cpu */
-		if (n == 0)
-			nodep->coremask = 1;
-
 		pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask);
 		for (core = 0; core < nlm_cores_per_node(); core++) {
 			/* we will be on node 0 core 0 */
-- 
1.7.9.5

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

* [PATCH 03/17] MIPS: Netlogic: Move coremask setup to nlm_node_init
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

This is needed for nlm_node_present(0) to work on uniprocessor compile.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/xlp/nlm_hal.c |    2 ++
 arch/mips/netlogic/xlp/wakeup.c  |    4 ----
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 997cd9e..7b277cd 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -54,6 +54,8 @@ void nlm_node_init(int node)
 	struct nlm_soc_info *nodep;
 
 	nodep = nlm_get_node(node);
+	if (node == 0)
+		nodep->coremask = 1;	/* node 0, boot cpu */
 	nodep->sysbase = nlm_get_sys_regbase(node);
 	nodep->picbase = nlm_get_pic_regbase(node);
 	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 9a92617..7589238 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -159,10 +159,6 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
 		 */
 		syscoremask = (1 << hweight32(~fusemask & mask)) - 1;
 
-		/* The boot cpu */
-		if (n == 0)
-			nodep->coremask = 1;
-
 		pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask);
 		for (core = 0; core < nlm_cores_per_node(); core++) {
 			/* we will be on node 0 core 0 */
-- 
1.7.9.5

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

* [PATCH 04/17] MIPS: Netlogic: Warn on invalid irq
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Warn and return if invalid IRQ is passed to nlm_set_pic_extra_ack.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/irq.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 5afc4b7..c100b9a 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -203,6 +203,8 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
 
 	xirq = nlm_irq_to_xirq(node, irq);
 	pic_data = irq_get_handler_data(xirq);
+	if (WARN_ON(!pic_data))
+		return;
 	pic_data->extra_ack = xack;
 }
 
-- 
1.7.9.5

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

* [PATCH 04/17] MIPS: Netlogic: Warn on invalid irq
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Warn and return if invalid IRQ is passed to nlm_set_pic_extra_ack.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/irq.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 5afc4b7..c100b9a 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -203,6 +203,8 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
 
 	xirq = nlm_irq_to_xirq(node, irq);
 	pic_data = irq_get_handler_data(xirq);
+	if (WARN_ON(!pic_data))
+		return;
 	pic_data->extra_ack = xack;
 }
 
-- 
1.7.9.5

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

* [PATCH 05/17] MIPS: Netlogic: Update function to read DRAM BARs
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Change name of xlp_get_dram_map to nlm_get_dram_map to be consistent
with the rest of the functions in the file. Pass the the size of the
array 'dram_map' to the function, and ensure that it does not write
past the end of the array.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h |    2 +-
 arch/mips/netlogic/xlp/nlm_hal.c             |   12 +++++++-----
 arch/mips/netlogic/xlp/setup.c               |    2 +-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 2b0c959..1b56bd4 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -84,7 +84,7 @@ void xlp_wakeup_secondary_cpus(void);
 
 void xlp_mmu_init(void);
 void nlm_hal_init(void);
-int xlp_get_dram_map(int n, uint64_t *dram_map);
+int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries);
 
 struct pci_dev;
 int xlp_socdev_to_node(const struct pci_dev *dev);
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 7b277cd..d85019b 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -319,19 +319,21 @@ unsigned int nlm_get_cpu_frequency(void)
 
 /*
  * Fills upto 8 pairs of entries containing the DRAM map of a node
- * if n < 0, get dram map for all nodes
+ * if node < 0, get dram map for all nodes
  */
-int xlp_get_dram_map(int n, uint64_t *dram_map)
+int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries)
 {
 	uint64_t bridgebase, base, lim;
 	uint32_t val;
 	unsigned int barreg, limreg, xlatreg;
-	int i, node, rv;
+	int i, n, rv;
 
 	/* Look only at mapping on Node 0, we don't handle crazy configs */
 	bridgebase = nlm_get_bridge_regbase(0);
 	rv = 0;
 	for (i = 0; i < 8; i++) {
+		if (rv + 1 >= nentries)
+			break;
 		if (cpu_is_xlp9xx()) {
 			barreg = BRIDGE_9XX_DRAM_BAR(i);
 			limreg = BRIDGE_9XX_DRAM_LIMIT(i);
@@ -341,10 +343,10 @@ int xlp_get_dram_map(int n, uint64_t *dram_map)
 			limreg = BRIDGE_DRAM_LIMIT(i);
 			xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i);
 		}
-		if (n >= 0) {
+		if (node >= 0) {
 			/* node specified, get node mapping of BAR */
 			val = nlm_read_bridge_reg(bridgebase, xlatreg);
-			node = (val >> 1) & 0x3;
+			n = (val >> 1) & 0x3;
 			if (n != node)
 				continue;
 		}
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 8c60a2d..d1c9e88 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -82,7 +82,7 @@ static void __init xlp_init_mem_from_bars(void)
 	uint64_t map[16];
 	int i, n;
 
-	n = xlp_get_dram_map(-1, map);	/* -1: info for all nodes */
+	n = nlm_get_dram_map(-1, map, ARRAY_SIZE(map));	/* -1 : all nodes */
 	for (i = 0; i < n; i += 2) {
 		/* exclude 0x1000_0000-0x2000_0000, u-boot device */
 		if (map[i] <= 0x10000000 && map[i+1] > 0x10000000)
-- 
1.7.9.5

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

* [PATCH 05/17] MIPS: Netlogic: Update function to read DRAM BARs
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Change name of xlp_get_dram_map to nlm_get_dram_map to be consistent
with the rest of the functions in the file. Pass the the size of the
array 'dram_map' to the function, and ensure that it does not write
past the end of the array.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h |    2 +-
 arch/mips/netlogic/xlp/nlm_hal.c             |   12 +++++++-----
 arch/mips/netlogic/xlp/setup.c               |    2 +-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 2b0c959..1b56bd4 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -84,7 +84,7 @@ void xlp_wakeup_secondary_cpus(void);
 
 void xlp_mmu_init(void);
 void nlm_hal_init(void);
-int xlp_get_dram_map(int n, uint64_t *dram_map);
+int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries);
 
 struct pci_dev;
 int xlp_socdev_to_node(const struct pci_dev *dev);
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 7b277cd..d85019b 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -319,19 +319,21 @@ unsigned int nlm_get_cpu_frequency(void)
 
 /*
  * Fills upto 8 pairs of entries containing the DRAM map of a node
- * if n < 0, get dram map for all nodes
+ * if node < 0, get dram map for all nodes
  */
-int xlp_get_dram_map(int n, uint64_t *dram_map)
+int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries)
 {
 	uint64_t bridgebase, base, lim;
 	uint32_t val;
 	unsigned int barreg, limreg, xlatreg;
-	int i, node, rv;
+	int i, n, rv;
 
 	/* Look only at mapping on Node 0, we don't handle crazy configs */
 	bridgebase = nlm_get_bridge_regbase(0);
 	rv = 0;
 	for (i = 0; i < 8; i++) {
+		if (rv + 1 >= nentries)
+			break;
 		if (cpu_is_xlp9xx()) {
 			barreg = BRIDGE_9XX_DRAM_BAR(i);
 			limreg = BRIDGE_9XX_DRAM_LIMIT(i);
@@ -341,10 +343,10 @@ int xlp_get_dram_map(int n, uint64_t *dram_map)
 			limreg = BRIDGE_DRAM_LIMIT(i);
 			xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i);
 		}
-		if (n >= 0) {
+		if (node >= 0) {
 			/* node specified, get node mapping of BAR */
 			val = nlm_read_bridge_reg(bridgebase, xlatreg);
-			node = (val >> 1) & 0x3;
+			n = (val >> 1) & 0x3;
 			if (n != node)
 				continue;
 		}
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 8c60a2d..d1c9e88 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -82,7 +82,7 @@ static void __init xlp_init_mem_from_bars(void)
 	uint64_t map[16];
 	int i, n;
 
-	n = xlp_get_dram_map(-1, map);	/* -1: info for all nodes */
+	n = nlm_get_dram_map(-1, map, ARRAY_SIZE(map));	/* -1 : all nodes */
 	for (i = 0; i < n; i += 2) {
 		/* exclude 0x1000_0000-0x2000_0000, u-boot device */
 		if (map[i] <= 0x10000000 && map[i+1] > 0x10000000)
-- 
1.7.9.5

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

* [PATCH 06/17] MIPS: Netlogic: Use cpumask_scnprintf for wakup_mask
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Use standard function to print cpumask. Also fixup a typo in the same
file.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/smp.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6baae15..b93c5d4 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -198,7 +198,7 @@ void __init nlm_smp_setup(void)
 	cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
 	pr_info("Possible CPU mask: %s\n", buf);
 
-	/* check with the cores we have worken up */
+	/* check with the cores we have woken up */
 	for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
 		ncore += hweight32(nlm_get_node(i)->coremask);
 
@@ -213,6 +213,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 {
 	uint32_t core0_thr_mask, core_thr_mask;
 	int threadmode, i, j;
+	char buf[64];
 
 	core0_thr_mask = 0;
 	for (i = 0; i < NLM_THREADS_PER_CORE; i++)
@@ -247,8 +248,8 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 	return threadmode;
 
 unsupp:
-	panic("Unsupported CPU mask %lx",
-		(unsigned long)cpumask_bits(wakeup_mask)[0]);
+	cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
+	panic("Unsupported CPU mask %s", buf);
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH 06/17] MIPS: Netlogic: Use cpumask_scnprintf for wakup_mask
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Use standard function to print cpumask. Also fixup a typo in the same
file.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/smp.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6baae15..b93c5d4 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -198,7 +198,7 @@ void __init nlm_smp_setup(void)
 	cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
 	pr_info("Possible CPU mask: %s\n", buf);
 
-	/* check with the cores we have worken up */
+	/* check with the cores we have woken up */
 	for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
 		ncore += hweight32(nlm_get_node(i)->coremask);
 
@@ -213,6 +213,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 {
 	uint32_t core0_thr_mask, core_thr_mask;
 	int threadmode, i, j;
+	char buf[64];
 
 	core0_thr_mask = 0;
 	for (i = 0; i < NLM_THREADS_PER_CORE; i++)
@@ -247,8 +248,8 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 	return threadmode;
 
 unsupp:
-	panic("Unsupported CPU mask %lx",
-		(unsigned long)cpumask_bits(wakeup_mask)[0]);
+	cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
+	panic("Unsupported CPU mask %s", buf);
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH 07/17] MIPS: Netlogic: Reduce size of reset code
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Update thread wakeup function to use scratch registers for saving SP and
RA. Move the register restore code needed for thread 0 to the calling
function. This reduces the size of code copied to the reset vector.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/reset.S   |   15 ++++++++-------
 arch/mips/netlogic/common/smpboot.S |    6 ++++--
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index b231fe1..fda772a 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -197,6 +197,9 @@ FEXPORT(nlm_reset_entry)
 EXPORT(nlm_boot_siblings)
 	/* core L1D flush before enable threads */
 	xlp_flush_l1_dcache
+	/* save ra and sp, will be used later (only for boot cpu) */
+	dmtc0	ra, $22, 6
+	dmtc0	sp, $22, 7
 	/* Enable hw threads by writing to MAP_THREADMODE of the core */
 	li	t0, CKSEG1ADDR(RESET_DATA_PHYS)
 	lw	t1, BOOT_THREAD_MODE(t0)	/* t1 <- thread mode */
@@ -238,14 +241,12 @@ EXPORT(nlm_boot_siblings)
 	nop
 
 	/*
-	 * For the boot CPU, we have to restore registers and
-	 * return
+	 * For the boot CPU, we have to restore ra and sp and return, rest
+	 * of the registers will be restored by the caller
 	 */
-4:	dmfc0	t0, $4, 2	/* restore SP from UserLocal */
-	li	t1, 0xfadebeef
-	dmtc0	t1, $4, 2	/* restore SP from UserLocal */
-	PTR_SUBU sp, t0, PT_SIZE
-	RESTORE_ALL
+4:
+	dmfc0	ra, $22, 6
+	dmfc0	sp, $22, 7
 	jr	ra
 	nop
 EXPORT(nlm_reset_entry_end)
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index 8597657..d9b456b 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -55,7 +55,6 @@
 	.set	arch=xlr		/* for mfcr/mtcr, XLR is sufficient */
 
 FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
-	dmtc0	sp, $4, 2		/* SP saved in UserLocal */
 	SAVE_ALL
 	sync
 	/* find the location to which nlm_boot_siblings was relocated */
@@ -65,7 +64,10 @@ FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
 	dsubu	t2, t1
 	daddu	t2, t0
 	/* call it */
-	jr	t2
+	jalr	t2
+	nop
+	RESTORE_ALL
+	jr	ra
 	nop
 	/* not reached */
 
-- 
1.7.9.5

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

* [PATCH 07/17] MIPS: Netlogic: Reduce size of reset code
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Update thread wakeup function to use scratch registers for saving SP and
RA. Move the register restore code needed for thread 0 to the calling
function. This reduces the size of code copied to the reset vector.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/reset.S   |   15 ++++++++-------
 arch/mips/netlogic/common/smpboot.S |    6 ++++--
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index b231fe1..fda772a 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -197,6 +197,9 @@ FEXPORT(nlm_reset_entry)
 EXPORT(nlm_boot_siblings)
 	/* core L1D flush before enable threads */
 	xlp_flush_l1_dcache
+	/* save ra and sp, will be used later (only for boot cpu) */
+	dmtc0	ra, $22, 6
+	dmtc0	sp, $22, 7
 	/* Enable hw threads by writing to MAP_THREADMODE of the core */
 	li	t0, CKSEG1ADDR(RESET_DATA_PHYS)
 	lw	t1, BOOT_THREAD_MODE(t0)	/* t1 <- thread mode */
@@ -238,14 +241,12 @@ EXPORT(nlm_boot_siblings)
 	nop
 
 	/*
-	 * For the boot CPU, we have to restore registers and
-	 * return
+	 * For the boot CPU, we have to restore ra and sp and return, rest
+	 * of the registers will be restored by the caller
 	 */
-4:	dmfc0	t0, $4, 2	/* restore SP from UserLocal */
-	li	t1, 0xfadebeef
-	dmtc0	t1, $4, 2	/* restore SP from UserLocal */
-	PTR_SUBU sp, t0, PT_SIZE
-	RESTORE_ALL
+4:
+	dmfc0	ra, $22, 6
+	dmfc0	sp, $22, 7
 	jr	ra
 	nop
 EXPORT(nlm_reset_entry_end)
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index 8597657..d9b456b 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -55,7 +55,6 @@
 	.set	arch=xlr		/* for mfcr/mtcr, XLR is sufficient */
 
 FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
-	dmtc0	sp, $4, 2		/* SP saved in UserLocal */
 	SAVE_ALL
 	sync
 	/* find the location to which nlm_boot_siblings was relocated */
@@ -65,7 +64,10 @@ FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
 	dsubu	t2, t1
 	daddu	t2, t0
 	/* call it */
-	jr	t2
+	jalr	t2
+	nop
+	RESTORE_ALL
+	jr	ra
 	nop
 	/* not reached */
 
-- 
1.7.9.5

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

* [PATCH 08/17] MIPS: Netlogic: Enable access to more than 64GB
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

The ELPA bit needs to be set in the PAGEGRAIN register to enable
access to >64GB physical address. Update reset.S to do this from
every hardware thread.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/reset.S |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index fda772a..13c1bc5 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -74,6 +74,18 @@
 .endm
 
 /*
+ * Allow access to physical mem >64G by enabling ELPA in PAGEGRAIN
+ * register. This is needed before going to C code since the SP can
+ * in this region. Called from all HW threads.
+ */
+.macro xlp_early_mmu_init
+	mfc0	t0, CP0_PAGEMASK, 1
+	li	t1, (1 << 29)		/* ELPA bit */
+	or	t0, t1
+	mtc0	t0, CP0_PAGEMASK, 1
+.endm
+
+/*
  * L1D cache has to be flushed before enabling threads in XLP.
  * On XLP8xx/XLP3xx, we do a low level flush using processor control
  * registers. On XLPII CPUs, usual cache instructions work.
@@ -228,6 +240,8 @@ EXPORT(nlm_boot_siblings)
 #endif
 	mtc0	t1, CP0_STATUS
 
+	xlp_early_mmu_init
+
 	/* mark CPU ready */
 	li	t3, CKSEG1ADDR(RESET_DATA_PHYS)
 	ADDIU	t1, t3, BOOT_CPU_READY
@@ -254,6 +268,7 @@ EXPORT(nlm_reset_entry_end)
 LEAF(nlm_init_boot_cpu)
 #ifdef CONFIG_CPU_XLP
 	xlp_config_lsu
+	xlp_early_mmu_init
 #endif
 	jr	ra
 	nop
-- 
1.7.9.5

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

* [PATCH 08/17] MIPS: Netlogic: Enable access to more than 64GB
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

The ELPA bit needs to be set in the PAGEGRAIN register to enable
access to >64GB physical address. Update reset.S to do this from
every hardware thread.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/common/reset.S |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index fda772a..13c1bc5 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -74,6 +74,18 @@
 .endm
 
 /*
+ * Allow access to physical mem >64G by enabling ELPA in PAGEGRAIN
+ * register. This is needed before going to C code since the SP can
+ * in this region. Called from all HW threads.
+ */
+.macro xlp_early_mmu_init
+	mfc0	t0, CP0_PAGEMASK, 1
+	li	t1, (1 << 29)		/* ELPA bit */
+	or	t0, t1
+	mtc0	t0, CP0_PAGEMASK, 1
+.endm
+
+/*
  * L1D cache has to be flushed before enabling threads in XLP.
  * On XLP8xx/XLP3xx, we do a low level flush using processor control
  * registers. On XLPII CPUs, usual cache instructions work.
@@ -228,6 +240,8 @@ EXPORT(nlm_boot_siblings)
 #endif
 	mtc0	t1, CP0_STATUS
 
+	xlp_early_mmu_init
+
 	/* mark CPU ready */
 	li	t3, CKSEG1ADDR(RESET_DATA_PHYS)
 	ADDIU	t1, t3, BOOT_CPU_READY
@@ -254,6 +268,7 @@ EXPORT(nlm_reset_entry_end)
 LEAF(nlm_init_boot_cpu)
 #ifdef CONFIG_CPU_XLP
 	xlp_config_lsu
+	xlp_early_mmu_init
 #endif
 	jr	ra
 	nop
-- 
1.7.9.5

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

* [PATCH 09/17] MIPS: Netlogic: IRQ mapping for some more SoC blocks
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Add IRQ to IRT (PIC interupt table index) mapping for SATA, GPIO, NAND
and SPI interfaces on the XLP SoC. Fix offsets for few blocks and add
device IDs for a few blocks.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/iomap.h |   16 +++--
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h   |    4 ++
 arch/mips/netlogic/xlp/nlm_hal.c               |   84 ++++++++++++++++--------
 3 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 1f23dfa..14b2f51 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -74,6 +74,8 @@
 #define XLP_IO_USB_OHCI2_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 4)
 #define XLP_IO_USB_OHCI3_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 5)
 
+#define XLP_IO_SATA_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 3, 2)
+
 /* XLP2xx has an updated USB block */
 #define XLP2XX_IO_USB_OFFSET(node, i)	XLP_HDR_OFFSET(node, 0, 4, i)
 #define XLP2XX_IO_USB_XHCI0_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 4, 1)
@@ -103,13 +105,11 @@
 #define XLP_IO_SYS_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 6, 5)
 #define XLP_IO_JTAG_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 6, 6)
 
+/* Flash */
 #define XLP_IO_NOR_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 0)
 #define XLP_IO_NAND_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 7, 1)
 #define XLP_IO_SPI_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 2)
-/* SD flash */
-#define XLP_IO_SD_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
-#define XLP_IO_MMC_OFFSET(node, slot)	\
-		((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+#define XLP_IO_MMC_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
 
 /* Things have changed drastically in XLP 9XX */
 #define XLP9XX_HDR_OFFSET(n, d, f)	\
@@ -135,11 +135,11 @@
 /* XLP9XX on-chip SATA controller */
 #define XLP9XX_IO_SATA_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 3, 2)
 
+/* Flash */
 #define XLP9XX_IO_NOR_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 0)
 #define XLP9XX_IO_NAND_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 1)
 #define XLP9XX_IO_SPI_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 2)
-/* SD flash */
-#define XLP9XX_IO_MMCSD_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
+#define XLP9XX_IO_MMC_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
 
 /* PCI config header register id's */
 #define XLP_PCI_CFGREG0			0x00
@@ -186,8 +186,10 @@
 #define PCI_DEVICE_ID_NLM_NOR		0x1015
 #define PCI_DEVICE_ID_NLM_NAND		0x1016
 #define PCI_DEVICE_ID_NLM_MMC		0x1018
-#define PCI_DEVICE_ID_NLM_XHCI		0x101d
+#define PCI_DEVICE_ID_NLM_SATA		0x101A
+#define PCI_DEVICE_ID_NLM_XHCI		0x101D
 
+#define PCI_DEVICE_ID_XLP9XX_MMC	0x9018
 #define PCI_DEVICE_ID_XLP9XX_SATA	0x901A
 #define PCI_DEVICE_ID_XLP9XX_XHCI	0x901D
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 1b56bd4..488863e 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -58,6 +58,10 @@
 #define PIC_I2C_1_IRQ			31
 #define PIC_I2C_2_IRQ			32
 #define PIC_I2C_3_IRQ			33
+#define PIC_SPI_IRQ			34
+#define PIC_NAND_IRQ			37
+#define PIC_SATA_IRQ			38
+#define PIC_GPIO_IRQ			39
 
 #define PIC_PCIE_LINK_MSI_IRQ_BASE	44	/* 44 - 47 MSI IRQ */
 #define PIC_PCIE_LINK_MSI_IRQ(i)	(44 + (i))
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index d85019b..44dc159 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -66,31 +66,39 @@ void nlm_node_init(int node)
 	spin_lock_init(&nodep->piclock);
 }
 
-int nlm_irq_to_irt(int irq)
+static int xlp9xx_irq_to_irt(int irq)
+{
+	switch (irq) {
+	case PIC_GPIO_IRQ:
+		return 12;
+	case PIC_9XX_XHCI_0_IRQ:
+		return 114;
+	case PIC_9XX_XHCI_1_IRQ:
+		return 115;
+	case PIC_UART_0_IRQ:
+		return 133;
+	case PIC_UART_1_IRQ:
+		return 134;
+	case PIC_SATA_IRQ:
+		return 143;
+	case PIC_SPI_IRQ:
+		return 152;
+	case PIC_MMC_IRQ:
+		return 153;
+	case PIC_PCIE_LINK_LEGACY_IRQ(0):
+	case PIC_PCIE_LINK_LEGACY_IRQ(1):
+	case PIC_PCIE_LINK_LEGACY_IRQ(2):
+	case PIC_PCIE_LINK_LEGACY_IRQ(3):
+		return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
+	}
+	return -1;
+}
+
+static int xlp_irq_to_irt(int irq)
 {
 	uint64_t pcibase;
 	int devoff, irt;
 
-	/* bypass for 9xx */
-	if (cpu_is_xlp9xx()) {
-		switch (irq) {
-		case PIC_9XX_XHCI_0_IRQ:
-			return 114;
-		case PIC_9XX_XHCI_1_IRQ:
-			return 115;
-		case PIC_UART_0_IRQ:
-			return 133;
-		case PIC_UART_1_IRQ:
-			return 134;
-		case PIC_PCIE_LINK_LEGACY_IRQ(0):
-		case PIC_PCIE_LINK_LEGACY_IRQ(1):
-		case PIC_PCIE_LINK_LEGACY_IRQ(2):
-		case PIC_PCIE_LINK_LEGACY_IRQ(3):
-			return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
-		}
-		return -1;
-	}
-
 	devoff = 0;
 	switch (irq) {
 	case PIC_UART_0_IRQ:
@@ -100,7 +108,7 @@ int nlm_irq_to_irt(int irq)
 		devoff = XLP_IO_UART1_OFFSET(0);
 		break;
 	case PIC_MMC_IRQ:
-		devoff = XLP_IO_SD_OFFSET(0);
+		devoff = XLP_IO_MMC_OFFSET(0);
 		break;
 	case PIC_I2C_0_IRQ:	/* I2C will be fixed up */
 	case PIC_I2C_1_IRQ:
@@ -111,6 +119,18 @@ int nlm_irq_to_irt(int irq)
 		else
 			devoff = XLP_IO_I2C0_OFFSET(0);
 		break;
+	case PIC_SATA_IRQ:
+		devoff = XLP_IO_SATA_OFFSET(0);
+		break;
+	case PIC_GPIO_IRQ:
+		devoff = XLP_IO_SATA_OFFSET(0);
+		break;
+	case PIC_NAND_IRQ:
+		devoff = XLP_IO_NAND_OFFSET(0);
+		break;
+	case PIC_SPI_IRQ:
+		devoff = XLP_IO_SPI_OFFSET(0);
+		break;
 	default:
 		if (cpu_is_xlpii()) {
 			switch (irq) {
@@ -166,18 +186,26 @@ int nlm_irq_to_irt(int irq)
 		/* HW bug, PCI IRT entries are bad on early silicon, fix */
 		irt = PIC_IRT_PCIE_LINK_INDEX(irq -
 					PIC_PCIE_LINK_LEGACY_IRQ_BASE);
-	} else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) &&
-			irq <= PIC_PCIE_LINK_MSI_IRQ(3)) {
-		irt = -2;
-	} else if (irq >= PIC_PCIE_MSIX_IRQ(0) &&
-			irq <= PIC_PCIE_MSIX_IRQ(3)) {
-		irt = -2;
 	} else {
 		irt = -1;
 	}
 	return irt;
 }
 
+int nlm_irq_to_irt(int irq)
+{
+	/* return -2 for irqs without 1-1 mapping */
+	if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
+		return -2;
+	if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
+		return -2;
+
+	if (cpu_is_xlp9xx())
+		return xlp9xx_irq_to_irt(irq);
+	else
+		return xlp_irq_to_irt(irq);
+}
+
 unsigned int nlm_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
-- 
1.7.9.5

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

* [PATCH 09/17] MIPS: Netlogic: IRQ mapping for some more SoC blocks
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Add IRQ to IRT (PIC interupt table index) mapping for SATA, GPIO, NAND
and SPI interfaces on the XLP SoC. Fix offsets for few blocks and add
device IDs for a few blocks.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/iomap.h |   16 +++--
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h   |    4 ++
 arch/mips/netlogic/xlp/nlm_hal.c               |   84 ++++++++++++++++--------
 3 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 1f23dfa..14b2f51 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -74,6 +74,8 @@
 #define XLP_IO_USB_OHCI2_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 4)
 #define XLP_IO_USB_OHCI3_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 5)
 
+#define XLP_IO_SATA_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 3, 2)
+
 /* XLP2xx has an updated USB block */
 #define XLP2XX_IO_USB_OFFSET(node, i)	XLP_HDR_OFFSET(node, 0, 4, i)
 #define XLP2XX_IO_USB_XHCI0_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 4, 1)
@@ -103,13 +105,11 @@
 #define XLP_IO_SYS_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 6, 5)
 #define XLP_IO_JTAG_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 6, 6)
 
+/* Flash */
 #define XLP_IO_NOR_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 0)
 #define XLP_IO_NAND_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 7, 1)
 #define XLP_IO_SPI_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 2)
-/* SD flash */
-#define XLP_IO_SD_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
-#define XLP_IO_MMC_OFFSET(node, slot)	\
-		((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+#define XLP_IO_MMC_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
 
 /* Things have changed drastically in XLP 9XX */
 #define XLP9XX_HDR_OFFSET(n, d, f)	\
@@ -135,11 +135,11 @@
 /* XLP9XX on-chip SATA controller */
 #define XLP9XX_IO_SATA_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 3, 2)
 
+/* Flash */
 #define XLP9XX_IO_NOR_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 0)
 #define XLP9XX_IO_NAND_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 1)
 #define XLP9XX_IO_SPI_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 2)
-/* SD flash */
-#define XLP9XX_IO_MMCSD_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
+#define XLP9XX_IO_MMC_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
 
 /* PCI config header register id's */
 #define XLP_PCI_CFGREG0			0x00
@@ -186,8 +186,10 @@
 #define PCI_DEVICE_ID_NLM_NOR		0x1015
 #define PCI_DEVICE_ID_NLM_NAND		0x1016
 #define PCI_DEVICE_ID_NLM_MMC		0x1018
-#define PCI_DEVICE_ID_NLM_XHCI		0x101d
+#define PCI_DEVICE_ID_NLM_SATA		0x101A
+#define PCI_DEVICE_ID_NLM_XHCI		0x101D
 
+#define PCI_DEVICE_ID_XLP9XX_MMC	0x9018
 #define PCI_DEVICE_ID_XLP9XX_SATA	0x901A
 #define PCI_DEVICE_ID_XLP9XX_XHCI	0x901D
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 1b56bd4..488863e 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -58,6 +58,10 @@
 #define PIC_I2C_1_IRQ			31
 #define PIC_I2C_2_IRQ			32
 #define PIC_I2C_3_IRQ			33
+#define PIC_SPI_IRQ			34
+#define PIC_NAND_IRQ			37
+#define PIC_SATA_IRQ			38
+#define PIC_GPIO_IRQ			39
 
 #define PIC_PCIE_LINK_MSI_IRQ_BASE	44	/* 44 - 47 MSI IRQ */
 #define PIC_PCIE_LINK_MSI_IRQ(i)	(44 + (i))
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index d85019b..44dc159 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -66,31 +66,39 @@ void nlm_node_init(int node)
 	spin_lock_init(&nodep->piclock);
 }
 
-int nlm_irq_to_irt(int irq)
+static int xlp9xx_irq_to_irt(int irq)
+{
+	switch (irq) {
+	case PIC_GPIO_IRQ:
+		return 12;
+	case PIC_9XX_XHCI_0_IRQ:
+		return 114;
+	case PIC_9XX_XHCI_1_IRQ:
+		return 115;
+	case PIC_UART_0_IRQ:
+		return 133;
+	case PIC_UART_1_IRQ:
+		return 134;
+	case PIC_SATA_IRQ:
+		return 143;
+	case PIC_SPI_IRQ:
+		return 152;
+	case PIC_MMC_IRQ:
+		return 153;
+	case PIC_PCIE_LINK_LEGACY_IRQ(0):
+	case PIC_PCIE_LINK_LEGACY_IRQ(1):
+	case PIC_PCIE_LINK_LEGACY_IRQ(2):
+	case PIC_PCIE_LINK_LEGACY_IRQ(3):
+		return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
+	}
+	return -1;
+}
+
+static int xlp_irq_to_irt(int irq)
 {
 	uint64_t pcibase;
 	int devoff, irt;
 
-	/* bypass for 9xx */
-	if (cpu_is_xlp9xx()) {
-		switch (irq) {
-		case PIC_9XX_XHCI_0_IRQ:
-			return 114;
-		case PIC_9XX_XHCI_1_IRQ:
-			return 115;
-		case PIC_UART_0_IRQ:
-			return 133;
-		case PIC_UART_1_IRQ:
-			return 134;
-		case PIC_PCIE_LINK_LEGACY_IRQ(0):
-		case PIC_PCIE_LINK_LEGACY_IRQ(1):
-		case PIC_PCIE_LINK_LEGACY_IRQ(2):
-		case PIC_PCIE_LINK_LEGACY_IRQ(3):
-			return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
-		}
-		return -1;
-	}
-
 	devoff = 0;
 	switch (irq) {
 	case PIC_UART_0_IRQ:
@@ -100,7 +108,7 @@ int nlm_irq_to_irt(int irq)
 		devoff = XLP_IO_UART1_OFFSET(0);
 		break;
 	case PIC_MMC_IRQ:
-		devoff = XLP_IO_SD_OFFSET(0);
+		devoff = XLP_IO_MMC_OFFSET(0);
 		break;
 	case PIC_I2C_0_IRQ:	/* I2C will be fixed up */
 	case PIC_I2C_1_IRQ:
@@ -111,6 +119,18 @@ int nlm_irq_to_irt(int irq)
 		else
 			devoff = XLP_IO_I2C0_OFFSET(0);
 		break;
+	case PIC_SATA_IRQ:
+		devoff = XLP_IO_SATA_OFFSET(0);
+		break;
+	case PIC_GPIO_IRQ:
+		devoff = XLP_IO_SATA_OFFSET(0);
+		break;
+	case PIC_NAND_IRQ:
+		devoff = XLP_IO_NAND_OFFSET(0);
+		break;
+	case PIC_SPI_IRQ:
+		devoff = XLP_IO_SPI_OFFSET(0);
+		break;
 	default:
 		if (cpu_is_xlpii()) {
 			switch (irq) {
@@ -166,18 +186,26 @@ int nlm_irq_to_irt(int irq)
 		/* HW bug, PCI IRT entries are bad on early silicon, fix */
 		irt = PIC_IRT_PCIE_LINK_INDEX(irq -
 					PIC_PCIE_LINK_LEGACY_IRQ_BASE);
-	} else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) &&
-			irq <= PIC_PCIE_LINK_MSI_IRQ(3)) {
-		irt = -2;
-	} else if (irq >= PIC_PCIE_MSIX_IRQ(0) &&
-			irq <= PIC_PCIE_MSIX_IRQ(3)) {
-		irt = -2;
 	} else {
 		irt = -1;
 	}
 	return irt;
 }
 
+int nlm_irq_to_irt(int irq)
+{
+	/* return -2 for irqs without 1-1 mapping */
+	if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
+		return -2;
+	if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
+		return -2;
+
+	if (cpu_is_xlp9xx())
+		return xlp9xx_irq_to_irt(irq);
+	else
+		return xlp_irq_to_irt(irq);
+}
+
 unsigned int nlm_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
-- 
1.7.9.5

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

* [PATCH 10/17] MIPS: Netlogic: Use PRID_IMP_MASK macro
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Use PRID_IMP_MASK macro instead of 0xff00 to extract the processor
type.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/mips-extns.h  |    4 ++--
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h |    4 ++--
 arch/mips/netlogic/common/reset.S            |    5 +++--
 arch/mips/netlogic/xlp/dt.c                  |    2 +-
 arch/mips/netlogic/xlp/setup.c               |    2 +-
 arch/mips/netlogic/xlp/wakeup.c              |    2 +-
 6 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index de9aada..38af905 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -146,9 +146,9 @@ static inline int hard_smp_processor_id(void)
 
 static inline int nlm_nodeid(void)
 {
-	uint32_t prid = read_c0_prid();
+	uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
 
-	if ((prid & 0xff00) == PRID_IMP_NETLOGIC_XLP9XX)
+	if (prid == PRID_IMP_NETLOGIC_XLP9XX)
 		return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
 	else
 		return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 488863e..f75014c 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -99,7 +99,7 @@ void *xlp_dt_init(void *fdtp);
 
 static inline int cpu_is_xlpii(void)
 {
-	int chip = read_c0_prid() & 0xff00;
+	int chip = read_c0_prid() & PRID_IMP_MASK;
 
 	return chip == PRID_IMP_NETLOGIC_XLP2XX ||
 		chip == PRID_IMP_NETLOGIC_XLP9XX;
@@ -107,7 +107,7 @@ static inline int cpu_is_xlpii(void)
 
 static inline int cpu_is_xlp9xx(void)
 {
-	int chip = read_c0_prid() & 0xff00;
+	int chip = read_c0_prid() & PRID_IMP_MASK;
 
 	return chip == PRID_IMP_NETLOGIC_XLP9XX;
 }
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index 13c1bc5..5b60b46 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -35,6 +35,7 @@
 
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/cpu.h>
 #include <asm/cacheops.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
@@ -92,7 +93,7 @@
  */
 .macro	xlp_flush_l1_dcache
 	mfc0	t0, CP0_EBASE, 0
-	andi	t0, t0, 0xff00
+	andi	t0, t0, PRID_IMP_MASK
 	slt	t1, t0, 0x1200
 	beqz	t1, 15f
 	nop
@@ -171,7 +172,7 @@ FEXPORT(nlm_reset_entry)
 
 1:	/* Entry point on core wakeup */
 	mfc0	t0, CP0_EBASE, 0	/* processor ID */
-	andi	t0, 0xff00
+	andi	t0, PRID_IMP_MASK
 	li	t1, 0x1500		/* XLP 9xx */
 	beq	t0, t1, 2f		/* does not need to set coherent */
 	nop
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
index 5754097..0b36ac8 100644
--- a/arch/mips/netlogic/xlp/dt.c
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -48,7 +48,7 @@ static void *xlp_fdt_blob;
 void __init *xlp_dt_init(void *fdtp)
 {
 	if (!fdtp) {
-		switch (current_cpu_data.processor_id & 0xff00) {
+		switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
 #ifdef CONFIG_DT_XLP_GVP
 		case PRID_IMP_NETLOGIC_XLP9XX:
 			fdtp = __dtb_xlp_gvp_begin;
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index d1c9e88..3455e9f 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -121,7 +121,7 @@ void __init plat_mem_setup(void)
 
 const char *get_system_type(void)
 {
-	switch (read_c0_prid() & 0xff00) {
+	switch (read_c0_prid() & PRID_IMP_MASK) {
 	case PRID_IMP_NETLOGIC_XLP9XX:
 	case PRID_IMP_NETLOGIC_XLP2XX:
 		return "Broadcom XLPII Series";
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 7589238..f4823ad 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -139,7 +139,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
 		} else {
 			fusemask = nlm_read_sys_reg(nodep->sysbase,
 						SYS_EFUSE_DEVICE_CFG_STATUS0);
-			switch (read_c0_prid() & 0xff00) {
+			switch (read_c0_prid() & PRID_IMP_MASK) {
 			case PRID_IMP_NETLOGIC_XLP3XX:
 				mask = 0xf;
 				break;
-- 
1.7.9.5

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

* [PATCH 10/17] MIPS: Netlogic: Use PRID_IMP_MASK macro
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Use PRID_IMP_MASK macro instead of 0xff00 to extract the processor
type.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/mips-extns.h  |    4 ++--
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h |    4 ++--
 arch/mips/netlogic/common/reset.S            |    5 +++--
 arch/mips/netlogic/xlp/dt.c                  |    2 +-
 arch/mips/netlogic/xlp/setup.c               |    2 +-
 arch/mips/netlogic/xlp/wakeup.c              |    2 +-
 6 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index de9aada..38af905 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -146,9 +146,9 @@ static inline int hard_smp_processor_id(void)
 
 static inline int nlm_nodeid(void)
 {
-	uint32_t prid = read_c0_prid();
+	uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
 
-	if ((prid & 0xff00) == PRID_IMP_NETLOGIC_XLP9XX)
+	if (prid == PRID_IMP_NETLOGIC_XLP9XX)
 		return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
 	else
 		return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 488863e..f75014c 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -99,7 +99,7 @@ void *xlp_dt_init(void *fdtp);
 
 static inline int cpu_is_xlpii(void)
 {
-	int chip = read_c0_prid() & 0xff00;
+	int chip = read_c0_prid() & PRID_IMP_MASK;
 
 	return chip == PRID_IMP_NETLOGIC_XLP2XX ||
 		chip == PRID_IMP_NETLOGIC_XLP9XX;
@@ -107,7 +107,7 @@ static inline int cpu_is_xlpii(void)
 
 static inline int cpu_is_xlp9xx(void)
 {
-	int chip = read_c0_prid() & 0xff00;
+	int chip = read_c0_prid() & PRID_IMP_MASK;
 
 	return chip == PRID_IMP_NETLOGIC_XLP9XX;
 }
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index 13c1bc5..5b60b46 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -35,6 +35,7 @@
 
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
+#include <asm/cpu.h>
 #include <asm/cacheops.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
@@ -92,7 +93,7 @@
  */
 .macro	xlp_flush_l1_dcache
 	mfc0	t0, CP0_EBASE, 0
-	andi	t0, t0, 0xff00
+	andi	t0, t0, PRID_IMP_MASK
 	slt	t1, t0, 0x1200
 	beqz	t1, 15f
 	nop
@@ -171,7 +172,7 @@ FEXPORT(nlm_reset_entry)
 
 1:	/* Entry point on core wakeup */
 	mfc0	t0, CP0_EBASE, 0	/* processor ID */
-	andi	t0, 0xff00
+	andi	t0, PRID_IMP_MASK
 	li	t1, 0x1500		/* XLP 9xx */
 	beq	t0, t1, 2f		/* does not need to set coherent */
 	nop
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
index 5754097..0b36ac8 100644
--- a/arch/mips/netlogic/xlp/dt.c
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -48,7 +48,7 @@ static void *xlp_fdt_blob;
 void __init *xlp_dt_init(void *fdtp)
 {
 	if (!fdtp) {
-		switch (current_cpu_data.processor_id & 0xff00) {
+		switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
 #ifdef CONFIG_DT_XLP_GVP
 		case PRID_IMP_NETLOGIC_XLP9XX:
 			fdtp = __dtb_xlp_gvp_begin;
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index d1c9e88..3455e9f 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -121,7 +121,7 @@ void __init plat_mem_setup(void)
 
 const char *get_system_type(void)
 {
-	switch (read_c0_prid() & 0xff00) {
+	switch (read_c0_prid() & PRID_IMP_MASK) {
 	case PRID_IMP_NETLOGIC_XLP9XX:
 	case PRID_IMP_NETLOGIC_XLP2XX:
 		return "Broadcom XLPII Series";
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 7589238..f4823ad 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -139,7 +139,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
 		} else {
 			fusemask = nlm_read_sys_reg(nodep->sysbase,
 						SYS_EFUSE_DEVICE_CFG_STATUS0);
-			switch (read_c0_prid() & 0xff00) {
+			switch (read_c0_prid() & PRID_IMP_MASK) {
 			case PRID_IMP_NETLOGIC_XLP3XX:
 				mask = 0xf;
 				break;
-- 
1.7.9.5

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

* [PATCH 11/17] MIPS: Netlogic: Fix XLP9XX pic entry
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Add the compatible property to the PIC entry. Also fix up the nodename
to use the correct address.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/dts/xlp_gvp.dts |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts
index 047d27f..bb4ecd1 100644
--- a/arch/mips/netlogic/dts/xlp_gvp.dts
+++ b/arch/mips/netlogic/dts/xlp_gvp.dts
@@ -26,11 +26,12 @@
 			interrupt-parent = <&pic>;
 			interrupts = <17>;
 		};
-		pic: pic@4000 {
-			interrupt-controller;
+		pic: pic@110000 {
+			compatible = "netlogic,xlp-pic";
 			#address-cells = <0>;
 			#interrupt-cells = <1>;
 			reg = <0 0x110000 0x200>;
+			interrupt-controller;
 		};
 
 		nor_flash@1,0 {
-- 
1.7.9.5

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

* [PATCH 11/17] MIPS: Netlogic: Fix XLP9XX pic entry
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Add the compatible property to the PIC entry. Also fix up the nodename
to use the correct address.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/dts/xlp_gvp.dts |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts
index 047d27f..bb4ecd1 100644
--- a/arch/mips/netlogic/dts/xlp_gvp.dts
+++ b/arch/mips/netlogic/dts/xlp_gvp.dts
@@ -26,11 +26,12 @@
 			interrupt-parent = <&pic>;
 			interrupts = <17>;
 		};
-		pic: pic@4000 {
-			interrupt-controller;
+		pic: pic@110000 {
+			compatible = "netlogic,xlp-pic";
 			#address-cells = <0>;
 			#interrupt-cells = <1>;
 			reg = <0 0x110000 0x200>;
+			interrupt-controller;
 		};
 
 		nor_flash@1,0 {
-- 
1.7.9.5

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

* [PATCH 12/17] MIPS: Netlogic: PIC freq calculation for XLP 9XX/2XX
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

Update PIC frequency calculation for XLP9XX and 2XX processors using
the correct PLL registers. This should work for all possible board
configurations.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/iomap.h |    2 +
 arch/mips/include/asm/netlogic/xlp-hal/sys.h   |   27 ++++++
 arch/mips/netlogic/common/time.c               |    5 +-
 arch/mips/netlogic/xlp/nlm_hal.c               |  114 +++++++++++++++++-------
 4 files changed, 114 insertions(+), 34 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 14b2f51..805bfd2 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -120,6 +120,8 @@
 #define XLP9XX_IO_UART_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 2, 2)
 #define XLP9XX_IO_SYS_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 0)
 #define XLP9XX_IO_FUSE_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 1)
+#define XLP9XX_IO_CLOCK_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 2)
+#define XLP9XX_IO_POWER_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 3)
 #define XLP9XX_IO_JTAG_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 4)
 
 #define XLP9XX_IO_PCIE_OFFSET(node, i)	XLP9XX_HDR_OFFSET(node, 1, i)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index d9b107f..bcb136d 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -147,6 +147,28 @@
 #define SYS_SYS_PLL_MEM_REQ			0x2a3
 #define SYS_PLL_MEM_STAT			0x2a4
 
+/* PLL registers XLP9XX */
+#define SYS_9XX_DMC_PLL_CTRL0			0x140
+#define SYS_9XX_DMC_PLL_CTRL1			0x141
+#define SYS_9XX_DMC_PLL_CTRL2			0x142
+#define SYS_9XX_DMC_PLL_CTRL3			0x143
+#define SYS_9XX_PLL_CTRL0			0x144
+#define SYS_9XX_PLL_CTRL1			0x145
+#define SYS_9XX_PLL_CTRL2			0x146
+#define SYS_9XX_PLL_CTRL3			0x147
+
+#define SYS_9XX_PLL_CTRL0_DEVX(x)		(0x148 + (x) * 4)
+#define SYS_9XX_PLL_CTRL1_DEVX(x)		(0x149 + (x) * 4)
+#define SYS_9XX_PLL_CTRL2_DEVX(x)		(0x14a + (x) * 4)
+#define SYS_9XX_PLL_CTRL3_DEVX(x)		(0x14b + (x) * 4)
+
+#define SYS_9XX_CPU_PLL_CHG_CTRL		0x188
+#define SYS_9XX_PLL_CHG_CTRL			0x189
+#define SYS_9XX_CLK_DEV_DIS			0x18a
+#define SYS_9XX_CLK_DEV_SEL			0x18b
+#define SYS_9XX_CLK_DEV_DIV			0x18d
+#define SYS_9XX_CLK_DEV_CHG			0x18f
+
 /* Registers changed on 9XX */
 #define SYS_9XX_POWER_ON_RESET_CFG		0x00
 #define SYS_9XX_CHIP_RESET			0x01
@@ -170,6 +192,11 @@
 #define nlm_get_fuse_regbase(node)	\
 			(nlm_get_fuse_pcibase(node) + XLP_IO_PCI_HDRSZ)
 
+#define nlm_get_clock_pcibase(node)	\
+			nlm_pcicfg_base(XLP9XX_IO_CLOCK_OFFSET(node))
+#define nlm_get_clock_regbase(node)	\
+			(nlm_get_clock_pcibase(node) + XLP_IO_PCI_HDRSZ)
+
 unsigned int nlm_get_pic_frequency(int node);
 #endif
 #endif
diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c
index 13391b8..0c0a1a6 100644
--- a/arch/mips/netlogic/common/time.c
+++ b/arch/mips/netlogic/common/time.c
@@ -82,6 +82,7 @@ static struct clocksource csrc_pic = {
 static void nlm_init_pic_timer(void)
 {
 	uint64_t picbase = nlm_get_node(0)->picbase;
+	u32 picfreq;
 
 	nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
 	if (current_cpu_data.cputype == CPU_XLR) {
@@ -92,7 +93,9 @@ static void nlm_init_pic_timer(void)
 		csrc_pic.read	= nlm_get_pic_timer;
 	}
 	csrc_pic.rating = 1000;
-	clocksource_register_hz(&csrc_pic, pic_timer_freq());
+	picfreq = pic_timer_freq();
+	clocksource_register_hz(&csrc_pic, picfreq);
+	pr_info("PIC clock source added, frequency %d\n", picfreq);
 }
 
 void __init plat_time_init(void)
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 44dc159..94469a9 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -234,21 +234,28 @@ unsigned int nlm_get_core_frequency(int node, int core)
 	return (unsigned int)num;
 }
 
-/* Calculate Frequency to the PIC from PLL.
- * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) /
- * ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
+/*
+ * Calculate PIC frequency from PLL registers.
+ * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
+ * 		((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
  */
-static unsigned int nlm_2xx_get_pic_frequency(int node)
+static unsigned int nlm_xlp2_get_pic_frequency(int node)
 {
-	u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div;
+	u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx;
 	u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
-	u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select;
+	u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk;
 
 	sysbase = nlm_get_node(node)->sysbase;
+	clockbase = nlm_get_clock_regbase(node);
+	cpu_xlp9xx = cpu_is_xlp9xx();
 
 	/* Find ref_clk_base */
-	ref_clk_select =
-		(nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
+	if (cpu_xlp9xx)
+		ref_clk_select = (nlm_read_sys_reg(sysbase,
+				SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3;
+	else
+		ref_clk_select = (nlm_read_sys_reg(sysbase,
+					SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
 	switch (ref_clk_select) {
 	case 0:
 		ref_clk = 200000000ULL;
@@ -269,30 +276,70 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
 	}
 
 	/* Find the clock source PLL device for PIC */
-	reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3;
-	switch (reg_select) {
-	case 0:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0);
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2);
-		break;
-	case 1:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0));
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0));
-		break;
-	case 2:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1));
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1));
-		break;
-	case 3:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2));
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2));
-		break;
+	if (cpu_xlp9xx) {
+		reg_select = nlm_read_sys_reg(clockbase,
+				SYS_9XX_CLK_DEV_SEL) & 0x3;
+		switch (reg_select) {
+		case 0:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0);
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2);
+			break;
+		case 1:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0_DEVX(0));
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2_DEVX(0));
+			break;
+		case 2:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0_DEVX(1));
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2_DEVX(1));
+			break;
+		case 3:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0_DEVX(2));
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2_DEVX(2));
+			break;
+		}
+	} else {
+		reg_select = (nlm_read_sys_reg(sysbase,
+					SYS_CLK_DEV_SEL) >> 22) & 0x3;
+		switch (reg_select) {
+		case 0:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0);
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2);
+			break;
+		case 1:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0_DEVX(0));
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2_DEVX(0));
+			break;
+		case 2:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0_DEVX(1));
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2_DEVX(1));
+			break;
+		case 3:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0_DEVX(2));
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2_DEVX(2));
+			break;
+		}
 	}
 
 	vco_post_div = (ctrl_val0 >> 5) & 0x7;
 	pll_post_div = (ctrl_val0 >> 24) & 0x7;
 	mdiv = ctrl_val2 & 0xff;
-	fdiv = (ctrl_val2 >> 8) & 0xfff;
+	fdiv = (ctrl_val2 >> 8) & 0x1fff;
 
 	/* Find PLL post divider value */
 	switch (pll_post_div) {
@@ -322,7 +369,12 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
 		do_div(pll_out_freq_num, pll_out_freq_den);
 
 	/* PIC post divider, which happens after PLL */
-	pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3;
+	if (cpu_xlp9xx)
+		pic_div = nlm_read_sys_reg(clockbase,
+				SYS_9XX_CLK_DEV_DIV) & 0x3;
+	else
+		pic_div = (nlm_read_sys_reg(sysbase,
+					SYS_CLK_DEV_DIV) >> 22) & 0x3;
 	do_div(pll_out_freq_num, 1 << pic_div);
 
 	return pll_out_freq_num;
@@ -330,12 +382,8 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
 
 unsigned int nlm_get_pic_frequency(int node)
 {
-	/* TODO Has to calculate freq as like 2xx */
-	if (cpu_is_xlp9xx())
-		return 250000000;
-
 	if (cpu_is_xlpii())
-		return nlm_2xx_get_pic_frequency(node);
+		return nlm_xlp2_get_pic_frequency(node);
 	else
 		return 133333333;
 }
-- 
1.7.9.5

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

* [PATCH 12/17] MIPS: Netlogic: PIC freq calculation for XLP 9XX/2XX
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

Update PIC frequency calculation for XLP9XX and 2XX processors using
the correct PLL registers. This should work for all possible board
configurations.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/iomap.h |    2 +
 arch/mips/include/asm/netlogic/xlp-hal/sys.h   |   27 ++++++
 arch/mips/netlogic/common/time.c               |    5 +-
 arch/mips/netlogic/xlp/nlm_hal.c               |  114 +++++++++++++++++-------
 4 files changed, 114 insertions(+), 34 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 14b2f51..805bfd2 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -120,6 +120,8 @@
 #define XLP9XX_IO_UART_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 2, 2)
 #define XLP9XX_IO_SYS_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 0)
 #define XLP9XX_IO_FUSE_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 1)
+#define XLP9XX_IO_CLOCK_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 2)
+#define XLP9XX_IO_POWER_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 3)
 #define XLP9XX_IO_JTAG_OFFSET(node)	XLP9XX_HDR_OFFSET(node, 6, 4)
 
 #define XLP9XX_IO_PCIE_OFFSET(node, i)	XLP9XX_HDR_OFFSET(node, 1, i)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index d9b107f..bcb136d 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -147,6 +147,28 @@
 #define SYS_SYS_PLL_MEM_REQ			0x2a3
 #define SYS_PLL_MEM_STAT			0x2a4
 
+/* PLL registers XLP9XX */
+#define SYS_9XX_DMC_PLL_CTRL0			0x140
+#define SYS_9XX_DMC_PLL_CTRL1			0x141
+#define SYS_9XX_DMC_PLL_CTRL2			0x142
+#define SYS_9XX_DMC_PLL_CTRL3			0x143
+#define SYS_9XX_PLL_CTRL0			0x144
+#define SYS_9XX_PLL_CTRL1			0x145
+#define SYS_9XX_PLL_CTRL2			0x146
+#define SYS_9XX_PLL_CTRL3			0x147
+
+#define SYS_9XX_PLL_CTRL0_DEVX(x)		(0x148 + (x) * 4)
+#define SYS_9XX_PLL_CTRL1_DEVX(x)		(0x149 + (x) * 4)
+#define SYS_9XX_PLL_CTRL2_DEVX(x)		(0x14a + (x) * 4)
+#define SYS_9XX_PLL_CTRL3_DEVX(x)		(0x14b + (x) * 4)
+
+#define SYS_9XX_CPU_PLL_CHG_CTRL		0x188
+#define SYS_9XX_PLL_CHG_CTRL			0x189
+#define SYS_9XX_CLK_DEV_DIS			0x18a
+#define SYS_9XX_CLK_DEV_SEL			0x18b
+#define SYS_9XX_CLK_DEV_DIV			0x18d
+#define SYS_9XX_CLK_DEV_CHG			0x18f
+
 /* Registers changed on 9XX */
 #define SYS_9XX_POWER_ON_RESET_CFG		0x00
 #define SYS_9XX_CHIP_RESET			0x01
@@ -170,6 +192,11 @@
 #define nlm_get_fuse_regbase(node)	\
 			(nlm_get_fuse_pcibase(node) + XLP_IO_PCI_HDRSZ)
 
+#define nlm_get_clock_pcibase(node)	\
+			nlm_pcicfg_base(XLP9XX_IO_CLOCK_OFFSET(node))
+#define nlm_get_clock_regbase(node)	\
+			(nlm_get_clock_pcibase(node) + XLP_IO_PCI_HDRSZ)
+
 unsigned int nlm_get_pic_frequency(int node);
 #endif
 #endif
diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c
index 13391b8..0c0a1a6 100644
--- a/arch/mips/netlogic/common/time.c
+++ b/arch/mips/netlogic/common/time.c
@@ -82,6 +82,7 @@ static struct clocksource csrc_pic = {
 static void nlm_init_pic_timer(void)
 {
 	uint64_t picbase = nlm_get_node(0)->picbase;
+	u32 picfreq;
 
 	nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
 	if (current_cpu_data.cputype == CPU_XLR) {
@@ -92,7 +93,9 @@ static void nlm_init_pic_timer(void)
 		csrc_pic.read	= nlm_get_pic_timer;
 	}
 	csrc_pic.rating = 1000;
-	clocksource_register_hz(&csrc_pic, pic_timer_freq());
+	picfreq = pic_timer_freq();
+	clocksource_register_hz(&csrc_pic, picfreq);
+	pr_info("PIC clock source added, frequency %d\n", picfreq);
 }
 
 void __init plat_time_init(void)
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 44dc159..94469a9 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -234,21 +234,28 @@ unsigned int nlm_get_core_frequency(int node, int core)
 	return (unsigned int)num;
 }
 
-/* Calculate Frequency to the PIC from PLL.
- * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) /
- * ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
+/*
+ * Calculate PIC frequency from PLL registers.
+ * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
+ * 		((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
  */
-static unsigned int nlm_2xx_get_pic_frequency(int node)
+static unsigned int nlm_xlp2_get_pic_frequency(int node)
 {
-	u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div;
+	u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx;
 	u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
-	u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select;
+	u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk;
 
 	sysbase = nlm_get_node(node)->sysbase;
+	clockbase = nlm_get_clock_regbase(node);
+	cpu_xlp9xx = cpu_is_xlp9xx();
 
 	/* Find ref_clk_base */
-	ref_clk_select =
-		(nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
+	if (cpu_xlp9xx)
+		ref_clk_select = (nlm_read_sys_reg(sysbase,
+				SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3;
+	else
+		ref_clk_select = (nlm_read_sys_reg(sysbase,
+					SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
 	switch (ref_clk_select) {
 	case 0:
 		ref_clk = 200000000ULL;
@@ -269,30 +276,70 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
 	}
 
 	/* Find the clock source PLL device for PIC */
-	reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3;
-	switch (reg_select) {
-	case 0:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0);
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2);
-		break;
-	case 1:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0));
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0));
-		break;
-	case 2:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1));
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1));
-		break;
-	case 3:
-		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2));
-		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2));
-		break;
+	if (cpu_xlp9xx) {
+		reg_select = nlm_read_sys_reg(clockbase,
+				SYS_9XX_CLK_DEV_SEL) & 0x3;
+		switch (reg_select) {
+		case 0:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0);
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2);
+			break;
+		case 1:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0_DEVX(0));
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2_DEVX(0));
+			break;
+		case 2:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0_DEVX(1));
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2_DEVX(1));
+			break;
+		case 3:
+			ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL0_DEVX(2));
+			ctrl_val2 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_PLL_CTRL2_DEVX(2));
+			break;
+		}
+	} else {
+		reg_select = (nlm_read_sys_reg(sysbase,
+					SYS_CLK_DEV_SEL) >> 22) & 0x3;
+		switch (reg_select) {
+		case 0:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0);
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2);
+			break;
+		case 1:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0_DEVX(0));
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2_DEVX(0));
+			break;
+		case 2:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0_DEVX(1));
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2_DEVX(1));
+			break;
+		case 3:
+			ctrl_val0 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL0_DEVX(2));
+			ctrl_val2 = nlm_read_sys_reg(sysbase,
+					SYS_PLL_CTRL2_DEVX(2));
+			break;
+		}
 	}
 
 	vco_post_div = (ctrl_val0 >> 5) & 0x7;
 	pll_post_div = (ctrl_val0 >> 24) & 0x7;
 	mdiv = ctrl_val2 & 0xff;
-	fdiv = (ctrl_val2 >> 8) & 0xfff;
+	fdiv = (ctrl_val2 >> 8) & 0x1fff;
 
 	/* Find PLL post divider value */
 	switch (pll_post_div) {
@@ -322,7 +369,12 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
 		do_div(pll_out_freq_num, pll_out_freq_den);
 
 	/* PIC post divider, which happens after PLL */
-	pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3;
+	if (cpu_xlp9xx)
+		pic_div = nlm_read_sys_reg(clockbase,
+				SYS_9XX_CLK_DEV_DIV) & 0x3;
+	else
+		pic_div = (nlm_read_sys_reg(sysbase,
+					SYS_CLK_DEV_DIV) >> 22) & 0x3;
 	do_div(pll_out_freq_num, 1 << pic_div);
 
 	return pll_out_freq_num;
@@ -330,12 +382,8 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
 
 unsigned int nlm_get_pic_frequency(int node)
 {
-	/* TODO Has to calculate freq as like 2xx */
-	if (cpu_is_xlp9xx())
-		return 250000000;
-
 	if (cpu_is_xlpii())
-		return nlm_2xx_get_pic_frequency(node);
+		return nlm_xlp2_get_pic_frequency(node);
 	else
 		return 133333333;
 }
-- 
1.7.9.5

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

* [PATCH 13/17] MIPS: Netlogic: Update XLP9XX/2XX core freq calculation
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Calculate XLP 9XX and 2XX core frequency from the per-core PLL. This
should give the correct value for all board configurations.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/sys.h |    8 +++
 arch/mips/netlogic/xlp/nlm_hal.c             |   83 ++++++++++++++++++++------
 2 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index bcb136d..bc7bddf 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -118,6 +118,10 @@
 #define SYS_SCRTCH3				0x4c
 
 /* PLL registers XLP2XX */
+#define SYS_CPU_PLL_CTRL0(core)			(0x1c0 + (core * 4))
+#define SYS_CPU_PLL_CTRL1(core)			(0x1c1 + (core * 4))
+#define SYS_CPU_PLL_CTRL2(core)			(0x1c2 + (core * 4))
+#define SYS_CPU_PLL_CTRL3(core)			(0x1c3 + (core * 4))
 #define SYS_PLL_CTRL0				0x240
 #define SYS_PLL_CTRL1				0x241
 #define SYS_PLL_CTRL2				0x242
@@ -148,6 +152,10 @@
 #define SYS_PLL_MEM_STAT			0x2a4
 
 /* PLL registers XLP9XX */
+#define SYS_9XX_CPU_PLL_CTRL0(core)		(0xc0 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL1(core)		(0xc1 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL2(core)		(0xc2 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL3(core)		(0xc3 + (core * 4))
 #define SYS_9XX_DMC_PLL_CTRL0			0x140
 #define SYS_9XX_DMC_PLL_CTRL1			0x141
 #define SYS_9XX_DMC_PLL_CTRL2			0x142
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 94469a9..a97b0d0 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -206,34 +206,81 @@ int nlm_irq_to_irt(int irq)
 		return xlp_irq_to_irt(irq);
 }
 
-unsigned int nlm_get_core_frequency(int node, int core)
+static unsigned int nlm_xlp2_get_core_frequency(int node, int core)
+{
+	unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom;
+	uint64_t num, sysbase, clockbase;
+
+	if (cpu_is_xlp9xx()) {
+		clockbase = nlm_get_clock_regbase(node);
+		ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_CPU_PLL_CTRL0(core));
+		ctrl_val1 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_CPU_PLL_CTRL1(core));
+	} else {
+		sysbase = nlm_get_node(node)->sysbase;
+		ctrl_val0 = nlm_read_sys_reg(sysbase,
+						SYS_CPU_PLL_CTRL0(core));
+		ctrl_val1 = nlm_read_sys_reg(sysbase,
+						SYS_CPU_PLL_CTRL1(core));
+	}
+
+	/* Find PLL post divider value */
+	switch ((ctrl_val0 >> 24) & 0x7) {
+	case 1:
+		pll_post_div = 2;
+		break;
+	case 3:
+		pll_post_div = 4;
+		break;
+	case 7:
+		pll_post_div = 8;
+		break;
+	case 6:
+		pll_post_div = 16;
+		break;
+	case 0:
+	default:
+		pll_post_div = 1;
+		break;
+	}
+
+	num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f));
+	denom = 3 * pll_post_div;
+	do_div(num, denom);
+
+	return (unsigned int)num;
+}
+
+static unsigned int nlm_xlp_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
 	unsigned int rstval, dfsval, denom;
 	uint64_t num, sysbase;
 
 	sysbase = nlm_get_node(node)->sysbase;
-	if (cpu_is_xlp9xx())
-		rstval = nlm_read_sys_reg(sysbase, SYS_9XX_POWER_ON_RESET_CFG);
-	else
-		rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
-	if (cpu_is_xlpii()) {
-		num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26));
-		denom = 3;
-	} else {
-		dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
-		pll_divf = ((rstval >> 10) & 0x7f) + 1;
-		pll_divr = ((rstval >> 8)  & 0x3) + 1;
-		ext_div  = ((rstval >> 30) & 0x3) + 1;
-		dfs_div  = ((dfsval >> (core * 4)) & 0xf) + 1;
-
-		num = 800000000ULL * pll_divf;
-		denom = 3 * pll_divr * ext_div * dfs_div;
-	}
+	rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
+	dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
+	pll_divf = ((rstval >> 10) & 0x7f) + 1;
+	pll_divr = ((rstval >> 8)  & 0x3) + 1;
+	ext_div  = ((rstval >> 30) & 0x3) + 1;
+	dfs_div  = ((dfsval >> (core * 4)) & 0xf) + 1;
+
+	num = 800000000ULL * pll_divf;
+	denom = 3 * pll_divr * ext_div * dfs_div;
 	do_div(num, denom);
+
 	return (unsigned int)num;
 }
 
+unsigned int nlm_get_core_frequency(int node, int core)
+{
+	if (cpu_is_xlpii())
+		return nlm_xlp2_get_core_frequency(node, core);
+	else
+		return nlm_xlp_get_core_frequency(node, core);
+}
+
 /*
  * Calculate PIC frequency from PLL registers.
  * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
-- 
1.7.9.5

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

* [PATCH 13/17] MIPS: Netlogic: Update XLP9XX/2XX core freq calculation
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Calculate XLP 9XX and 2XX core frequency from the per-core PLL. This
should give the correct value for all board configurations.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/sys.h |    8 +++
 arch/mips/netlogic/xlp/nlm_hal.c             |   83 ++++++++++++++++++++------
 2 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index bcb136d..bc7bddf 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -118,6 +118,10 @@
 #define SYS_SCRTCH3				0x4c
 
 /* PLL registers XLP2XX */
+#define SYS_CPU_PLL_CTRL0(core)			(0x1c0 + (core * 4))
+#define SYS_CPU_PLL_CTRL1(core)			(0x1c1 + (core * 4))
+#define SYS_CPU_PLL_CTRL2(core)			(0x1c2 + (core * 4))
+#define SYS_CPU_PLL_CTRL3(core)			(0x1c3 + (core * 4))
 #define SYS_PLL_CTRL0				0x240
 #define SYS_PLL_CTRL1				0x241
 #define SYS_PLL_CTRL2				0x242
@@ -148,6 +152,10 @@
 #define SYS_PLL_MEM_STAT			0x2a4
 
 /* PLL registers XLP9XX */
+#define SYS_9XX_CPU_PLL_CTRL0(core)		(0xc0 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL1(core)		(0xc1 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL2(core)		(0xc2 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL3(core)		(0xc3 + (core * 4))
 #define SYS_9XX_DMC_PLL_CTRL0			0x140
 #define SYS_9XX_DMC_PLL_CTRL1			0x141
 #define SYS_9XX_DMC_PLL_CTRL2			0x142
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 94469a9..a97b0d0 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -206,34 +206,81 @@ int nlm_irq_to_irt(int irq)
 		return xlp_irq_to_irt(irq);
 }
 
-unsigned int nlm_get_core_frequency(int node, int core)
+static unsigned int nlm_xlp2_get_core_frequency(int node, int core)
+{
+	unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom;
+	uint64_t num, sysbase, clockbase;
+
+	if (cpu_is_xlp9xx()) {
+		clockbase = nlm_get_clock_regbase(node);
+		ctrl_val0 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_CPU_PLL_CTRL0(core));
+		ctrl_val1 = nlm_read_sys_reg(clockbase,
+					SYS_9XX_CPU_PLL_CTRL1(core));
+	} else {
+		sysbase = nlm_get_node(node)->sysbase;
+		ctrl_val0 = nlm_read_sys_reg(sysbase,
+						SYS_CPU_PLL_CTRL0(core));
+		ctrl_val1 = nlm_read_sys_reg(sysbase,
+						SYS_CPU_PLL_CTRL1(core));
+	}
+
+	/* Find PLL post divider value */
+	switch ((ctrl_val0 >> 24) & 0x7) {
+	case 1:
+		pll_post_div = 2;
+		break;
+	case 3:
+		pll_post_div = 4;
+		break;
+	case 7:
+		pll_post_div = 8;
+		break;
+	case 6:
+		pll_post_div = 16;
+		break;
+	case 0:
+	default:
+		pll_post_div = 1;
+		break;
+	}
+
+	num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f));
+	denom = 3 * pll_post_div;
+	do_div(num, denom);
+
+	return (unsigned int)num;
+}
+
+static unsigned int nlm_xlp_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
 	unsigned int rstval, dfsval, denom;
 	uint64_t num, sysbase;
 
 	sysbase = nlm_get_node(node)->sysbase;
-	if (cpu_is_xlp9xx())
-		rstval = nlm_read_sys_reg(sysbase, SYS_9XX_POWER_ON_RESET_CFG);
-	else
-		rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
-	if (cpu_is_xlpii()) {
-		num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26));
-		denom = 3;
-	} else {
-		dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
-		pll_divf = ((rstval >> 10) & 0x7f) + 1;
-		pll_divr = ((rstval >> 8)  & 0x3) + 1;
-		ext_div  = ((rstval >> 30) & 0x3) + 1;
-		dfs_div  = ((dfsval >> (core * 4)) & 0xf) + 1;
-
-		num = 800000000ULL * pll_divf;
-		denom = 3 * pll_divr * ext_div * dfs_div;
-	}
+	rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
+	dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
+	pll_divf = ((rstval >> 10) & 0x7f) + 1;
+	pll_divr = ((rstval >> 8)  & 0x3) + 1;
+	ext_div  = ((rstval >> 30) & 0x3) + 1;
+	dfs_div  = ((dfsval >> (core * 4)) & 0xf) + 1;
+
+	num = 800000000ULL * pll_divf;
+	denom = 3 * pll_divr * ext_div * dfs_div;
 	do_div(num, denom);
+
 	return (unsigned int)num;
 }
 
+unsigned int nlm_get_core_frequency(int node, int core)
+{
+	if (cpu_is_xlpii())
+		return nlm_xlp2_get_core_frequency(node, core);
+	else
+		return nlm_xlp_get_core_frequency(node, core);
+}
+
 /*
  * Calculate PIC frequency from PLL registers.
  * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
-- 
1.7.9.5

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

* [PATCH 14/17] MIPS: Netlogic: Add support for XLP5XX
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Yonghong Song, ralf, Jayachandran C

From: Yonghong Song <ysong@broadcom.com>

Add support for the XLP5XX processor which is an 8 core variant of the
XLP9XX. Add XLP5XX cases to code which earlier handled XLP9XX.

Signed-off-by: Yonghong Song <ysong@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/cpu.h                  |    1 +
 arch/mips/include/asm/netlogic/mips-extns.h  |    3 ++-
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h |    6 ++++--
 arch/mips/kernel/cpu-probe.c                 |    1 +
 arch/mips/netlogic/common/reset.S            |    4 ++++
 arch/mips/netlogic/xlp/dt.c                  |    1 +
 arch/mips/netlogic/xlp/setup.c               |    1 +
 arch/mips/netlogic/xlp/wakeup.c              |   10 +++++++++-
 8 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 530eb8b..fd18e86 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -201,6 +201,7 @@
 #define PRID_IMP_NETLOGIC_XLP3XX	0x1100
 #define PRID_IMP_NETLOGIC_XLP2XX	0x1200
 #define PRID_IMP_NETLOGIC_XLP9XX	0x1500
+#define PRID_IMP_NETLOGIC_XLP5XX	0x1300
 
 /*
  * Particular Revision values for bits 7:0 of the PRId register.
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index 38af905..06f1f75 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -148,7 +148,8 @@ static inline int nlm_nodeid(void)
 {
 	uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
 
-	if (prid == PRID_IMP_NETLOGIC_XLP9XX)
+	if ((prid == PRID_IMP_NETLOGIC_XLP9XX) ||
+			(prid == PRID_IMP_NETLOGIC_XLP5XX))
 		return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
 	else
 		return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index f75014c..8f8afe0 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -102,14 +102,16 @@ static inline int cpu_is_xlpii(void)
 	int chip = read_c0_prid() & PRID_IMP_MASK;
 
 	return chip == PRID_IMP_NETLOGIC_XLP2XX ||
-		chip == PRID_IMP_NETLOGIC_XLP9XX;
+		chip == PRID_IMP_NETLOGIC_XLP9XX ||
+		chip == PRID_IMP_NETLOGIC_XLP5XX;
 }
 
 static inline int cpu_is_xlp9xx(void)
 {
 	int chip = read_c0_prid() & PRID_IMP_MASK;
 
-	return chip == PRID_IMP_NETLOGIC_XLP9XX;
+	return chip == PRID_IMP_NETLOGIC_XLP9XX ||
+		chip == PRID_IMP_NETLOGIC_XLP5XX;
 }
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_NLM_XLP_H */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 6e8fb85..5114beb 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1074,6 +1074,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
 	switch (c->processor_id & PRID_IMP_MASK) {
 	case PRID_IMP_NETLOGIC_XLP2XX:
 	case PRID_IMP_NETLOGIC_XLP9XX:
+	case PRID_IMP_NETLOGIC_XLP5XX:
 		c->cputype = CPU_XLP;
 		__cpu_name[cpu] = "Broadcom XLPII";
 		break;
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index 5b60b46..701c4bc 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -177,6 +177,10 @@ FEXPORT(nlm_reset_entry)
 	beq	t0, t1, 2f		/* does not need to set coherent */
 	nop
 
+	li	t1, 0x1300		/* XLP 5xx */
+	beq	t0, t1, 2f		/* does not need to set coherent */
+	nop
+
 	/* set bit in SYS coherent register for the core */
 	mfc0	t0, CP0_EBASE, 1
 	mfc0	t1, CP0_EBASE, 1
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
index 0b36ac8..bba993a 100644
--- a/arch/mips/netlogic/xlp/dt.c
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -51,6 +51,7 @@ void __init *xlp_dt_init(void *fdtp)
 		switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
 #ifdef CONFIG_DT_XLP_GVP
 		case PRID_IMP_NETLOGIC_XLP9XX:
+		case PRID_IMP_NETLOGIC_XLP5XX:
 			fdtp = __dtb_xlp_gvp_begin;
 			break;
 #endif
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 3455e9f..135a38f 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -123,6 +123,7 @@ const char *get_system_type(void)
 {
 	switch (read_c0_prid() & PRID_IMP_MASK) {
 	case PRID_IMP_NETLOGIC_XLP9XX:
+	case PRID_IMP_NETLOGIC_XLP5XX:
 	case PRID_IMP_NETLOGIC_XLP2XX:
 		return "Broadcom XLPII Series";
 	default:
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index f4823ad..e5f44d2 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -135,7 +135,15 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
 		if (cpu_is_xlp9xx()) {
 			fusebase = nlm_get_fuse_regbase(n);
 			fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6);
-			mask = 0xfffff;
+			switch (read_c0_prid() & PRID_IMP_MASK) {
+			case PRID_IMP_NETLOGIC_XLP5XX:
+				mask = 0xff;
+				break;
+			case PRID_IMP_NETLOGIC_XLP9XX:
+			default:
+				mask = 0xfffff;
+				break;
+			}
 		} else {
 			fusemask = nlm_read_sys_reg(nodep->sysbase,
 						SYS_EFUSE_DEVICE_CFG_STATUS0);
-- 
1.7.9.5

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

* [PATCH 14/17] MIPS: Netlogic: Add support for XLP5XX
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Yonghong Song, ralf, Jayachandran C

From: Yonghong Song <ysong@broadcom.com>

Add support for the XLP5XX processor which is an 8 core variant of the
XLP9XX. Add XLP5XX cases to code which earlier handled XLP9XX.

Signed-off-by: Yonghong Song <ysong@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/cpu.h                  |    1 +
 arch/mips/include/asm/netlogic/mips-extns.h  |    3 ++-
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h |    6 ++++--
 arch/mips/kernel/cpu-probe.c                 |    1 +
 arch/mips/netlogic/common/reset.S            |    4 ++++
 arch/mips/netlogic/xlp/dt.c                  |    1 +
 arch/mips/netlogic/xlp/setup.c               |    1 +
 arch/mips/netlogic/xlp/wakeup.c              |   10 +++++++++-
 8 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 530eb8b..fd18e86 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -201,6 +201,7 @@
 #define PRID_IMP_NETLOGIC_XLP3XX	0x1100
 #define PRID_IMP_NETLOGIC_XLP2XX	0x1200
 #define PRID_IMP_NETLOGIC_XLP9XX	0x1500
+#define PRID_IMP_NETLOGIC_XLP5XX	0x1300
 
 /*
  * Particular Revision values for bits 7:0 of the PRId register.
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index 38af905..06f1f75 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -148,7 +148,8 @@ static inline int nlm_nodeid(void)
 {
 	uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
 
-	if (prid == PRID_IMP_NETLOGIC_XLP9XX)
+	if ((prid == PRID_IMP_NETLOGIC_XLP9XX) ||
+			(prid == PRID_IMP_NETLOGIC_XLP5XX))
 		return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
 	else
 		return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index f75014c..8f8afe0 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -102,14 +102,16 @@ static inline int cpu_is_xlpii(void)
 	int chip = read_c0_prid() & PRID_IMP_MASK;
 
 	return chip == PRID_IMP_NETLOGIC_XLP2XX ||
-		chip == PRID_IMP_NETLOGIC_XLP9XX;
+		chip == PRID_IMP_NETLOGIC_XLP9XX ||
+		chip == PRID_IMP_NETLOGIC_XLP5XX;
 }
 
 static inline int cpu_is_xlp9xx(void)
 {
 	int chip = read_c0_prid() & PRID_IMP_MASK;
 
-	return chip == PRID_IMP_NETLOGIC_XLP9XX;
+	return chip == PRID_IMP_NETLOGIC_XLP9XX ||
+		chip == PRID_IMP_NETLOGIC_XLP5XX;
 }
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_NLM_XLP_H */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 6e8fb85..5114beb 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1074,6 +1074,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
 	switch (c->processor_id & PRID_IMP_MASK) {
 	case PRID_IMP_NETLOGIC_XLP2XX:
 	case PRID_IMP_NETLOGIC_XLP9XX:
+	case PRID_IMP_NETLOGIC_XLP5XX:
 		c->cputype = CPU_XLP;
 		__cpu_name[cpu] = "Broadcom XLPII";
 		break;
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index 5b60b46..701c4bc 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -177,6 +177,10 @@ FEXPORT(nlm_reset_entry)
 	beq	t0, t1, 2f		/* does not need to set coherent */
 	nop
 
+	li	t1, 0x1300		/* XLP 5xx */
+	beq	t0, t1, 2f		/* does not need to set coherent */
+	nop
+
 	/* set bit in SYS coherent register for the core */
 	mfc0	t0, CP0_EBASE, 1
 	mfc0	t1, CP0_EBASE, 1
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
index 0b36ac8..bba993a 100644
--- a/arch/mips/netlogic/xlp/dt.c
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -51,6 +51,7 @@ void __init *xlp_dt_init(void *fdtp)
 		switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
 #ifdef CONFIG_DT_XLP_GVP
 		case PRID_IMP_NETLOGIC_XLP9XX:
+		case PRID_IMP_NETLOGIC_XLP5XX:
 			fdtp = __dtb_xlp_gvp_begin;
 			break;
 #endif
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 3455e9f..135a38f 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -123,6 +123,7 @@ const char *get_system_type(void)
 {
 	switch (read_c0_prid() & PRID_IMP_MASK) {
 	case PRID_IMP_NETLOGIC_XLP9XX:
+	case PRID_IMP_NETLOGIC_XLP5XX:
 	case PRID_IMP_NETLOGIC_XLP2XX:
 		return "Broadcom XLPII Series";
 	default:
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index f4823ad..e5f44d2 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -135,7 +135,15 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
 		if (cpu_is_xlp9xx()) {
 			fusebase = nlm_get_fuse_regbase(n);
 			fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6);
-			mask = 0xfffff;
+			switch (read_c0_prid() & PRID_IMP_MASK) {
+			case PRID_IMP_NETLOGIC_XLP5XX:
+				mask = 0xff;
+				break;
+			case PRID_IMP_NETLOGIC_XLP9XX:
+			default:
+				mask = 0xfffff;
+				break;
+			}
 		} else {
 			fusemask = nlm_read_sys_reg(nodep->sysbase,
 						SYS_EFUSE_DEVICE_CFG_STATUS0);
-- 
1.7.9.5

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

* [PATCH 15/17] MIPS: Add MSI support for XLP9XX
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

In XLP9XX, the interrupt routing table for MSI-X has been moved to the
PCIe controller's config space from PIC. There are also 32 MSI-X
interrupts available per link on XLP9XX.

Update XLP MSI/MSI-X code to handle this.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |   14 ++
 arch/mips/include/asm/netlogic/xlp-hal/pic.h    |    4 +
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h    |    5 +-
 arch/mips/pci/msi-xlp.c                         |  178 +++++++++++++++++------
 4 files changed, 151 insertions(+), 50 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index d4deb87..91540f4 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -69,6 +69,20 @@
 #define PCIE_9XX_BYTE_SWAP_IO_BASE	0x25e
 #define PCIE_9XX_BYTE_SWAP_IO_LIM	0x25f
 
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE	0x264
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT	0x265
+#define PCIE_9XX_MSI_STATUS		0x283
+#define PCIE_9XX_MSI_EN			0x284
+/* 128 MSIX vectors available in 9xx */
+#define PCIE_9XX_MSIX_STATUS0		0x286
+#define PCIE_9XX_MSIX_STATUSX(n)	(n + 0x286)
+#define PCIE_9XX_MSIX_VEC		0x296
+#define PCIE_9XX_MSIX_VECX(n)		(n + 0x296)
+#define PCIE_9XX_INT_STATUS0		0x397
+#define PCIE_9XX_INT_STATUS1		0x398
+#define PCIE_9XX_INT_EN0		0x399
+#define PCIE_9XX_INT_EN1		0x39a
+
 /* other */
 #define PCIE_NLINKS			4
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index f10bf3b..41cefe9 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -199,6 +199,10 @@
 #define PIC_IRT_PCIE_LINK_3_INDEX	81
 #define PIC_IRT_PCIE_LINK_INDEX(num)	((num) + PIC_IRT_PCIE_LINK_0_INDEX)
 
+#define PIC_9XX_IRT_PCIE_LINK_0_INDEX	191
+#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \
+				((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX)
+
 #define PIC_CLOCK_TIMER			7
 
 #if !defined(LOCORE) && !defined(__ASSEMBLY__)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 8f8afe0..c0b2a80 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -70,8 +70,9 @@
 #define PIC_PCIE_MSIX_IRQ_BASE		48	/* 48 - 51 MSI-X IRQ */
 #define PIC_PCIE_MSIX_IRQ(i)		(48 + (i))
 
-#define NLM_MSIX_VEC_BASE		96	/* 96 - 127 - MSIX mapped */
-#define NLM_MSI_VEC_BASE		128	/* 128 -255 - MSI mapped */
+/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */
+#define NLM_MSIX_VEC_BASE		96	/* 96 - 223 - MSIX mapped */
+#define NLM_MSI_VEC_BASE		224	/* 224 -351 - MSI mapped */
 
 #define NLM_PIC_INDIRECT_VEC_BASE	512
 #define NLM_GPIO_VEC_BASE		768
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index afd8405..d00be82 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -56,8 +56,8 @@
 #include <asm/netlogic/xlp-hal/bridge.h>
 
 #define XLP_MSIVEC_PER_LINK	32
-#define XLP_MSIXVEC_TOTAL	32
-#define XLP_MSIXVEC_PER_LINK	8
+#define XLP_MSIXVEC_TOTAL	(cpu_is_xlp9xx() ? 128 : 32)
+#define XLP_MSIXVEC_PER_LINK	(cpu_is_xlp9xx() ? 32 : 8)
 
 /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */
 static inline int nlm_link_msiirq(int link, int msivec)
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec)
 	return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msivec(int irq)
 {
-	return irq % XLP_MSIVEC_PER_LINK;
+	return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK;
 }
 
+/* get the link from the irq number */
 static inline int nlm_irq_msilink(int irq)
 {
-	return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) /
-						XLP_MSIVEC_PER_LINK;
+	int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS;
+
+	return ((irq - NLM_MSI_VEC_BASE) % total_msivec) /
+		XLP_MSIVEC_PER_LINK;
 }
 
 /*
- * Only 32 MSI-X vectors are possible because there are only 32 PIC
- * interrupts for MSI. We split them statically and use 8 MSI-X vectors
- * per link - this keeps the allocation and lookup simple.
+ * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because
+ * there are only 32 PIC interrupts for MSI. We split them statically
+ * and use 8 MSI-X vectors per link - this keeps the allocation and
+ * lookup simple.
+ * On XLP 9xx, there are 32 vectors per link, and the interrupts are
+ * not routed thru PIC, so we can use all 128 MSI-X vectors.
  */
 static inline int nlm_link_msixirq(int link, int bit)
 {
 	return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msixvec(int irq)
 {
-	return irq % XLP_MSIXVEC_TOTAL;  /* works when given xirq */
+	return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL;
 }
 
-static inline int nlm_irq_msixlink(int irq)
+/* get the link from MSIX vec */
+static inline int nlm_irq_msixlink(int msixvec)
 {
-	return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK;
+	return msixvec / XLP_MSIXVEC_PER_LINK;
 }
 
 /*
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask |= 1u << vec;
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask &= ~(1u << vec);
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d)
 	xlp_msi_disable(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
+	if (cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_9XX_IRT_PCIE_LINK_INDEX(link));
+	else
+		nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
 }
 
 static struct irq_chip xlp_msi_chip = {
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = {
 };
 
 /*
- * The MSI-X interrupt handling is different from MSI, there are 32
- * MSI-X interrupts generated by the PIC and each of these correspond
- * to a MSI-X vector (0-31) that can be assigned.
+ * XLP8XX/4XX/3XX/2XX:
+ * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X
+ * interrupts generated by the PIC and each of these correspond to a MSI-X
+ * vector (0-31) that can be assigned.
+ *
+ * We divide the MSI-X vectors to 8 per link and do a per-link allocation
  *
- * We divide the MSI-X vectors to 8 per link and do a per-link
- * allocation
+ * XLP9XX:
+ * 32 MSI-X vectors are available per link, and the interrupts are not routed
+ * thru the PIC. PIC ack not needed.
  *
  * Enable and disable done using standard MSI functions.
  */
 static void xlp_msix_mask_ack(struct irq_data *d)
 {
-	struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+	struct xlp_msi_data *md;
 	int link, msixvec;
+	uint32_t status_reg, bit;
 
 	msixvec = nlm_irq_msixvec(d->irq);
-	link = nlm_irq_msixlink(d->irq);
+	link = nlm_irq_msixlink(msixvec);
 	mask_msi_irq(d);
+	md = irq_data_get_irq_handler_data(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec);
+	if (cpu_is_xlp9xx()) {
+		status_reg = PCIE_9XX_MSIX_STATUSX(link);
+		bit = msixvec % XLP_MSIXVEC_PER_LINK;
+	} else {
+		status_reg = PCIE_MSIX_STATUS;
+		bit = msixvec;
+	}
+	nlm_write_reg(md->lnkbase, status_reg, 1u << bit);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec));
+	if (!cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_IRT_PCIE_MSIX_INDEX(msixvec));
 }
 
 static struct irq_chip xlp_msix_chip = {
@@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
 {
 	u32 val;
 
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
 
 	spin_lock_irqsave(&md->msi_lock, flags);
 	if (md->msi_alloc_mask == 0) {
-		/* switch the link IRQ to MSI range */
 		xlp_config_link_msi(lnkbase, lirq, msiaddr);
-		irt = PIC_IRT_PCIE_LINK_INDEX(link);
+		/* switch the link IRQ to MSI range */
+		if (cpu_is_xlp9xx())
+			irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
+		else
+			irt = PIC_IRT_PCIE_LINK_INDEX(link);
 		nlm_setup_pic_irq(node, lirq, lirq, irt);
 		nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
 				 node * nlm_threads_per_node(), 1 /*en */);
@@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 		val |= 0x80000000U;
 		nlm_write_reg(lnkbase, 0x2C, val);
 	}
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 	val |= (1 << 8) | lirq;
 	nlm_write_pci_reg(lnkbase, 0xf, val);
 
-	/* MSI-X addresses */
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8);
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
-					(msixaddr + MSI_ADDR_SZ) >> 8);
+	if (cpu_is_xlp9xx()) {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	} else {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	}
 }
 
 /*
@@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
 
 	xirq += t;
 	msixvec = nlm_irq_msixvec(xirq);
+
 	msg.address_hi = msixaddr >> 32;
 	msg.address_lo = msixaddr & 0xffffffff;
 	msg.data = 0xc00 | msixvec;
@@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 {
 	struct nlm_soc_info *nodep;
 	struct xlp_msi_data *md;
-	int irq, i, irt, msixvec;
+	int irq, i, irt, msixvec, val;
 
 	pr_info("[%d %d] Init node PCI IRT\n", node, link);
 	nodep = nlm_get_node(node);
@@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 		irq_set_handler_data(i, md);
 	}
 
-	for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) {
-		/* Initialize MSI-X irts to generate one interrupt per link */
-		msixvec = link * XLP_MSIXVEC_PER_LINK + i;
-		irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
-		nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link),
-			node * nlm_threads_per_node(), 1 /* enable */);
+	for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
+		if (cpu_is_xlp9xx()) {
+			val = ((node * nlm_threads_per_node()) << 7 |
+				PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
+			nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
+					(link * XLP_MSIXVEC_PER_LINK)), val);
+		} else {
+			/* Initialize MSI-X irts to generate one interrupt
+			 * per link
+			 */
+			msixvec = link * XLP_MSIXVEC_PER_LINK + i;
+			irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
+			nlm_pic_init_irt(nodep->picbase, irt,
+					PIC_PCIE_MSIX_IRQ(link),
+					node * nlm_threads_per_node(), 1);
+		}
 
 		/* Initialize MSI-X extended irq space for the link  */
 		irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
 		irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
 		irq_set_handler_data(irq, md);
 	}
-
 }
 
 void nlm_dispatch_msi(int node, int lirq)
@@ -480,10 +558,14 @@ void nlm_dispatch_msix(int node, int lirq)
 	link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
 	irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
 	md = irq_get_handler_data(irqbase);
-	status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
+	if (cpu_is_xlp9xx())
+		status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
+	else
+		status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
 
 	/* narrow it down to the MSI-x vectors for our link */
-	status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
+	if (!cpu_is_xlp9xx())
+		status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
 			((1 << XLP_MSIXVEC_PER_LINK) - 1);
 
 	while (status) {
-- 
1.7.9.5

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

* [PATCH 15/17] MIPS: Add MSI support for XLP9XX
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

In XLP9XX, the interrupt routing table for MSI-X has been moved to the
PCIe controller's config space from PIC. There are also 32 MSI-X
interrupts available per link on XLP9XX.

Update XLP MSI/MSI-X code to handle this.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |   14 ++
 arch/mips/include/asm/netlogic/xlp-hal/pic.h    |    4 +
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h    |    5 +-
 arch/mips/pci/msi-xlp.c                         |  178 +++++++++++++++++------
 4 files changed, 151 insertions(+), 50 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index d4deb87..91540f4 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -69,6 +69,20 @@
 #define PCIE_9XX_BYTE_SWAP_IO_BASE	0x25e
 #define PCIE_9XX_BYTE_SWAP_IO_LIM	0x25f
 
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE	0x264
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT	0x265
+#define PCIE_9XX_MSI_STATUS		0x283
+#define PCIE_9XX_MSI_EN			0x284
+/* 128 MSIX vectors available in 9xx */
+#define PCIE_9XX_MSIX_STATUS0		0x286
+#define PCIE_9XX_MSIX_STATUSX(n)	(n + 0x286)
+#define PCIE_9XX_MSIX_VEC		0x296
+#define PCIE_9XX_MSIX_VECX(n)		(n + 0x296)
+#define PCIE_9XX_INT_STATUS0		0x397
+#define PCIE_9XX_INT_STATUS1		0x398
+#define PCIE_9XX_INT_EN0		0x399
+#define PCIE_9XX_INT_EN1		0x39a
+
 /* other */
 #define PCIE_NLINKS			4
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index f10bf3b..41cefe9 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -199,6 +199,10 @@
 #define PIC_IRT_PCIE_LINK_3_INDEX	81
 #define PIC_IRT_PCIE_LINK_INDEX(num)	((num) + PIC_IRT_PCIE_LINK_0_INDEX)
 
+#define PIC_9XX_IRT_PCIE_LINK_0_INDEX	191
+#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \
+				((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX)
+
 #define PIC_CLOCK_TIMER			7
 
 #if !defined(LOCORE) && !defined(__ASSEMBLY__)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 8f8afe0..c0b2a80 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -70,8 +70,9 @@
 #define PIC_PCIE_MSIX_IRQ_BASE		48	/* 48 - 51 MSI-X IRQ */
 #define PIC_PCIE_MSIX_IRQ(i)		(48 + (i))
 
-#define NLM_MSIX_VEC_BASE		96	/* 96 - 127 - MSIX mapped */
-#define NLM_MSI_VEC_BASE		128	/* 128 -255 - MSI mapped */
+/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */
+#define NLM_MSIX_VEC_BASE		96	/* 96 - 223 - MSIX mapped */
+#define NLM_MSI_VEC_BASE		224	/* 224 -351 - MSI mapped */
 
 #define NLM_PIC_INDIRECT_VEC_BASE	512
 #define NLM_GPIO_VEC_BASE		768
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index afd8405..d00be82 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -56,8 +56,8 @@
 #include <asm/netlogic/xlp-hal/bridge.h>
 
 #define XLP_MSIVEC_PER_LINK	32
-#define XLP_MSIXVEC_TOTAL	32
-#define XLP_MSIXVEC_PER_LINK	8
+#define XLP_MSIXVEC_TOTAL	(cpu_is_xlp9xx() ? 128 : 32)
+#define XLP_MSIXVEC_PER_LINK	(cpu_is_xlp9xx() ? 32 : 8)
 
 /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */
 static inline int nlm_link_msiirq(int link, int msivec)
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec)
 	return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msivec(int irq)
 {
-	return irq % XLP_MSIVEC_PER_LINK;
+	return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK;
 }
 
+/* get the link from the irq number */
 static inline int nlm_irq_msilink(int irq)
 {
-	return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) /
-						XLP_MSIVEC_PER_LINK;
+	int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS;
+
+	return ((irq - NLM_MSI_VEC_BASE) % total_msivec) /
+		XLP_MSIVEC_PER_LINK;
 }
 
 /*
- * Only 32 MSI-X vectors are possible because there are only 32 PIC
- * interrupts for MSI. We split them statically and use 8 MSI-X vectors
- * per link - this keeps the allocation and lookup simple.
+ * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because
+ * there are only 32 PIC interrupts for MSI. We split them statically
+ * and use 8 MSI-X vectors per link - this keeps the allocation and
+ * lookup simple.
+ * On XLP 9xx, there are 32 vectors per link, and the interrupts are
+ * not routed thru PIC, so we can use all 128 MSI-X vectors.
  */
 static inline int nlm_link_msixirq(int link, int bit)
 {
 	return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msixvec(int irq)
 {
-	return irq % XLP_MSIXVEC_TOTAL;  /* works when given xirq */
+	return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL;
 }
 
-static inline int nlm_irq_msixlink(int irq)
+/* get the link from MSIX vec */
+static inline int nlm_irq_msixlink(int msixvec)
 {
-	return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK;
+	return msixvec / XLP_MSIXVEC_PER_LINK;
 }
 
 /*
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask |= 1u << vec;
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask &= ~(1u << vec);
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d)
 	xlp_msi_disable(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
+	if (cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_9XX_IRT_PCIE_LINK_INDEX(link));
+	else
+		nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
 }
 
 static struct irq_chip xlp_msi_chip = {
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = {
 };
 
 /*
- * The MSI-X interrupt handling is different from MSI, there are 32
- * MSI-X interrupts generated by the PIC and each of these correspond
- * to a MSI-X vector (0-31) that can be assigned.
+ * XLP8XX/4XX/3XX/2XX:
+ * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X
+ * interrupts generated by the PIC and each of these correspond to a MSI-X
+ * vector (0-31) that can be assigned.
+ *
+ * We divide the MSI-X vectors to 8 per link and do a per-link allocation
  *
- * We divide the MSI-X vectors to 8 per link and do a per-link
- * allocation
+ * XLP9XX:
+ * 32 MSI-X vectors are available per link, and the interrupts are not routed
+ * thru the PIC. PIC ack not needed.
  *
  * Enable and disable done using standard MSI functions.
  */
 static void xlp_msix_mask_ack(struct irq_data *d)
 {
-	struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+	struct xlp_msi_data *md;
 	int link, msixvec;
+	uint32_t status_reg, bit;
 
 	msixvec = nlm_irq_msixvec(d->irq);
-	link = nlm_irq_msixlink(d->irq);
+	link = nlm_irq_msixlink(msixvec);
 	mask_msi_irq(d);
+	md = irq_data_get_irq_handler_data(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec);
+	if (cpu_is_xlp9xx()) {
+		status_reg = PCIE_9XX_MSIX_STATUSX(link);
+		bit = msixvec % XLP_MSIXVEC_PER_LINK;
+	} else {
+		status_reg = PCIE_MSIX_STATUS;
+		bit = msixvec;
+	}
+	nlm_write_reg(md->lnkbase, status_reg, 1u << bit);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec));
+	if (!cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_IRT_PCIE_MSIX_INDEX(msixvec));
 }
 
 static struct irq_chip xlp_msix_chip = {
@@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
 {
 	u32 val;
 
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
 
 	spin_lock_irqsave(&md->msi_lock, flags);
 	if (md->msi_alloc_mask == 0) {
-		/* switch the link IRQ to MSI range */
 		xlp_config_link_msi(lnkbase, lirq, msiaddr);
-		irt = PIC_IRT_PCIE_LINK_INDEX(link);
+		/* switch the link IRQ to MSI range */
+		if (cpu_is_xlp9xx())
+			irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
+		else
+			irt = PIC_IRT_PCIE_LINK_INDEX(link);
 		nlm_setup_pic_irq(node, lirq, lirq, irt);
 		nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
 				 node * nlm_threads_per_node(), 1 /*en */);
@@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 		val |= 0x80000000U;
 		nlm_write_reg(lnkbase, 0x2C, val);
 	}
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 	val |= (1 << 8) | lirq;
 	nlm_write_pci_reg(lnkbase, 0xf, val);
 
-	/* MSI-X addresses */
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8);
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
-					(msixaddr + MSI_ADDR_SZ) >> 8);
+	if (cpu_is_xlp9xx()) {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	} else {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	}
 }
 
 /*
@@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
 
 	xirq += t;
 	msixvec = nlm_irq_msixvec(xirq);
+
 	msg.address_hi = msixaddr >> 32;
 	msg.address_lo = msixaddr & 0xffffffff;
 	msg.data = 0xc00 | msixvec;
@@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 {
 	struct nlm_soc_info *nodep;
 	struct xlp_msi_data *md;
-	int irq, i, irt, msixvec;
+	int irq, i, irt, msixvec, val;
 
 	pr_info("[%d %d] Init node PCI IRT\n", node, link);
 	nodep = nlm_get_node(node);
@@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 		irq_set_handler_data(i, md);
 	}
 
-	for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) {
-		/* Initialize MSI-X irts to generate one interrupt per link */
-		msixvec = link * XLP_MSIXVEC_PER_LINK + i;
-		irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
-		nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link),
-			node * nlm_threads_per_node(), 1 /* enable */);
+	for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
+		if (cpu_is_xlp9xx()) {
+			val = ((node * nlm_threads_per_node()) << 7 |
+				PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
+			nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
+					(link * XLP_MSIXVEC_PER_LINK)), val);
+		} else {
+			/* Initialize MSI-X irts to generate one interrupt
+			 * per link
+			 */
+			msixvec = link * XLP_MSIXVEC_PER_LINK + i;
+			irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
+			nlm_pic_init_irt(nodep->picbase, irt,
+					PIC_PCIE_MSIX_IRQ(link),
+					node * nlm_threads_per_node(), 1);
+		}
 
 		/* Initialize MSI-X extended irq space for the link  */
 		irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
 		irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
 		irq_set_handler_data(irq, md);
 	}
-
 }
 
 void nlm_dispatch_msi(int node, int lirq)
@@ -480,10 +558,14 @@ void nlm_dispatch_msix(int node, int lirq)
 	link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
 	irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
 	md = irq_get_handler_data(irqbase);
-	status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
+	if (cpu_is_xlp9xx())
+		status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
+	else
+		status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
 
 	/* narrow it down to the MSI-x vectors for our link */
-	status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
+	if (!cpu_is_xlp9xx())
+		status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
 			((1 << XLP_MSIXVEC_PER_LINK) - 1);
 
 	while (status) {
-- 
1.7.9.5

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

* [PATCH 16/17] MIPS: Netlogic: Support for XLP3XX on-chip SATA
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

XLP3XX includes an on-chip SATA controller with 4 ports. The
controller needs glue logic initialization and PCI fixup before
it can be used with the standard AHCI driver.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/xlp/Makefile    |    1 +
 arch/mips/netlogic/xlp/ahci-init.c |  209 ++++++++++++++++++++++++++++++++++++
 2 files changed, 210 insertions(+)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init.c

diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index ed9a93c..0cb53af 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -2,3 +2,4 @@ obj-y				+= setup.o nlm_hal.o cop2-ex.o dt.o
 obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
 obj-$(CONFIG_USB)		+= usb-init-xlp2.o
+obj-$(CONFIG_SATA_AHCI)		+= ahci-init.o
diff --git a/arch/mips/netlogic/xlp/ahci-init.c b/arch/mips/netlogic/xlp/ahci-init.c
new file mode 100644
index 0000000..a9d0fae
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+#include <asm/netlogic/mips-extns.h>
+
+#define SATA_CTL		0x0
+#define SATA_STATUS		0x1	/* Status Reg */
+#define SATA_INT		0x2	/* Interrupt Reg */
+#define SATA_INT_MASK		0x3	/* Interrupt Mask Reg */
+#define SATA_CR_REG_TIMER	0x4	/* PHY Conrol Timer Reg */
+#define SATA_CORE_ID		0x5	/* Core ID Reg */
+#define SATA_AXI_SLAVE_OPT1	0x6	/* AXI Slave Options Reg */
+#define SATA_PHY_LOS_LEV	0x7	/* PHY LOS Level Reg */
+#define SATA_PHY_MULTI		0x8	/* PHY Multiplier Reg */
+#define SATA_PHY_CLK_SEL	0x9	/* Clock Select Reg */
+#define SATA_PHY_AMP1_GEN1	0xa	/* PHY Transmit Amplitude Reg 1 */
+#define SATA_PHY_AMP1_GEN2	0xb	/* PHY Transmit Amplitude Reg 2 */
+#define SATA_PHY_AMP1_GEN3	0xc	/* PHY Transmit Amplitude Reg 3 */
+#define SATA_PHY_PRE1		0xd	/* PHY Transmit Preemphasis Reg 1 */
+#define SATA_PHY_PRE2		0xe	/* PHY Transmit Preemphasis Reg 2 */
+#define SATA_PHY_PRE3		0xf	/* PHY Transmit Preemphasis Reg 3 */
+#define SATA_SPDMODE		0x10	/* Speed Mode Reg */
+#define SATA_REFCLK		0x11	/* Reference Clock Control Reg */
+#define SATA_BYTE_SWAP_DIS	0x12	/* byte swap disable */
+
+/*SATA_CTL Bits */
+#define SATA_RST_N		BIT(0)
+#define PHY0_RESET_N		BIT(16)
+#define PHY1_RESET_N		BIT(17)
+#define PHY2_RESET_N		BIT(18)
+#define PHY3_RESET_N		BIT(19)
+#define M_CSYSREQ		BIT(2)
+#define S_CSYSREQ		BIT(3)
+
+/*SATA_STATUS Bits */
+#define P0_PHY_READY		BIT(4)
+#define P1_PHY_READY		BIT(5)
+#define P2_PHY_READY		BIT(6)
+#define P3_PHY_READY		BIT(7)
+
+#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node)	\
+		nlm_pcicfg_base(XLP_IO_SATA_OFFSET(node))
+/* SATA device specific configuration registers are starts at 0x900 offset */
+#define nlm_get_sata_regbase(node)	\
+		(nlm_get_sata_pcibase(node) + 0x900)
+
+static void sata_clear_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
+{
+	uint32_t reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
+{
+	uint32_t reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void nlm_sata_firmware_init(int node)
+{
+	uint32_t reg_val;
+	uint64_t regbase;
+	int i;
+
+	pr_info("XLP AHCI Initialization started.\n");
+	regbase = nlm_get_sata_regbase(node);
+
+	/* Reset SATA */
+	sata_clear_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	/* Reset PHY */
+	sata_clear_glue_reg(regbase, SATA_CTL,
+			(PHY3_RESET_N | PHY2_RESET_N
+			 | PHY1_RESET_N | PHY0_RESET_N));
+
+	/* Set SATA */
+	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	/* Set PHY */
+	sata_set_glue_reg(regbase, SATA_CTL,
+			(PHY3_RESET_N | PHY2_RESET_N
+			 | PHY1_RESET_N | PHY0_RESET_N));
+
+	pr_debug("Waiting for PHYs to come up.\n");
+	i = 0;
+	do {
+		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+		i++;
+	} while (((reg_val & 0xF0) != 0xF0) && (i < 10000));
+
+	for (i = 0; i < 4; i++) {
+		if (reg_val  & (P0_PHY_READY << i))
+			pr_info("PHY%d is up.\n", i);
+		else
+			pr_info("PHY%d is down.\n", i);
+	}
+
+	pr_info("XLP AHCI init done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+	int node = 0;
+	int chip = read_c0_prid() & PRID_REV_MASK;
+
+	if (chip == PRID_IMP_NETLOGIC_XLP3XX)
+		nlm_sata_firmware_init(node);
+	return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+	uint32_t val = 0;
+	uint64_t regbase;
+
+	regbase = nlm_get_sata_regbase(nlm_nodeid());
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+	/*
+	 * The AHCI resource is in BAR 0, move it to
+	 * BAR 5, where it is expected
+	 */
+	dev->resource[5] = dev->resource[0];
+	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+	uint32_t val;
+	uint64_t regbase;
+	int node = 0; /* XLP3XX does not support multi-node */
+
+	regbase = nlm_get_sata_regbase(node);
+
+	/* clear pending interrupts and then enable them */
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+
+	/* Mask the core interrupt. If all the interrupts
+	 * are enabled there are spurious interrupt flow
+	 * happening, to avoid only enable core interrupt
+	 * mask.
+	 */
+	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+	dev->irq = PIC_SATA_IRQ;
+	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
+		nlm_sata_fixup_bar);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
+		nlm_sata_fixup_final);
-- 
1.7.9.5

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

* [PATCH 16/17] MIPS: Netlogic: Support for XLP3XX on-chip SATA
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

XLP3XX includes an on-chip SATA controller with 4 ports. The
controller needs glue logic initialization and PCI fixup before
it can be used with the standard AHCI driver.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/xlp/Makefile    |    1 +
 arch/mips/netlogic/xlp/ahci-init.c |  209 ++++++++++++++++++++++++++++++++++++
 2 files changed, 210 insertions(+)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init.c

diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index ed9a93c..0cb53af 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -2,3 +2,4 @@ obj-y				+= setup.o nlm_hal.o cop2-ex.o dt.o
 obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
 obj-$(CONFIG_USB)		+= usb-init-xlp2.o
+obj-$(CONFIG_SATA_AHCI)		+= ahci-init.o
diff --git a/arch/mips/netlogic/xlp/ahci-init.c b/arch/mips/netlogic/xlp/ahci-init.c
new file mode 100644
index 0000000..a9d0fae
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+#include <asm/netlogic/mips-extns.h>
+
+#define SATA_CTL		0x0
+#define SATA_STATUS		0x1	/* Status Reg */
+#define SATA_INT		0x2	/* Interrupt Reg */
+#define SATA_INT_MASK		0x3	/* Interrupt Mask Reg */
+#define SATA_CR_REG_TIMER	0x4	/* PHY Conrol Timer Reg */
+#define SATA_CORE_ID		0x5	/* Core ID Reg */
+#define SATA_AXI_SLAVE_OPT1	0x6	/* AXI Slave Options Reg */
+#define SATA_PHY_LOS_LEV	0x7	/* PHY LOS Level Reg */
+#define SATA_PHY_MULTI		0x8	/* PHY Multiplier Reg */
+#define SATA_PHY_CLK_SEL	0x9	/* Clock Select Reg */
+#define SATA_PHY_AMP1_GEN1	0xa	/* PHY Transmit Amplitude Reg 1 */
+#define SATA_PHY_AMP1_GEN2	0xb	/* PHY Transmit Amplitude Reg 2 */
+#define SATA_PHY_AMP1_GEN3	0xc	/* PHY Transmit Amplitude Reg 3 */
+#define SATA_PHY_PRE1		0xd	/* PHY Transmit Preemphasis Reg 1 */
+#define SATA_PHY_PRE2		0xe	/* PHY Transmit Preemphasis Reg 2 */
+#define SATA_PHY_PRE3		0xf	/* PHY Transmit Preemphasis Reg 3 */
+#define SATA_SPDMODE		0x10	/* Speed Mode Reg */
+#define SATA_REFCLK		0x11	/* Reference Clock Control Reg */
+#define SATA_BYTE_SWAP_DIS	0x12	/* byte swap disable */
+
+/*SATA_CTL Bits */
+#define SATA_RST_N		BIT(0)
+#define PHY0_RESET_N		BIT(16)
+#define PHY1_RESET_N		BIT(17)
+#define PHY2_RESET_N		BIT(18)
+#define PHY3_RESET_N		BIT(19)
+#define M_CSYSREQ		BIT(2)
+#define S_CSYSREQ		BIT(3)
+
+/*SATA_STATUS Bits */
+#define P0_PHY_READY		BIT(4)
+#define P1_PHY_READY		BIT(5)
+#define P2_PHY_READY		BIT(6)
+#define P3_PHY_READY		BIT(7)
+
+#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node)	\
+		nlm_pcicfg_base(XLP_IO_SATA_OFFSET(node))
+/* SATA device specific configuration registers are starts at 0x900 offset */
+#define nlm_get_sata_regbase(node)	\
+		(nlm_get_sata_pcibase(node) + 0x900)
+
+static void sata_clear_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
+{
+	uint32_t reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
+{
+	uint32_t reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void nlm_sata_firmware_init(int node)
+{
+	uint32_t reg_val;
+	uint64_t regbase;
+	int i;
+
+	pr_info("XLP AHCI Initialization started.\n");
+	regbase = nlm_get_sata_regbase(node);
+
+	/* Reset SATA */
+	sata_clear_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	/* Reset PHY */
+	sata_clear_glue_reg(regbase, SATA_CTL,
+			(PHY3_RESET_N | PHY2_RESET_N
+			 | PHY1_RESET_N | PHY0_RESET_N));
+
+	/* Set SATA */
+	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	/* Set PHY */
+	sata_set_glue_reg(regbase, SATA_CTL,
+			(PHY3_RESET_N | PHY2_RESET_N
+			 | PHY1_RESET_N | PHY0_RESET_N));
+
+	pr_debug("Waiting for PHYs to come up.\n");
+	i = 0;
+	do {
+		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+		i++;
+	} while (((reg_val & 0xF0) != 0xF0) && (i < 10000));
+
+	for (i = 0; i < 4; i++) {
+		if (reg_val  & (P0_PHY_READY << i))
+			pr_info("PHY%d is up.\n", i);
+		else
+			pr_info("PHY%d is down.\n", i);
+	}
+
+	pr_info("XLP AHCI init done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+	int node = 0;
+	int chip = read_c0_prid() & PRID_REV_MASK;
+
+	if (chip == PRID_IMP_NETLOGIC_XLP3XX)
+		nlm_sata_firmware_init(node);
+	return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+	uint32_t val = 0;
+	uint64_t regbase;
+
+	regbase = nlm_get_sata_regbase(nlm_nodeid());
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+	/*
+	 * The AHCI resource is in BAR 0, move it to
+	 * BAR 5, where it is expected
+	 */
+	dev->resource[5] = dev->resource[0];
+	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+	uint32_t val;
+	uint64_t regbase;
+	int node = 0; /* XLP3XX does not support multi-node */
+
+	regbase = nlm_get_sata_regbase(node);
+
+	/* clear pending interrupts and then enable them */
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+
+	/* Mask the core interrupt. If all the interrupts
+	 * are enabled there are spurious interrupt flow
+	 * happening, to avoid only enable core interrupt
+	 * mask.
+	 */
+	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+	dev->irq = PIC_SATA_IRQ;
+	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
+		nlm_sata_fixup_bar);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
+		nlm_sata_fixup_final);
-- 
1.7.9.5

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

* [PATCH 17/17] MIPS: Netlogic: XLP9XX on-chip SATA support
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

The XLP9XX SoC has an on-chip SATA controller with two ports. Add
ahci-init-xlp2.c to initialize the controller, setup the glue logic
registers, fixup PCI quirks and setup interrupt ack logic.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/xlp/Makefile         |    1 +
 arch/mips/netlogic/xlp/ahci-init-xlp2.c |  378 +++++++++++++++++++++++++++++++
 2 files changed, 379 insertions(+)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init-xlp2.c

diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index 0cb53af..be358a8 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
 obj-$(CONFIG_USB)		+= usb-init-xlp2.o
 obj-$(CONFIG_SATA_AHCI)		+= ahci-init.o
+obj-$(CONFIG_SATA_AHCI)		+= ahci-init-xlp2.o
diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
new file mode 100644
index 0000000..a55e111
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/nodemask.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/mips-extns.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+
+#define SATA_CTL		0x0
+#define SATA_STATUS		0x1 /* Status Reg */
+#define SATA_INT		0x2 /* Interrupt Reg */
+#define SATA_INT_MASK		0x3 /* Interrupt Mask Reg */
+#define SATA_BIU_TIMEOUT	0x4
+#define AXIWRSPERRLOG		0x5
+#define AXIRDSPERRLOG		0x6
+#define BiuTimeoutLow		0x7
+#define BiuTimeoutHi		0x8
+#define BiuSlvErLow		0x9
+#define BiuSlvErHi		0xa
+#define IO_CONFIG_SWAP_DIS	0xb
+#define CR_REG_TIMER		0xc
+#define CORE_ID			0xd
+#define AXI_SLAVE_OPT1		0xe
+#define PHY_MEM_ACCESS		0xf
+#define PHY0_CNTRL		0x10
+#define PHY0_STAT		0x11
+#define PHY0_RX_ALIGN		0x12
+#define PHY0_RX_EQ_LO		0x13
+#define PHY0_RX_EQ_HI		0x14
+#define PHY0_BIST_LOOP		0x15
+#define PHY1_CNTRL		0x16
+#define PHY1_STAT		0x17
+#define PHY1_RX_ALIGN		0x18
+#define PHY1_RX_EQ_LO		0x19
+#define PHY1_RX_EQ_HI		0x1a
+#define PHY1_BIST_LOOP		0x1b
+#define RdExBase		0x1c
+#define RdExLimit		0x1d
+#define CacheAllocBase		0x1e
+#define CacheAllocLimit		0x1f
+#define BiuSlaveCmdGstNum	0x20
+
+/*SATA_CTL Bits */
+#define SATA_RST_N		BIT(0)  /* Active low reset sata_core phy */
+#define SataCtlReserve0		BIT(1)
+#define M_CSYSREQ		BIT(2)  /* AXI master low power, not used */
+#define S_CSYSREQ		BIT(3)  /* AXI slave low power, not used */
+#define P0_CP_DET		BIT(8)  /* Reserved, bring in from pad */
+#define P0_MP_SW		BIT(9)  /* Mech Switch */
+#define P0_DISABLE		BIT(10) /* disable p0 */
+#define P0_ACT_LED_EN		BIT(11) /* Active LED enable */
+#define P0_IRST_HARD_SYNTH	BIT(12) /* PHY hard synth reset */
+#define P0_IRST_HARD_TXRX	BIT(13) /* PHY lane hard reset */
+#define P0_IRST_POR		BIT(14) /* PHY power on reset*/
+#define P0_IPDTXL		BIT(15) /* PHY Tx lane dis/power down */
+#define P0_IPDRXL		BIT(16) /* PHY Rx lane dis/power down */
+#define P0_IPDIPDMSYNTH		BIT(17) /* PHY synthesizer dis/porwer down */
+#define P0_CP_POD_EN		BIT(18) /* CP_POD enable */
+#define P0_AT_BYPASS		BIT(19) /* P0 address translation by pass */
+#define P1_CP_DET		BIT(20) /* Reserved,Cold Detect */
+#define P1_MP_SW		BIT(21) /* Mech Switch */
+#define P1_DISABLE		BIT(22) /* disable p1 */
+#define P1_ACT_LED_EN		BIT(23) /* Active LED enable */
+#define P1_IRST_HARD_SYNTH	BIT(24) /* PHY hard synth reset */
+#define P1_IRST_HARD_TXRX	BIT(25) /* PHY lane hard reset */
+#define P1_IRST_POR		BIT(26) /* PHY power on reset*/
+#define P1_IPDTXL		BIT(27) /* PHY Tx lane dis/porwer down */
+#define P1_IPDRXL		BIT(28) /* PHY Rx lane dis/porwer down */
+#define P1_IPDIPDMSYNTH		BIT(29) /* PHY synthesizer dis/porwer down */
+#define P1_CP_POD_EN		BIT(30)
+#define P1_AT_BYPASS		BIT(31) /* P1 address translation by pass */
+
+/* Status register */
+#define M_CACTIVE		BIT(0)  /* m_cactive, not used */
+#define S_CACTIVE		BIT(1)  /* s_cactive, not used */
+#define P0_PHY_READY		BIT(8)  /* phy is ready */
+#define P0_CP_POD		BIT(9)  /* Cold PowerOn */
+#define P0_SLUMBER		BIT(10) /* power mode slumber */
+#define P0_PATIAL		BIT(11) /* power mode patial */
+#define P0_PHY_SIG_DET		BIT(12) /* phy dignal detect */
+#define P0_PHY_CALI		BIT(13) /* phy calibration done */
+#define P1_PHY_READY		BIT(16) /* phy is ready */
+#define P1_CP_POD		BIT(17) /* Cold PowerOn */
+#define P1_SLUMBER		BIT(18) /* power mode slumber */
+#define P1_PATIAL		BIT(19) /* power mode patial */
+#define P1_PHY_SIG_DET		BIT(20) /* phy dignal detect */
+#define P1_PHY_CALI		BIT(21) /* phy calibration done */
+
+/* SATA CR_REG_TIMER bits */
+#define CR_TIME_SCALE		(0x1000 << 0)
+
+/* SATA PHY specific registers start and end address */
+#define RXCDRCALFOSC0		0x0065
+#define CALDUTY			0x006e
+#define RXDPIF			0x8065
+#define PPMDRIFTMAX_HI		0x80A4
+
+#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node)	\
+		nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
+#define nlm_get_sata_regbase(node)	\
+		(nlm_get_sata_pcibase(node) + 0x100)
+
+/* SATA PHY config for register block 1 0x0065 .. 0x006e */
+static const u8 sata_phy_config1[]  = {
+	0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
+};
+
+/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
+static const u8 sata_phy_config2[]  = {
+	0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
+	0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
+	0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
+	0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
+	0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
+	0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
+	0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
+};
+
+static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
+{
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(1u << 31) | (physel << 24) | (data << 16) | addr);
+	udelay(850);
+}
+
+static void config_sata_phy(u64 regbase, u32 node)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
+	}
+}
+
+#if 0	/* DEBUG */
+static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
+{
+	u32 val;
+
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(0 << 31) | (physel << 24) | (data << 16) | addr);
+	udelay(850);
+	val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
+	return (val >> 16) & 0xff;
+}
+
+static void check_phy_register(u63 regbase, u32 addr, u32 physel, u8 xdata)
+{
+	u64 regbase;
+	u8 data;
+
+	data = read_phy_reg(regbase, addr, physel);
+	pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
+		addr, physel, data, data == xdata ? "TRUE" : "FALSE");
+}
+
+static void verify_sata_phy_config(u64 regbase, u32 node)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			check_phy_register(regbase, node, reg, port,
+					sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			check_phy_register(regbase, node, reg, port,
+					sata_phy_config2[i]);
+	}
+}
+#endif
+
+static void nlm_sata_firmware_init(int node)
+{
+	u32 reg_val;
+	u64 regbase;
+	int n;
+
+	pr_info("Initializing XLP9XX On-chip AHCI...\n");
+	regbase = nlm_get_sata_regbase(node);
+
+	/* Reset port0 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+
+	/* port1 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+	udelay(300);
+
+	/* Set PHY */
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	udelay(1000);
+
+	/* setup PHY */
+	config_sata_phy(regbase, node);
+#if 0	/* For debug */
+	verify_sata_phy_config(regbase, node);
+#endif
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	udelay(300);
+
+	/* Override reset in serial PHY mode */
+	sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
+	/* Set reset SATA */
+	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
+	sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
+
+	pr_debug("Waiting for PHYs to come up.\n");
+	n = 10000;
+	do {
+		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+		if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
+			break;
+		udelay(10);
+	} while (--n > 0);
+
+	if (reg_val  & P0_PHY_READY)
+		pr_info("PHY0 is up.\n");
+	else
+		pr_info("PHY0 is down.\n");
+	if (reg_val  & P1_PHY_READY)
+		pr_info("PHY1 is up.\n");
+	else
+		pr_info("PHY1 is down.\n");
+
+	pr_info("XLP AHCI Init Done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+	int node;
+
+	if (!cpu_is_xlp9xx())
+		return 0;
+	for (node = 0; node < NLM_NR_NODES; node++)
+		if (nlm_node_present(node))
+			nlm_sata_firmware_init(node);
+	return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+	u64 regbase;
+	u32 val;
+	int node;
+
+	node = data->irq / NLM_IRQS_PER_NODE;
+	regbase = nlm_get_sata_regbase(node);
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+	dev->resource[5] = dev->resource[0];
+	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+	u32 val;
+	u64 regbase;
+	int node;
+
+	/* Find end bridge function to find node */
+	node = xlp_socdev_to_node(dev);
+	regbase = nlm_get_sata_regbase(node);
+
+	/* clear pending interrupts and then enable them */
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+
+	/* Enable only the core interrupt */
+	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+	dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
+	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_bar);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_final);
-- 
1.7.9.5

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

* [PATCH 17/17] MIPS: Netlogic: XLP9XX on-chip SATA support
@ 2014-04-29 14:37   ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-04-29 14:37 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

The XLP9XX SoC has an on-chip SATA controller with two ports. Add
ahci-init-xlp2.c to initialize the controller, setup the glue logic
registers, fixup PCI quirks and setup interrupt ack logic.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 arch/mips/netlogic/xlp/Makefile         |    1 +
 arch/mips/netlogic/xlp/ahci-init-xlp2.c |  378 +++++++++++++++++++++++++++++++
 2 files changed, 379 insertions(+)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init-xlp2.c

diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index 0cb53af..be358a8 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
 obj-$(CONFIG_USB)		+= usb-init-xlp2.o
 obj-$(CONFIG_SATA_AHCI)		+= ahci-init.o
+obj-$(CONFIG_SATA_AHCI)		+= ahci-init-xlp2.o
diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
new file mode 100644
index 0000000..a55e111
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/nodemask.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/mips-extns.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+
+#define SATA_CTL		0x0
+#define SATA_STATUS		0x1 /* Status Reg */
+#define SATA_INT		0x2 /* Interrupt Reg */
+#define SATA_INT_MASK		0x3 /* Interrupt Mask Reg */
+#define SATA_BIU_TIMEOUT	0x4
+#define AXIWRSPERRLOG		0x5
+#define AXIRDSPERRLOG		0x6
+#define BiuTimeoutLow		0x7
+#define BiuTimeoutHi		0x8
+#define BiuSlvErLow		0x9
+#define BiuSlvErHi		0xa
+#define IO_CONFIG_SWAP_DIS	0xb
+#define CR_REG_TIMER		0xc
+#define CORE_ID			0xd
+#define AXI_SLAVE_OPT1		0xe
+#define PHY_MEM_ACCESS		0xf
+#define PHY0_CNTRL		0x10
+#define PHY0_STAT		0x11
+#define PHY0_RX_ALIGN		0x12
+#define PHY0_RX_EQ_LO		0x13
+#define PHY0_RX_EQ_HI		0x14
+#define PHY0_BIST_LOOP		0x15
+#define PHY1_CNTRL		0x16
+#define PHY1_STAT		0x17
+#define PHY1_RX_ALIGN		0x18
+#define PHY1_RX_EQ_LO		0x19
+#define PHY1_RX_EQ_HI		0x1a
+#define PHY1_BIST_LOOP		0x1b
+#define RdExBase		0x1c
+#define RdExLimit		0x1d
+#define CacheAllocBase		0x1e
+#define CacheAllocLimit		0x1f
+#define BiuSlaveCmdGstNum	0x20
+
+/*SATA_CTL Bits */
+#define SATA_RST_N		BIT(0)  /* Active low reset sata_core phy */
+#define SataCtlReserve0		BIT(1)
+#define M_CSYSREQ		BIT(2)  /* AXI master low power, not used */
+#define S_CSYSREQ		BIT(3)  /* AXI slave low power, not used */
+#define P0_CP_DET		BIT(8)  /* Reserved, bring in from pad */
+#define P0_MP_SW		BIT(9)  /* Mech Switch */
+#define P0_DISABLE		BIT(10) /* disable p0 */
+#define P0_ACT_LED_EN		BIT(11) /* Active LED enable */
+#define P0_IRST_HARD_SYNTH	BIT(12) /* PHY hard synth reset */
+#define P0_IRST_HARD_TXRX	BIT(13) /* PHY lane hard reset */
+#define P0_IRST_POR		BIT(14) /* PHY power on reset*/
+#define P0_IPDTXL		BIT(15) /* PHY Tx lane dis/power down */
+#define P0_IPDRXL		BIT(16) /* PHY Rx lane dis/power down */
+#define P0_IPDIPDMSYNTH		BIT(17) /* PHY synthesizer dis/porwer down */
+#define P0_CP_POD_EN		BIT(18) /* CP_POD enable */
+#define P0_AT_BYPASS		BIT(19) /* P0 address translation by pass */
+#define P1_CP_DET		BIT(20) /* Reserved,Cold Detect */
+#define P1_MP_SW		BIT(21) /* Mech Switch */
+#define P1_DISABLE		BIT(22) /* disable p1 */
+#define P1_ACT_LED_EN		BIT(23) /* Active LED enable */
+#define P1_IRST_HARD_SYNTH	BIT(24) /* PHY hard synth reset */
+#define P1_IRST_HARD_TXRX	BIT(25) /* PHY lane hard reset */
+#define P1_IRST_POR		BIT(26) /* PHY power on reset*/
+#define P1_IPDTXL		BIT(27) /* PHY Tx lane dis/porwer down */
+#define P1_IPDRXL		BIT(28) /* PHY Rx lane dis/porwer down */
+#define P1_IPDIPDMSYNTH		BIT(29) /* PHY synthesizer dis/porwer down */
+#define P1_CP_POD_EN		BIT(30)
+#define P1_AT_BYPASS		BIT(31) /* P1 address translation by pass */
+
+/* Status register */
+#define M_CACTIVE		BIT(0)  /* m_cactive, not used */
+#define S_CACTIVE		BIT(1)  /* s_cactive, not used */
+#define P0_PHY_READY		BIT(8)  /* phy is ready */
+#define P0_CP_POD		BIT(9)  /* Cold PowerOn */
+#define P0_SLUMBER		BIT(10) /* power mode slumber */
+#define P0_PATIAL		BIT(11) /* power mode patial */
+#define P0_PHY_SIG_DET		BIT(12) /* phy dignal detect */
+#define P0_PHY_CALI		BIT(13) /* phy calibration done */
+#define P1_PHY_READY		BIT(16) /* phy is ready */
+#define P1_CP_POD		BIT(17) /* Cold PowerOn */
+#define P1_SLUMBER		BIT(18) /* power mode slumber */
+#define P1_PATIAL		BIT(19) /* power mode patial */
+#define P1_PHY_SIG_DET		BIT(20) /* phy dignal detect */
+#define P1_PHY_CALI		BIT(21) /* phy calibration done */
+
+/* SATA CR_REG_TIMER bits */
+#define CR_TIME_SCALE		(0x1000 << 0)
+
+/* SATA PHY specific registers start and end address */
+#define RXCDRCALFOSC0		0x0065
+#define CALDUTY			0x006e
+#define RXDPIF			0x8065
+#define PPMDRIFTMAX_HI		0x80A4
+
+#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node)	\
+		nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
+#define nlm_get_sata_regbase(node)	\
+		(nlm_get_sata_pcibase(node) + 0x100)
+
+/* SATA PHY config for register block 1 0x0065 .. 0x006e */
+static const u8 sata_phy_config1[]  = {
+	0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
+};
+
+/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
+static const u8 sata_phy_config2[]  = {
+	0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
+	0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
+	0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
+	0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
+	0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
+	0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
+	0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
+};
+
+static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
+{
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(1u << 31) | (physel << 24) | (data << 16) | addr);
+	udelay(850);
+}
+
+static void config_sata_phy(u64 regbase, u32 node)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
+	}
+}
+
+#if 0	/* DEBUG */
+static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
+{
+	u32 val;
+
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(0 << 31) | (physel << 24) | (data << 16) | addr);
+	udelay(850);
+	val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
+	return (val >> 16) & 0xff;
+}
+
+static void check_phy_register(u63 regbase, u32 addr, u32 physel, u8 xdata)
+{
+	u64 regbase;
+	u8 data;
+
+	data = read_phy_reg(regbase, addr, physel);
+	pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
+		addr, physel, data, data == xdata ? "TRUE" : "FALSE");
+}
+
+static void verify_sata_phy_config(u64 regbase, u32 node)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			check_phy_register(regbase, node, reg, port,
+					sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			check_phy_register(regbase, node, reg, port,
+					sata_phy_config2[i]);
+	}
+}
+#endif
+
+static void nlm_sata_firmware_init(int node)
+{
+	u32 reg_val;
+	u64 regbase;
+	int n;
+
+	pr_info("Initializing XLP9XX On-chip AHCI...\n");
+	regbase = nlm_get_sata_regbase(node);
+
+	/* Reset port0 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+
+	/* port1 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+	udelay(300);
+
+	/* Set PHY */
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	udelay(1000);
+
+	/* setup PHY */
+	config_sata_phy(regbase, node);
+#if 0	/* For debug */
+	verify_sata_phy_config(regbase, node);
+#endif
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	udelay(300);
+
+	/* Override reset in serial PHY mode */
+	sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
+	/* Set reset SATA */
+	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
+	sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
+
+	pr_debug("Waiting for PHYs to come up.\n");
+	n = 10000;
+	do {
+		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+		if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
+			break;
+		udelay(10);
+	} while (--n > 0);
+
+	if (reg_val  & P0_PHY_READY)
+		pr_info("PHY0 is up.\n");
+	else
+		pr_info("PHY0 is down.\n");
+	if (reg_val  & P1_PHY_READY)
+		pr_info("PHY1 is up.\n");
+	else
+		pr_info("PHY1 is down.\n");
+
+	pr_info("XLP AHCI Init Done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+	int node;
+
+	if (!cpu_is_xlp9xx())
+		return 0;
+	for (node = 0; node < NLM_NR_NODES; node++)
+		if (nlm_node_present(node))
+			nlm_sata_firmware_init(node);
+	return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+	u64 regbase;
+	u32 val;
+	int node;
+
+	node = data->irq / NLM_IRQS_PER_NODE;
+	regbase = nlm_get_sata_regbase(node);
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+	dev->resource[5] = dev->resource[0];
+	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+	u32 val;
+	u64 regbase;
+	int node;
+
+	/* Find end bridge function to find node */
+	node = xlp_socdev_to_node(dev);
+	regbase = nlm_get_sata_regbase(node);
+
+	/* clear pending interrupts and then enable them */
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+
+	/* Enable only the core interrupt */
+	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+	dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
+	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_bar);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_final);
-- 
1.7.9.5

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

* Re: [PATCH 11/17] MIPS: Netlogic: Fix XLP9XX pic entry
  2014-04-29 14:37   ` Jayachandran C
  (?)
@ 2014-04-29 17:36   ` Sergei Shtylyov
  2014-04-30  9:56       ` Jayachandran C.
  -1 siblings, 1 reply; 49+ messages in thread
From: Sergei Shtylyov @ 2014-04-29 17:36 UTC (permalink / raw)
  To: Jayachandran C, linux-mips; +Cc: ralf

Hello.

On 04/29/2014 06:37 PM, Jayachandran C wrote:

> Add the compatible property to the PIC entry. Also fix up the nodename
> to use the correct address.

> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
>   arch/mips/netlogic/dts/xlp_gvp.dts |    5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)

> diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts
> index 047d27f..bb4ecd1 100644
> --- a/arch/mips/netlogic/dts/xlp_gvp.dts
> +++ b/arch/mips/netlogic/dts/xlp_gvp.dts
> @@ -26,11 +26,12 @@
>   			interrupt-parent = <&pic>;
>   			interrupts = <17>;
>   		};
> -		pic: pic@4000 {
> -			interrupt-controller;
> +		pic: pic@110000 {

    According to the ePAPR standard [1], the node name should be 
"interrupt-controller@110000".

> +			compatible = "netlogic,xlp-pic";
>   			#address-cells = <0>;
>   			#interrupt-cells = <1>;
>   			reg = <0 0x110000 0x200>;
> +			interrupt-controller;
>   		};

[1] http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf

WBR, Sergei

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

* Re: [PATCH 11/17] MIPS: Netlogic: Fix XLP9XX pic entry
@ 2014-04-30  9:56       ` Jayachandran C.
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C. @ 2014-04-30  9:56 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linux-mips, ralf

On Tue, Apr 29, 2014 at 09:36:18PM +0400, Sergei Shtylyov wrote:
> Hello.
> 
> On 04/29/2014 06:37 PM, Jayachandran C wrote:
> 
> >Add the compatible property to the PIC entry. Also fix up the nodename
> >to use the correct address.
> 
> >Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> >---
> >  arch/mips/netlogic/dts/xlp_gvp.dts |    5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> >diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts
> >index 047d27f..bb4ecd1 100644
> >--- a/arch/mips/netlogic/dts/xlp_gvp.dts
> >+++ b/arch/mips/netlogic/dts/xlp_gvp.dts
> >@@ -26,11 +26,12 @@
> >  			interrupt-parent = <&pic>;
> >  			interrupts = <17>;
> >  		};
> >-		pic: pic@4000 {
> >-			interrupt-controller;
> >+		pic: pic@110000 {
> 
>    According to the ePAPR standard [1], the node name should be
> "interrupt-controller@110000".
> 
> >+			compatible = "netlogic,xlp-pic";
> >  			#address-cells = <0>;
> >  			#interrupt-cells = <1>;
> >  			reg = <0 0x110000 0x200>;
> >+			interrupt-controller;
> >  		};

The ePAPR document itself has a interrupt-controller definition which
uses the node name "pic". And most of the linux kernel dts files use
"pic" as well.

Based on this, I think that even if the standard recommends using
interrupt-contoller as the nodename, pic can be used as well.

Thanks,
JC.

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

* Re: [PATCH 11/17] MIPS: Netlogic: Fix XLP9XX pic entry
@ 2014-04-30  9:56       ` Jayachandran C.
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C. @ 2014-04-30  9:56 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linux-mips, ralf

On Tue, Apr 29, 2014 at 09:36:18PM +0400, Sergei Shtylyov wrote:
> Hello.
> 
> On 04/29/2014 06:37 PM, Jayachandran C wrote:
> 
> >Add the compatible property to the PIC entry. Also fix up the nodename
> >to use the correct address.
> 
> >Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> >---
> >  arch/mips/netlogic/dts/xlp_gvp.dts |    5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> >diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts
> >index 047d27f..bb4ecd1 100644
> >--- a/arch/mips/netlogic/dts/xlp_gvp.dts
> >+++ b/arch/mips/netlogic/dts/xlp_gvp.dts
> >@@ -26,11 +26,12 @@
> >  			interrupt-parent = <&pic>;
> >  			interrupts = <17>;
> >  		};
> >-		pic: pic@4000 {
> >-			interrupt-controller;
> >+		pic: pic@110000 {
> 
>    According to the ePAPR standard [1], the node name should be
> "interrupt-controller@110000".
> 
> >+			compatible = "netlogic,xlp-pic";
> >  			#address-cells = <0>;
> >  			#interrupt-cells = <1>;
> >  			reg = <0 0x110000 0x200>;
> >+			interrupt-controller;
> >  		};

The ePAPR document itself has a interrupt-controller definition which
uses the node name "pic". And most of the linux kernel dts files use
"pic" as well.

Based on this, I think that even if the standard recommends using
interrupt-contoller as the nodename, pic can be used as well.

Thanks,
JC.

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

* [PATCH v2 06/17] MIPS: Netlogic: Use cpumask_scnprintf for wakeup_mask
@ 2014-05-09 11:04     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:04 UTC (permalink / raw)
  To: g, linux-mips; +Cc: Jayachandran C, ralf

Use standard function to print cpumask. Also fixup a typo in the same
file.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Fix subject line for patch]

 arch/mips/netlogic/common/smp.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6baae15..b93c5d4 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -198,7 +198,7 @@ void __init nlm_smp_setup(void)
 	cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
 	pr_info("Possible CPU mask: %s\n", buf);
 
-	/* check with the cores we have worken up */
+	/* check with the cores we have woken up */
 	for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
 		ncore += hweight32(nlm_get_node(i)->coremask);
 
@@ -213,6 +213,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 {
 	uint32_t core0_thr_mask, core_thr_mask;
 	int threadmode, i, j;
+	char buf[64];
 
 	core0_thr_mask = 0;
 	for (i = 0; i < NLM_THREADS_PER_CORE; i++)
@@ -247,8 +248,8 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 	return threadmode;
 
 unsupp:
-	panic("Unsupported CPU mask %lx",
-		(unsigned long)cpumask_bits(wakeup_mask)[0]);
+	cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
+	panic("Unsupported CPU mask %s", buf);
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH v2 06/17] MIPS: Netlogic: Use cpumask_scnprintf for wakeup_mask
@ 2014-05-09 11:04     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:04 UTC (permalink / raw)
  To: g, linux-mips; +Cc: Jayachandran C, ralf

Use standard function to print cpumask. Also fixup a typo in the same
file.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Fix subject line for patch]

 arch/mips/netlogic/common/smp.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6baae15..b93c5d4 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -198,7 +198,7 @@ void __init nlm_smp_setup(void)
 	cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
 	pr_info("Possible CPU mask: %s\n", buf);
 
-	/* check with the cores we have worken up */
+	/* check with the cores we have woken up */
 	for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
 		ncore += hweight32(nlm_get_node(i)->coremask);
 
@@ -213,6 +213,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 {
 	uint32_t core0_thr_mask, core_thr_mask;
 	int threadmode, i, j;
+	char buf[64];
 
 	core0_thr_mask = 0;
 	for (i = 0; i < NLM_THREADS_PER_CORE; i++)
@@ -247,8 +248,8 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 	return threadmode;
 
 unsupp:
-	panic("Unsupported CPU mask %lx",
-		(unsigned long)cpumask_bits(wakeup_mask)[0]);
+	cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
+	panic("Unsupported CPU mask %s", buf);
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH v2 07/17] MIPS: Netlogic: Reduce size of reset code
@ 2014-05-09 11:05     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:05 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Update thread wakeup function to use scratch registers for saving SP and
RA. Move the register restore code needed for thread 0 to the calling
function. This reduces the size of code copied to the reset vector.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Use proper function macros for xlp_boot_core0_siblings]

 arch/mips/netlogic/common/reset.S   |   15 ++++++++-------
 arch/mips/netlogic/common/smpboot.S |   12 ++++++++----
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index b231fe1..fda772a 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -197,6 +197,9 @@ FEXPORT(nlm_reset_entry)
 EXPORT(nlm_boot_siblings)
 	/* core L1D flush before enable threads */
 	xlp_flush_l1_dcache
+	/* save ra and sp, will be used later (only for boot cpu) */
+	dmtc0	ra, $22, 6
+	dmtc0	sp, $22, 7
 	/* Enable hw threads by writing to MAP_THREADMODE of the core */
 	li	t0, CKSEG1ADDR(RESET_DATA_PHYS)
 	lw	t1, BOOT_THREAD_MODE(t0)	/* t1 <- thread mode */
@@ -238,14 +241,12 @@ EXPORT(nlm_boot_siblings)
 	nop
 
 	/*
-	 * For the boot CPU, we have to restore registers and
-	 * return
+	 * For the boot CPU, we have to restore ra and sp and return, rest
+	 * of the registers will be restored by the caller
 	 */
-4:	dmfc0	t0, $4, 2	/* restore SP from UserLocal */
-	li	t1, 0xfadebeef
-	dmtc0	t1, $4, 2	/* restore SP from UserLocal */
-	PTR_SUBU sp, t0, PT_SIZE
-	RESTORE_ALL
+4:
+	dmfc0	ra, $22, 6
+	dmfc0	sp, $22, 7
 	jr	ra
 	nop
 EXPORT(nlm_reset_entry_end)
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index 8597657..805355b 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -54,8 +54,9 @@
 	.set	noat
 	.set	arch=xlr		/* for mfcr/mtcr, XLR is sufficient */
 
-FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
-	dmtc0	sp, $4, 2		/* SP saved in UserLocal */
+/* Called by the boot cpu to wake up its sibling threads */
+NESTED(xlp_boot_core0_siblings, PT_SIZE, sp)
+	/* CPU register contents lost when enabling threads, save them first */
 	SAVE_ALL
 	sync
 	/* find the location to which nlm_boot_siblings was relocated */
@@ -65,9 +66,12 @@ FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
 	dsubu	t2, t1
 	daddu	t2, t0
 	/* call it */
-	jr	t2
+	jalr	t2
 	nop
-	/* not reached */
+	RESTORE_ALL
+	jr	ra
+	nop
+END(xlp_boot_core0_siblings)
 
 NESTED(nlm_boot_secondary_cpus, 16, sp)
 	/* Initialize CP0 Status */
-- 
1.7.9.5

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

* [PATCH v2 07/17] MIPS: Netlogic: Reduce size of reset code
@ 2014-05-09 11:05     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:05 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Update thread wakeup function to use scratch registers for saving SP and
RA. Move the register restore code needed for thread 0 to the calling
function. This reduces the size of code copied to the reset vector.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Use proper function macros for xlp_boot_core0_siblings]

 arch/mips/netlogic/common/reset.S   |   15 ++++++++-------
 arch/mips/netlogic/common/smpboot.S |   12 ++++++++----
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index b231fe1..fda772a 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -197,6 +197,9 @@ FEXPORT(nlm_reset_entry)
 EXPORT(nlm_boot_siblings)
 	/* core L1D flush before enable threads */
 	xlp_flush_l1_dcache
+	/* save ra and sp, will be used later (only for boot cpu) */
+	dmtc0	ra, $22, 6
+	dmtc0	sp, $22, 7
 	/* Enable hw threads by writing to MAP_THREADMODE of the core */
 	li	t0, CKSEG1ADDR(RESET_DATA_PHYS)
 	lw	t1, BOOT_THREAD_MODE(t0)	/* t1 <- thread mode */
@@ -238,14 +241,12 @@ EXPORT(nlm_boot_siblings)
 	nop
 
 	/*
-	 * For the boot CPU, we have to restore registers and
-	 * return
+	 * For the boot CPU, we have to restore ra and sp and return, rest
+	 * of the registers will be restored by the caller
 	 */
-4:	dmfc0	t0, $4, 2	/* restore SP from UserLocal */
-	li	t1, 0xfadebeef
-	dmtc0	t1, $4, 2	/* restore SP from UserLocal */
-	PTR_SUBU sp, t0, PT_SIZE
-	RESTORE_ALL
+4:
+	dmfc0	ra, $22, 6
+	dmfc0	sp, $22, 7
 	jr	ra
 	nop
 EXPORT(nlm_reset_entry_end)
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index 8597657..805355b 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -54,8 +54,9 @@
 	.set	noat
 	.set	arch=xlr		/* for mfcr/mtcr, XLR is sufficient */
 
-FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
-	dmtc0	sp, $4, 2		/* SP saved in UserLocal */
+/* Called by the boot cpu to wake up its sibling threads */
+NESTED(xlp_boot_core0_siblings, PT_SIZE, sp)
+	/* CPU register contents lost when enabling threads, save them first */
 	SAVE_ALL
 	sync
 	/* find the location to which nlm_boot_siblings was relocated */
@@ -65,9 +66,12 @@ FEXPORT(xlp_boot_core0_siblings)	/* "Master" cpu starts from here */
 	dsubu	t2, t1
 	daddu	t2, t0
 	/* call it */
-	jr	t2
+	jalr	t2
 	nop
-	/* not reached */
+	RESTORE_ALL
+	jr	ra
+	nop
+END(xlp_boot_core0_siblings)
 
 NESTED(nlm_boot_secondary_cpus, 16, sp)
 	/* Initialize CP0 Status */
-- 
1.7.9.5

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

* [PATCH v2 09/17] MIPS: Netlogic: IRQ mapping for some more SoC blocks
@ 2014-05-09 11:05     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:05 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Add IRQ to IRT (PIC interupt table index) mapping for SATA, GPIO, NAND
and SPI interfaces on the XLP SoC. Fix offsets for few blocks and add
device IDs for a few blocks.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Fix GPIO irq]

 arch/mips/include/asm/netlogic/xlp-hal/iomap.h |   16 +++--
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h   |    4 ++
 arch/mips/netlogic/xlp/nlm_hal.c               |   84 ++++++++++++++++--------
 3 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 1f23dfa..14b2f51 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -74,6 +74,8 @@
 #define XLP_IO_USB_OHCI2_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 4)
 #define XLP_IO_USB_OHCI3_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 5)
 
+#define XLP_IO_SATA_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 3, 2)
+
 /* XLP2xx has an updated USB block */
 #define XLP2XX_IO_USB_OFFSET(node, i)	XLP_HDR_OFFSET(node, 0, 4, i)
 #define XLP2XX_IO_USB_XHCI0_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 4, 1)
@@ -103,13 +105,11 @@
 #define XLP_IO_SYS_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 6, 5)
 #define XLP_IO_JTAG_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 6, 6)
 
+/* Flash */
 #define XLP_IO_NOR_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 0)
 #define XLP_IO_NAND_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 7, 1)
 #define XLP_IO_SPI_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 2)
-/* SD flash */
-#define XLP_IO_SD_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
-#define XLP_IO_MMC_OFFSET(node, slot)	\
-		((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+#define XLP_IO_MMC_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
 
 /* Things have changed drastically in XLP 9XX */
 #define XLP9XX_HDR_OFFSET(n, d, f)	\
@@ -135,11 +135,11 @@
 /* XLP9XX on-chip SATA controller */
 #define XLP9XX_IO_SATA_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 3, 2)
 
+/* Flash */
 #define XLP9XX_IO_NOR_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 0)
 #define XLP9XX_IO_NAND_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 1)
 #define XLP9XX_IO_SPI_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 2)
-/* SD flash */
-#define XLP9XX_IO_MMCSD_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
+#define XLP9XX_IO_MMC_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
 
 /* PCI config header register id's */
 #define XLP_PCI_CFGREG0			0x00
@@ -186,8 +186,10 @@
 #define PCI_DEVICE_ID_NLM_NOR		0x1015
 #define PCI_DEVICE_ID_NLM_NAND		0x1016
 #define PCI_DEVICE_ID_NLM_MMC		0x1018
-#define PCI_DEVICE_ID_NLM_XHCI		0x101d
+#define PCI_DEVICE_ID_NLM_SATA		0x101A
+#define PCI_DEVICE_ID_NLM_XHCI		0x101D
 
+#define PCI_DEVICE_ID_XLP9XX_MMC	0x9018
 #define PCI_DEVICE_ID_XLP9XX_SATA	0x901A
 #define PCI_DEVICE_ID_XLP9XX_XHCI	0x901D
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 1b56bd4..488863e 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -58,6 +58,10 @@
 #define PIC_I2C_1_IRQ			31
 #define PIC_I2C_2_IRQ			32
 #define PIC_I2C_3_IRQ			33
+#define PIC_SPI_IRQ			34
+#define PIC_NAND_IRQ			37
+#define PIC_SATA_IRQ			38
+#define PIC_GPIO_IRQ			39
 
 #define PIC_PCIE_LINK_MSI_IRQ_BASE	44	/* 44 - 47 MSI IRQ */
 #define PIC_PCIE_LINK_MSI_IRQ(i)	(44 + (i))
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index d85019b..66a2dae 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -66,31 +66,39 @@ void nlm_node_init(int node)
 	spin_lock_init(&nodep->piclock);
 }
 
-int nlm_irq_to_irt(int irq)
+static int xlp9xx_irq_to_irt(int irq)
+{
+	switch (irq) {
+	case PIC_GPIO_IRQ:
+		return 12;
+	case PIC_9XX_XHCI_0_IRQ:
+		return 114;
+	case PIC_9XX_XHCI_1_IRQ:
+		return 115;
+	case PIC_UART_0_IRQ:
+		return 133;
+	case PIC_UART_1_IRQ:
+		return 134;
+	case PIC_SATA_IRQ:
+		return 143;
+	case PIC_SPI_IRQ:
+		return 152;
+	case PIC_MMC_IRQ:
+		return 153;
+	case PIC_PCIE_LINK_LEGACY_IRQ(0):
+	case PIC_PCIE_LINK_LEGACY_IRQ(1):
+	case PIC_PCIE_LINK_LEGACY_IRQ(2):
+	case PIC_PCIE_LINK_LEGACY_IRQ(3):
+		return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
+	}
+	return -1;
+}
+
+static int xlp_irq_to_irt(int irq)
 {
 	uint64_t pcibase;
 	int devoff, irt;
 
-	/* bypass for 9xx */
-	if (cpu_is_xlp9xx()) {
-		switch (irq) {
-		case PIC_9XX_XHCI_0_IRQ:
-			return 114;
-		case PIC_9XX_XHCI_1_IRQ:
-			return 115;
-		case PIC_UART_0_IRQ:
-			return 133;
-		case PIC_UART_1_IRQ:
-			return 134;
-		case PIC_PCIE_LINK_LEGACY_IRQ(0):
-		case PIC_PCIE_LINK_LEGACY_IRQ(1):
-		case PIC_PCIE_LINK_LEGACY_IRQ(2):
-		case PIC_PCIE_LINK_LEGACY_IRQ(3):
-			return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
-		}
-		return -1;
-	}
-
 	devoff = 0;
 	switch (irq) {
 	case PIC_UART_0_IRQ:
@@ -100,7 +108,7 @@ int nlm_irq_to_irt(int irq)
 		devoff = XLP_IO_UART1_OFFSET(0);
 		break;
 	case PIC_MMC_IRQ:
-		devoff = XLP_IO_SD_OFFSET(0);
+		devoff = XLP_IO_MMC_OFFSET(0);
 		break;
 	case PIC_I2C_0_IRQ:	/* I2C will be fixed up */
 	case PIC_I2C_1_IRQ:
@@ -111,6 +119,18 @@ int nlm_irq_to_irt(int irq)
 		else
 			devoff = XLP_IO_I2C0_OFFSET(0);
 		break;
+	case PIC_SATA_IRQ:
+		devoff = XLP_IO_SATA_OFFSET(0);
+		break;
+	case PIC_GPIO_IRQ:
+		devoff = XLP_IO_GPIO_OFFSET(0);
+		break;
+	case PIC_NAND_IRQ:
+		devoff = XLP_IO_NAND_OFFSET(0);
+		break;
+	case PIC_SPI_IRQ:
+		devoff = XLP_IO_SPI_OFFSET(0);
+		break;
 	default:
 		if (cpu_is_xlpii()) {
 			switch (irq) {
@@ -166,18 +186,26 @@ int nlm_irq_to_irt(int irq)
 		/* HW bug, PCI IRT entries are bad on early silicon, fix */
 		irt = PIC_IRT_PCIE_LINK_INDEX(irq -
 					PIC_PCIE_LINK_LEGACY_IRQ_BASE);
-	} else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) &&
-			irq <= PIC_PCIE_LINK_MSI_IRQ(3)) {
-		irt = -2;
-	} else if (irq >= PIC_PCIE_MSIX_IRQ(0) &&
-			irq <= PIC_PCIE_MSIX_IRQ(3)) {
-		irt = -2;
 	} else {
 		irt = -1;
 	}
 	return irt;
 }
 
+int nlm_irq_to_irt(int irq)
+{
+	/* return -2 for irqs without 1-1 mapping */
+	if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
+		return -2;
+	if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
+		return -2;
+
+	if (cpu_is_xlp9xx())
+		return xlp9xx_irq_to_irt(irq);
+	else
+		return xlp_irq_to_irt(irq);
+}
+
 unsigned int nlm_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
-- 
1.7.9.5

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

* [PATCH v2 09/17] MIPS: Netlogic: IRQ mapping for some more SoC blocks
@ 2014-05-09 11:05     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:05 UTC (permalink / raw)
  To: linux-mips; +Cc: Jayachandran C, ralf

Add IRQ to IRT (PIC interupt table index) mapping for SATA, GPIO, NAND
and SPI interfaces on the XLP SoC. Fix offsets for few blocks and add
device IDs for a few blocks.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Fix GPIO irq]

 arch/mips/include/asm/netlogic/xlp-hal/iomap.h |   16 +++--
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h   |    4 ++
 arch/mips/netlogic/xlp/nlm_hal.c               |   84 ++++++++++++++++--------
 3 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 1f23dfa..14b2f51 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -74,6 +74,8 @@
 #define XLP_IO_USB_OHCI2_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 4)
 #define XLP_IO_USB_OHCI3_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 2, 5)
 
+#define XLP_IO_SATA_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 3, 2)
+
 /* XLP2xx has an updated USB block */
 #define XLP2XX_IO_USB_OFFSET(node, i)	XLP_HDR_OFFSET(node, 0, 4, i)
 #define XLP2XX_IO_USB_XHCI0_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 4, 1)
@@ -103,13 +105,11 @@
 #define XLP_IO_SYS_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 6, 5)
 #define XLP_IO_JTAG_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 6, 6)
 
+/* Flash */
 #define XLP_IO_NOR_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 0)
 #define XLP_IO_NAND_OFFSET(node)	XLP_HDR_OFFSET(node, 0, 7, 1)
 #define XLP_IO_SPI_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 2)
-/* SD flash */
-#define XLP_IO_SD_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
-#define XLP_IO_MMC_OFFSET(node, slot)	\
-		((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+#define XLP_IO_MMC_OFFSET(node)		XLP_HDR_OFFSET(node, 0, 7, 3)
 
 /* Things have changed drastically in XLP 9XX */
 #define XLP9XX_HDR_OFFSET(n, d, f)	\
@@ -135,11 +135,11 @@
 /* XLP9XX on-chip SATA controller */
 #define XLP9XX_IO_SATA_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 3, 2)
 
+/* Flash */
 #define XLP9XX_IO_NOR_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 0)
 #define XLP9XX_IO_NAND_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 1)
 #define XLP9XX_IO_SPI_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 2)
-/* SD flash */
-#define XLP9XX_IO_MMCSD_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
+#define XLP9XX_IO_MMC_OFFSET(node)		XLP9XX_HDR_OFFSET(node, 7, 3)
 
 /* PCI config header register id's */
 #define XLP_PCI_CFGREG0			0x00
@@ -186,8 +186,10 @@
 #define PCI_DEVICE_ID_NLM_NOR		0x1015
 #define PCI_DEVICE_ID_NLM_NAND		0x1016
 #define PCI_DEVICE_ID_NLM_MMC		0x1018
-#define PCI_DEVICE_ID_NLM_XHCI		0x101d
+#define PCI_DEVICE_ID_NLM_SATA		0x101A
+#define PCI_DEVICE_ID_NLM_XHCI		0x101D
 
+#define PCI_DEVICE_ID_XLP9XX_MMC	0x9018
 #define PCI_DEVICE_ID_XLP9XX_SATA	0x901A
 #define PCI_DEVICE_ID_XLP9XX_XHCI	0x901D
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 1b56bd4..488863e 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -58,6 +58,10 @@
 #define PIC_I2C_1_IRQ			31
 #define PIC_I2C_2_IRQ			32
 #define PIC_I2C_3_IRQ			33
+#define PIC_SPI_IRQ			34
+#define PIC_NAND_IRQ			37
+#define PIC_SATA_IRQ			38
+#define PIC_GPIO_IRQ			39
 
 #define PIC_PCIE_LINK_MSI_IRQ_BASE	44	/* 44 - 47 MSI IRQ */
 #define PIC_PCIE_LINK_MSI_IRQ(i)	(44 + (i))
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index d85019b..66a2dae 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -66,31 +66,39 @@ void nlm_node_init(int node)
 	spin_lock_init(&nodep->piclock);
 }
 
-int nlm_irq_to_irt(int irq)
+static int xlp9xx_irq_to_irt(int irq)
+{
+	switch (irq) {
+	case PIC_GPIO_IRQ:
+		return 12;
+	case PIC_9XX_XHCI_0_IRQ:
+		return 114;
+	case PIC_9XX_XHCI_1_IRQ:
+		return 115;
+	case PIC_UART_0_IRQ:
+		return 133;
+	case PIC_UART_1_IRQ:
+		return 134;
+	case PIC_SATA_IRQ:
+		return 143;
+	case PIC_SPI_IRQ:
+		return 152;
+	case PIC_MMC_IRQ:
+		return 153;
+	case PIC_PCIE_LINK_LEGACY_IRQ(0):
+	case PIC_PCIE_LINK_LEGACY_IRQ(1):
+	case PIC_PCIE_LINK_LEGACY_IRQ(2):
+	case PIC_PCIE_LINK_LEGACY_IRQ(3):
+		return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
+	}
+	return -1;
+}
+
+static int xlp_irq_to_irt(int irq)
 {
 	uint64_t pcibase;
 	int devoff, irt;
 
-	/* bypass for 9xx */
-	if (cpu_is_xlp9xx()) {
-		switch (irq) {
-		case PIC_9XX_XHCI_0_IRQ:
-			return 114;
-		case PIC_9XX_XHCI_1_IRQ:
-			return 115;
-		case PIC_UART_0_IRQ:
-			return 133;
-		case PIC_UART_1_IRQ:
-			return 134;
-		case PIC_PCIE_LINK_LEGACY_IRQ(0):
-		case PIC_PCIE_LINK_LEGACY_IRQ(1):
-		case PIC_PCIE_LINK_LEGACY_IRQ(2):
-		case PIC_PCIE_LINK_LEGACY_IRQ(3):
-			return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
-		}
-		return -1;
-	}
-
 	devoff = 0;
 	switch (irq) {
 	case PIC_UART_0_IRQ:
@@ -100,7 +108,7 @@ int nlm_irq_to_irt(int irq)
 		devoff = XLP_IO_UART1_OFFSET(0);
 		break;
 	case PIC_MMC_IRQ:
-		devoff = XLP_IO_SD_OFFSET(0);
+		devoff = XLP_IO_MMC_OFFSET(0);
 		break;
 	case PIC_I2C_0_IRQ:	/* I2C will be fixed up */
 	case PIC_I2C_1_IRQ:
@@ -111,6 +119,18 @@ int nlm_irq_to_irt(int irq)
 		else
 			devoff = XLP_IO_I2C0_OFFSET(0);
 		break;
+	case PIC_SATA_IRQ:
+		devoff = XLP_IO_SATA_OFFSET(0);
+		break;
+	case PIC_GPIO_IRQ:
+		devoff = XLP_IO_GPIO_OFFSET(0);
+		break;
+	case PIC_NAND_IRQ:
+		devoff = XLP_IO_NAND_OFFSET(0);
+		break;
+	case PIC_SPI_IRQ:
+		devoff = XLP_IO_SPI_OFFSET(0);
+		break;
 	default:
 		if (cpu_is_xlpii()) {
 			switch (irq) {
@@ -166,18 +186,26 @@ int nlm_irq_to_irt(int irq)
 		/* HW bug, PCI IRT entries are bad on early silicon, fix */
 		irt = PIC_IRT_PCIE_LINK_INDEX(irq -
 					PIC_PCIE_LINK_LEGACY_IRQ_BASE);
-	} else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) &&
-			irq <= PIC_PCIE_LINK_MSI_IRQ(3)) {
-		irt = -2;
-	} else if (irq >= PIC_PCIE_MSIX_IRQ(0) &&
-			irq <= PIC_PCIE_MSIX_IRQ(3)) {
-		irt = -2;
 	} else {
 		irt = -1;
 	}
 	return irt;
 }
 
+int nlm_irq_to_irt(int irq)
+{
+	/* return -2 for irqs without 1-1 mapping */
+	if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
+		return -2;
+	if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
+		return -2;
+
+	if (cpu_is_xlp9xx())
+		return xlp9xx_irq_to_irt(irq);
+	else
+		return xlp_irq_to_irt(irq);
+}
+
 unsigned int nlm_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
-- 
1.7.9.5

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

* [PATCH v2 15/17] MIPS: Add MSI support for XLP9XX
@ 2014-05-09 11:05     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:05 UTC (permalink / raw)
  To: g, linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

In XLP9XX, the interrupt routing table for MSI-X has been moved to the
PCIe controller's config space from PIC. There are also 32 MSI-X
interrupts available per link on XLP9XX.

Update XLP MSI/MSI-X code to handle this.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Added correct MSI ack register for 9XX]

 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |   14 ++
 arch/mips/include/asm/netlogic/xlp-hal/pic.h    |    4 +
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h    |    5 +-
 arch/mips/pci/msi-xlp.c                         |  184 +++++++++++++++++------
 4 files changed, 156 insertions(+), 51 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index d4deb87..91540f4 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -69,6 +69,20 @@
 #define PCIE_9XX_BYTE_SWAP_IO_BASE	0x25e
 #define PCIE_9XX_BYTE_SWAP_IO_LIM	0x25f
 
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE	0x264
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT	0x265
+#define PCIE_9XX_MSI_STATUS		0x283
+#define PCIE_9XX_MSI_EN			0x284
+/* 128 MSIX vectors available in 9xx */
+#define PCIE_9XX_MSIX_STATUS0		0x286
+#define PCIE_9XX_MSIX_STATUSX(n)	(n + 0x286)
+#define PCIE_9XX_MSIX_VEC		0x296
+#define PCIE_9XX_MSIX_VECX(n)		(n + 0x296)
+#define PCIE_9XX_INT_STATUS0		0x397
+#define PCIE_9XX_INT_STATUS1		0x398
+#define PCIE_9XX_INT_EN0		0x399
+#define PCIE_9XX_INT_EN1		0x39a
+
 /* other */
 #define PCIE_NLINKS			4
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index f10bf3b..41cefe9 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -199,6 +199,10 @@
 #define PIC_IRT_PCIE_LINK_3_INDEX	81
 #define PIC_IRT_PCIE_LINK_INDEX(num)	((num) + PIC_IRT_PCIE_LINK_0_INDEX)
 
+#define PIC_9XX_IRT_PCIE_LINK_0_INDEX	191
+#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \
+				((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX)
+
 #define PIC_CLOCK_TIMER			7
 
 #if !defined(LOCORE) && !defined(__ASSEMBLY__)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 8f8afe0..c0b2a80 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -70,8 +70,9 @@
 #define PIC_PCIE_MSIX_IRQ_BASE		48	/* 48 - 51 MSI-X IRQ */
 #define PIC_PCIE_MSIX_IRQ(i)		(48 + (i))
 
-#define NLM_MSIX_VEC_BASE		96	/* 96 - 127 - MSIX mapped */
-#define NLM_MSI_VEC_BASE		128	/* 128 -255 - MSI mapped */
+/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */
+#define NLM_MSIX_VEC_BASE		96	/* 96 - 223 - MSIX mapped */
+#define NLM_MSI_VEC_BASE		224	/* 224 -351 - MSI mapped */
 
 #define NLM_PIC_INDIRECT_VEC_BASE	512
 #define NLM_GPIO_VEC_BASE		768
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index afd8405..1ef3ed6 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -56,8 +56,8 @@
 #include <asm/netlogic/xlp-hal/bridge.h>
 
 #define XLP_MSIVEC_PER_LINK	32
-#define XLP_MSIXVEC_TOTAL	32
-#define XLP_MSIXVEC_PER_LINK	8
+#define XLP_MSIXVEC_TOTAL	(cpu_is_xlp9xx() ? 128 : 32)
+#define XLP_MSIXVEC_PER_LINK	(cpu_is_xlp9xx() ? 32 : 8)
 
 /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */
 static inline int nlm_link_msiirq(int link, int msivec)
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec)
 	return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msivec(int irq)
 {
-	return irq % XLP_MSIVEC_PER_LINK;
+	return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK;
 }
 
+/* get the link from the irq number */
 static inline int nlm_irq_msilink(int irq)
 {
-	return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) /
-						XLP_MSIVEC_PER_LINK;
+	int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS;
+
+	return ((irq - NLM_MSI_VEC_BASE) % total_msivec) /
+		XLP_MSIVEC_PER_LINK;
 }
 
 /*
- * Only 32 MSI-X vectors are possible because there are only 32 PIC
- * interrupts for MSI. We split them statically and use 8 MSI-X vectors
- * per link - this keeps the allocation and lookup simple.
+ * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because
+ * there are only 32 PIC interrupts for MSI. We split them statically
+ * and use 8 MSI-X vectors per link - this keeps the allocation and
+ * lookup simple.
+ * On XLP 9xx, there are 32 vectors per link, and the interrupts are
+ * not routed thru PIC, so we can use all 128 MSI-X vectors.
  */
 static inline int nlm_link_msixirq(int link, int bit)
 {
 	return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msixvec(int irq)
 {
-	return irq % XLP_MSIXVEC_TOTAL;  /* works when given xirq */
+	return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL;
 }
 
-static inline int nlm_irq_msixlink(int irq)
+/* get the link from MSIX vec */
+static inline int nlm_irq_msixlink(int msixvec)
 {
-	return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK;
+	return msixvec / XLP_MSIXVEC_PER_LINK;
 }
 
 /*
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask |= 1u << vec;
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask &= ~(1u << vec);
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d)
 	xlp_msi_disable(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
+	if (cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_9XX_IRT_PCIE_LINK_INDEX(link));
+	else
+		nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
 }
 
 static struct irq_chip xlp_msi_chip = {
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = {
 };
 
 /*
- * The MSI-X interrupt handling is different from MSI, there are 32
- * MSI-X interrupts generated by the PIC and each of these correspond
- * to a MSI-X vector (0-31) that can be assigned.
+ * XLP8XX/4XX/3XX/2XX:
+ * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X
+ * interrupts generated by the PIC and each of these correspond to a MSI-X
+ * vector (0-31) that can be assigned.
  *
- * We divide the MSI-X vectors to 8 per link and do a per-link
- * allocation
+ * We divide the MSI-X vectors to 8 per link and do a per-link allocation
+ *
+ * XLP9XX:
+ * 32 MSI-X vectors are available per link, and the interrupts are not routed
+ * thru the PIC. PIC ack not needed.
  *
  * Enable and disable done using standard MSI functions.
  */
 static void xlp_msix_mask_ack(struct irq_data *d)
 {
-	struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+	struct xlp_msi_data *md;
 	int link, msixvec;
+	uint32_t status_reg, bit;
 
 	msixvec = nlm_irq_msixvec(d->irq);
-	link = nlm_irq_msixlink(d->irq);
+	link = nlm_irq_msixlink(msixvec);
 	mask_msi_irq(d);
+	md = irq_data_get_irq_handler_data(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec);
+	if (cpu_is_xlp9xx()) {
+		status_reg = PCIE_9XX_MSIX_STATUSX(link);
+		bit = msixvec % XLP_MSIXVEC_PER_LINK;
+	} else {
+		status_reg = PCIE_MSIX_STATUS;
+		bit = msixvec;
+	}
+	nlm_write_reg(md->lnkbase, status_reg, 1u << bit);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec));
+	if (!cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_IRT_PCIE_MSIX_INDEX(msixvec));
 }
 
 static struct irq_chip xlp_msix_chip = {
@@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
 {
 	u32 val;
 
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
 
 	spin_lock_irqsave(&md->msi_lock, flags);
 	if (md->msi_alloc_mask == 0) {
-		/* switch the link IRQ to MSI range */
 		xlp_config_link_msi(lnkbase, lirq, msiaddr);
-		irt = PIC_IRT_PCIE_LINK_INDEX(link);
+		/* switch the link IRQ to MSI range */
+		if (cpu_is_xlp9xx())
+			irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
+		else
+			irt = PIC_IRT_PCIE_LINK_INDEX(link);
 		nlm_setup_pic_irq(node, lirq, lirq, irt);
 		nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
 				 node * nlm_threads_per_node(), 1 /*en */);
@@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 		val |= 0x80000000U;
 		nlm_write_reg(lnkbase, 0x2C, val);
 	}
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 	val |= (1 << 8) | lirq;
 	nlm_write_pci_reg(lnkbase, 0xf, val);
 
-	/* MSI-X addresses */
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8);
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
-					(msixaddr + MSI_ADDR_SZ) >> 8);
+	if (cpu_is_xlp9xx()) {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	} else {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	}
 }
 
 /*
@@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
 
 	xirq += t;
 	msixvec = nlm_irq_msixvec(xirq);
+
 	msg.address_hi = msixaddr >> 32;
 	msg.address_lo = msixaddr & 0xffffffff;
 	msg.data = 0xc00 | msixvec;
@@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 {
 	struct nlm_soc_info *nodep;
 	struct xlp_msi_data *md;
-	int irq, i, irt, msixvec;
+	int irq, i, irt, msixvec, val;
 
 	pr_info("[%d %d] Init node PCI IRT\n", node, link);
 	nodep = nlm_get_node(node);
@@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 		irq_set_handler_data(i, md);
 	}
 
-	for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) {
-		/* Initialize MSI-X irts to generate one interrupt per link */
-		msixvec = link * XLP_MSIXVEC_PER_LINK + i;
-		irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
-		nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link),
-			node * nlm_threads_per_node(), 1 /* enable */);
+	for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
+		if (cpu_is_xlp9xx()) {
+			val = ((node * nlm_threads_per_node()) << 7 |
+				PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
+			nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
+					(link * XLP_MSIXVEC_PER_LINK)), val);
+		} else {
+			/* Initialize MSI-X irts to generate one interrupt
+			 * per link
+			 */
+			msixvec = link * XLP_MSIXVEC_PER_LINK + i;
+			irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
+			nlm_pic_init_irt(nodep->picbase, irt,
+					PIC_PCIE_MSIX_IRQ(link),
+					node * nlm_threads_per_node(), 1);
+		}
 
 		/* Initialize MSI-X extended irq space for the link  */
 		irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
 		irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
 		irq_set_handler_data(irq, md);
 	}
-
 }
 
 void nlm_dispatch_msi(int node, int lirq)
@@ -462,7 +540,11 @@ void nlm_dispatch_msi(int node, int lirq)
 	link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE;
 	irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
 	md = irq_get_handler_data(irqbase);
-	status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
+	if (cpu_is_xlp9xx())
+		status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
+						md->msi_enabled_mask;
+	else
+		status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
 						md->msi_enabled_mask;
 	while (status) {
 		i = __ffs(status);
@@ -480,10 +562,14 @@ void nlm_dispatch_msix(int node, int lirq)
 	link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
 	irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
 	md = irq_get_handler_data(irqbase);
-	status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
+	if (cpu_is_xlp9xx())
+		status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
+	else
+		status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
 
 	/* narrow it down to the MSI-x vectors for our link */
-	status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
+	if (!cpu_is_xlp9xx())
+		status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
 			((1 << XLP_MSIXVEC_PER_LINK) - 1);
 
 	while (status) {
-- 
1.7.9.5

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

* [PATCH v2 15/17] MIPS: Add MSI support for XLP9XX
@ 2014-05-09 11:05     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:05 UTC (permalink / raw)
  To: g, linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

In XLP9XX, the interrupt routing table for MSI-X has been moved to the
PCIe controller's config space from PIC. There are also 32 MSI-X
interrupts available per link on XLP9XX.

Update XLP MSI/MSI-X code to handle this.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Added correct MSI ack register for 9XX]

 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |   14 ++
 arch/mips/include/asm/netlogic/xlp-hal/pic.h    |    4 +
 arch/mips/include/asm/netlogic/xlp-hal/xlp.h    |    5 +-
 arch/mips/pci/msi-xlp.c                         |  184 +++++++++++++++++------
 4 files changed, 156 insertions(+), 51 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index d4deb87..91540f4 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -69,6 +69,20 @@
 #define PCIE_9XX_BYTE_SWAP_IO_BASE	0x25e
 #define PCIE_9XX_BYTE_SWAP_IO_LIM	0x25f
 
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE	0x264
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT	0x265
+#define PCIE_9XX_MSI_STATUS		0x283
+#define PCIE_9XX_MSI_EN			0x284
+/* 128 MSIX vectors available in 9xx */
+#define PCIE_9XX_MSIX_STATUS0		0x286
+#define PCIE_9XX_MSIX_STATUSX(n)	(n + 0x286)
+#define PCIE_9XX_MSIX_VEC		0x296
+#define PCIE_9XX_MSIX_VECX(n)		(n + 0x296)
+#define PCIE_9XX_INT_STATUS0		0x397
+#define PCIE_9XX_INT_STATUS1		0x398
+#define PCIE_9XX_INT_EN0		0x399
+#define PCIE_9XX_INT_EN1		0x39a
+
 /* other */
 #define PCIE_NLINKS			4
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index f10bf3b..41cefe9 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -199,6 +199,10 @@
 #define PIC_IRT_PCIE_LINK_3_INDEX	81
 #define PIC_IRT_PCIE_LINK_INDEX(num)	((num) + PIC_IRT_PCIE_LINK_0_INDEX)
 
+#define PIC_9XX_IRT_PCIE_LINK_0_INDEX	191
+#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \
+				((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX)
+
 #define PIC_CLOCK_TIMER			7
 
 #if !defined(LOCORE) && !defined(__ASSEMBLY__)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 8f8afe0..c0b2a80 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -70,8 +70,9 @@
 #define PIC_PCIE_MSIX_IRQ_BASE		48	/* 48 - 51 MSI-X IRQ */
 #define PIC_PCIE_MSIX_IRQ(i)		(48 + (i))
 
-#define NLM_MSIX_VEC_BASE		96	/* 96 - 127 - MSIX mapped */
-#define NLM_MSI_VEC_BASE		128	/* 128 -255 - MSI mapped */
+/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */
+#define NLM_MSIX_VEC_BASE		96	/* 96 - 223 - MSIX mapped */
+#define NLM_MSI_VEC_BASE		224	/* 224 -351 - MSI mapped */
 
 #define NLM_PIC_INDIRECT_VEC_BASE	512
 #define NLM_GPIO_VEC_BASE		768
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index afd8405..1ef3ed6 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -56,8 +56,8 @@
 #include <asm/netlogic/xlp-hal/bridge.h>
 
 #define XLP_MSIVEC_PER_LINK	32
-#define XLP_MSIXVEC_TOTAL	32
-#define XLP_MSIXVEC_PER_LINK	8
+#define XLP_MSIXVEC_TOTAL	(cpu_is_xlp9xx() ? 128 : 32)
+#define XLP_MSIXVEC_PER_LINK	(cpu_is_xlp9xx() ? 32 : 8)
 
 /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */
 static inline int nlm_link_msiirq(int link, int msivec)
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec)
 	return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msivec(int irq)
 {
-	return irq % XLP_MSIVEC_PER_LINK;
+	return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK;
 }
 
+/* get the link from the irq number */
 static inline int nlm_irq_msilink(int irq)
 {
-	return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) /
-						XLP_MSIVEC_PER_LINK;
+	int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS;
+
+	return ((irq - NLM_MSI_VEC_BASE) % total_msivec) /
+		XLP_MSIVEC_PER_LINK;
 }
 
 /*
- * Only 32 MSI-X vectors are possible because there are only 32 PIC
- * interrupts for MSI. We split them statically and use 8 MSI-X vectors
- * per link - this keeps the allocation and lookup simple.
+ * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because
+ * there are only 32 PIC interrupts for MSI. We split them statically
+ * and use 8 MSI-X vectors per link - this keeps the allocation and
+ * lookup simple.
+ * On XLP 9xx, there are 32 vectors per link, and the interrupts are
+ * not routed thru PIC, so we can use all 128 MSI-X vectors.
  */
 static inline int nlm_link_msixirq(int link, int bit)
 {
 	return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit;
 }
 
+/* get the link MSI vector from irq number */
 static inline int nlm_irq_msixvec(int irq)
 {
-	return irq % XLP_MSIXVEC_TOTAL;  /* works when given xirq */
+	return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL;
 }
 
-static inline int nlm_irq_msixlink(int irq)
+/* get the link from MSIX vec */
+static inline int nlm_irq_msixlink(int msixvec)
 {
-	return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK;
+	return msixvec / XLP_MSIXVEC_PER_LINK;
 }
 
 /*
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask |= 1u << vec;
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d)
 	vec = nlm_irq_msivec(d->irq);
 	spin_lock_irqsave(&md->msi_lock, flags);
 	md->msi_enabled_mask &= ~(1u << vec);
-	nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+				md->msi_enabled_mask);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
 	spin_unlock_irqrestore(&md->msi_lock, flags);
 }
 
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d)
 	xlp_msi_disable(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
+	if (cpu_is_xlp9xx())
+		nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec);
+	else
+		nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
+	if (cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_9XX_IRT_PCIE_LINK_INDEX(link));
+	else
+		nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
 }
 
 static struct irq_chip xlp_msi_chip = {
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = {
 };
 
 /*
- * The MSI-X interrupt handling is different from MSI, there are 32
- * MSI-X interrupts generated by the PIC and each of these correspond
- * to a MSI-X vector (0-31) that can be assigned.
+ * XLP8XX/4XX/3XX/2XX:
+ * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X
+ * interrupts generated by the PIC and each of these correspond to a MSI-X
+ * vector (0-31) that can be assigned.
  *
- * We divide the MSI-X vectors to 8 per link and do a per-link
- * allocation
+ * We divide the MSI-X vectors to 8 per link and do a per-link allocation
+ *
+ * XLP9XX:
+ * 32 MSI-X vectors are available per link, and the interrupts are not routed
+ * thru the PIC. PIC ack not needed.
  *
  * Enable and disable done using standard MSI functions.
  */
 static void xlp_msix_mask_ack(struct irq_data *d)
 {
-	struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+	struct xlp_msi_data *md;
 	int link, msixvec;
+	uint32_t status_reg, bit;
 
 	msixvec = nlm_irq_msixvec(d->irq);
-	link = nlm_irq_msixlink(d->irq);
+	link = nlm_irq_msixlink(msixvec);
 	mask_msi_irq(d);
+	md = irq_data_get_irq_handler_data(d);
 
 	/* Ack MSI on bridge */
-	nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec);
+	if (cpu_is_xlp9xx()) {
+		status_reg = PCIE_9XX_MSIX_STATUSX(link);
+		bit = msixvec % XLP_MSIXVEC_PER_LINK;
+	} else {
+		status_reg = PCIE_MSIX_STATUS;
+		bit = msixvec;
+	}
+	nlm_write_reg(md->lnkbase, status_reg, 1u << bit);
 
 	/* Ack at eirr and PIC */
 	ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link));
-	nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec));
+	if (!cpu_is_xlp9xx())
+		nlm_pic_ack(md->node->picbase,
+				PIC_IRT_PCIE_MSIX_INDEX(msixvec));
 }
 
 static struct irq_chip xlp_msix_chip = {
@@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
 {
 	u32 val;
 
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
 
 	spin_lock_irqsave(&md->msi_lock, flags);
 	if (md->msi_alloc_mask == 0) {
-		/* switch the link IRQ to MSI range */
 		xlp_config_link_msi(lnkbase, lirq, msiaddr);
-		irt = PIC_IRT_PCIE_LINK_INDEX(link);
+		/* switch the link IRQ to MSI range */
+		if (cpu_is_xlp9xx())
+			irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
+		else
+			irt = PIC_IRT_PCIE_LINK_INDEX(link);
 		nlm_setup_pic_irq(node, lirq, lirq, irt);
 		nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
 				 node * nlm_threads_per_node(), 1 /*en */);
@@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 		val |= 0x80000000U;
 		nlm_write_reg(lnkbase, 0x2C, val);
 	}
-	val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
-	if ((val & 0x200) == 0) {
-		val |= 0x200;		/* MSI Interrupt enable */
-		nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+
+	if (cpu_is_xlp9xx()) {
+		val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+		}
+	} else {
+		val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+		if ((val & 0x200) == 0) {
+			val |= 0x200;		/* MSI Interrupt enable */
+			nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+		}
 	}
 
 	val = nlm_read_reg(lnkbase, 0x1);	/* CMD */
@@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
 	val |= (1 << 8) | lirq;
 	nlm_write_pci_reg(lnkbase, 0xf, val);
 
-	/* MSI-X addresses */
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8);
-	nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
-					(msixaddr + MSI_ADDR_SZ) >> 8);
+	if (cpu_is_xlp9xx()) {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	} else {
+		/* MSI-X addresses */
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
+				msixaddr >> 8);
+		nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
+				(msixaddr + MSI_ADDR_SZ) >> 8);
+	}
 }
 
 /*
@@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
 
 	xirq += t;
 	msixvec = nlm_irq_msixvec(xirq);
+
 	msg.address_hi = msixaddr >> 32;
 	msg.address_lo = msixaddr & 0xffffffff;
 	msg.data = 0xc00 | msixvec;
@@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 {
 	struct nlm_soc_info *nodep;
 	struct xlp_msi_data *md;
-	int irq, i, irt, msixvec;
+	int irq, i, irt, msixvec, val;
 
 	pr_info("[%d %d] Init node PCI IRT\n", node, link);
 	nodep = nlm_get_node(node);
@@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link)
 		irq_set_handler_data(i, md);
 	}
 
-	for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) {
-		/* Initialize MSI-X irts to generate one interrupt per link */
-		msixvec = link * XLP_MSIXVEC_PER_LINK + i;
-		irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
-		nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link),
-			node * nlm_threads_per_node(), 1 /* enable */);
+	for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
+		if (cpu_is_xlp9xx()) {
+			val = ((node * nlm_threads_per_node()) << 7 |
+				PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
+			nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
+					(link * XLP_MSIXVEC_PER_LINK)), val);
+		} else {
+			/* Initialize MSI-X irts to generate one interrupt
+			 * per link
+			 */
+			msixvec = link * XLP_MSIXVEC_PER_LINK + i;
+			irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
+			nlm_pic_init_irt(nodep->picbase, irt,
+					PIC_PCIE_MSIX_IRQ(link),
+					node * nlm_threads_per_node(), 1);
+		}
 
 		/* Initialize MSI-X extended irq space for the link  */
 		irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
 		irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
 		irq_set_handler_data(irq, md);
 	}
-
 }
 
 void nlm_dispatch_msi(int node, int lirq)
@@ -462,7 +540,11 @@ void nlm_dispatch_msi(int node, int lirq)
 	link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE;
 	irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
 	md = irq_get_handler_data(irqbase);
-	status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
+	if (cpu_is_xlp9xx())
+		status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
+						md->msi_enabled_mask;
+	else
+		status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
 						md->msi_enabled_mask;
 	while (status) {
 		i = __ffs(status);
@@ -480,10 +562,14 @@ void nlm_dispatch_msix(int node, int lirq)
 	link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
 	irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
 	md = irq_get_handler_data(irqbase);
-	status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
+	if (cpu_is_xlp9xx())
+		status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
+	else
+		status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
 
 	/* narrow it down to the MSI-x vectors for our link */
-	status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
+	if (!cpu_is_xlp9xx())
+		status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
 			((1 << XLP_MSIXVEC_PER_LINK) - 1);
 
 	while (status) {
-- 
1.7.9.5

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

* [PATCH v2 17/17] MIPS: Netlogic: XLP9XX on-chip SATA support
@ 2014-05-09 11:06     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:06 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

The XLP9XX SoC has an on-chip SATA controller with two ports. Add
ahci-init-xlp2.c to initialize the controller, setup the glue logic
registers, fixup PCI quirks and setup interrupt ack logic.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Change '#if 0' to use a variable, and fix code which was commented
 with the macro]

 arch/mips/netlogic/xlp/Makefile         |    1 +
 arch/mips/netlogic/xlp/ahci-init-xlp2.c |  377 +++++++++++++++++++++++++++++++
 2 files changed, 378 insertions(+)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init-xlp2.c

diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index 0cb53af..be358a8 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
 obj-$(CONFIG_USB)		+= usb-init-xlp2.o
 obj-$(CONFIG_SATA_AHCI)		+= ahci-init.o
+obj-$(CONFIG_SATA_AHCI)		+= ahci-init-xlp2.o
diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
new file mode 100644
index 0000000..c83dbf3
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/nodemask.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/mips-extns.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+
+#define SATA_CTL		0x0
+#define SATA_STATUS		0x1 /* Status Reg */
+#define SATA_INT		0x2 /* Interrupt Reg */
+#define SATA_INT_MASK		0x3 /* Interrupt Mask Reg */
+#define SATA_BIU_TIMEOUT	0x4
+#define AXIWRSPERRLOG		0x5
+#define AXIRDSPERRLOG		0x6
+#define BiuTimeoutLow		0x7
+#define BiuTimeoutHi		0x8
+#define BiuSlvErLow		0x9
+#define BiuSlvErHi		0xa
+#define IO_CONFIG_SWAP_DIS	0xb
+#define CR_REG_TIMER		0xc
+#define CORE_ID			0xd
+#define AXI_SLAVE_OPT1		0xe
+#define PHY_MEM_ACCESS		0xf
+#define PHY0_CNTRL		0x10
+#define PHY0_STAT		0x11
+#define PHY0_RX_ALIGN		0x12
+#define PHY0_RX_EQ_LO		0x13
+#define PHY0_RX_EQ_HI		0x14
+#define PHY0_BIST_LOOP		0x15
+#define PHY1_CNTRL		0x16
+#define PHY1_STAT		0x17
+#define PHY1_RX_ALIGN		0x18
+#define PHY1_RX_EQ_LO		0x19
+#define PHY1_RX_EQ_HI		0x1a
+#define PHY1_BIST_LOOP		0x1b
+#define RdExBase		0x1c
+#define RdExLimit		0x1d
+#define CacheAllocBase		0x1e
+#define CacheAllocLimit		0x1f
+#define BiuSlaveCmdGstNum	0x20
+
+/*SATA_CTL Bits */
+#define SATA_RST_N		BIT(0)  /* Active low reset sata_core phy */
+#define SataCtlReserve0		BIT(1)
+#define M_CSYSREQ		BIT(2)  /* AXI master low power, not used */
+#define S_CSYSREQ		BIT(3)  /* AXI slave low power, not used */
+#define P0_CP_DET		BIT(8)  /* Reserved, bring in from pad */
+#define P0_MP_SW		BIT(9)  /* Mech Switch */
+#define P0_DISABLE		BIT(10) /* disable p0 */
+#define P0_ACT_LED_EN		BIT(11) /* Active LED enable */
+#define P0_IRST_HARD_SYNTH	BIT(12) /* PHY hard synth reset */
+#define P0_IRST_HARD_TXRX	BIT(13) /* PHY lane hard reset */
+#define P0_IRST_POR		BIT(14) /* PHY power on reset*/
+#define P0_IPDTXL		BIT(15) /* PHY Tx lane dis/power down */
+#define P0_IPDRXL		BIT(16) /* PHY Rx lane dis/power down */
+#define P0_IPDIPDMSYNTH		BIT(17) /* PHY synthesizer dis/porwer down */
+#define P0_CP_POD_EN		BIT(18) /* CP_POD enable */
+#define P0_AT_BYPASS		BIT(19) /* P0 address translation by pass */
+#define P1_CP_DET		BIT(20) /* Reserved,Cold Detect */
+#define P1_MP_SW		BIT(21) /* Mech Switch */
+#define P1_DISABLE		BIT(22) /* disable p1 */
+#define P1_ACT_LED_EN		BIT(23) /* Active LED enable */
+#define P1_IRST_HARD_SYNTH	BIT(24) /* PHY hard synth reset */
+#define P1_IRST_HARD_TXRX	BIT(25) /* PHY lane hard reset */
+#define P1_IRST_POR		BIT(26) /* PHY power on reset*/
+#define P1_IPDTXL		BIT(27) /* PHY Tx lane dis/porwer down */
+#define P1_IPDRXL		BIT(28) /* PHY Rx lane dis/porwer down */
+#define P1_IPDIPDMSYNTH		BIT(29) /* PHY synthesizer dis/porwer down */
+#define P1_CP_POD_EN		BIT(30)
+#define P1_AT_BYPASS		BIT(31) /* P1 address translation by pass */
+
+/* Status register */
+#define M_CACTIVE		BIT(0)  /* m_cactive, not used */
+#define S_CACTIVE		BIT(1)  /* s_cactive, not used */
+#define P0_PHY_READY		BIT(8)  /* phy is ready */
+#define P0_CP_POD		BIT(9)  /* Cold PowerOn */
+#define P0_SLUMBER		BIT(10) /* power mode slumber */
+#define P0_PATIAL		BIT(11) /* power mode patial */
+#define P0_PHY_SIG_DET		BIT(12) /* phy dignal detect */
+#define P0_PHY_CALI		BIT(13) /* phy calibration done */
+#define P1_PHY_READY		BIT(16) /* phy is ready */
+#define P1_CP_POD		BIT(17) /* Cold PowerOn */
+#define P1_SLUMBER		BIT(18) /* power mode slumber */
+#define P1_PATIAL		BIT(19) /* power mode patial */
+#define P1_PHY_SIG_DET		BIT(20) /* phy dignal detect */
+#define P1_PHY_CALI		BIT(21) /* phy calibration done */
+
+/* SATA CR_REG_TIMER bits */
+#define CR_TIME_SCALE		(0x1000 << 0)
+
+/* SATA PHY specific registers start and end address */
+#define RXCDRCALFOSC0		0x0065
+#define CALDUTY			0x006e
+#define RXDPIF			0x8065
+#define PPMDRIFTMAX_HI		0x80A4
+
+#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node)	\
+		nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
+#define nlm_get_sata_regbase(node)	\
+		(nlm_get_sata_pcibase(node) + 0x100)
+
+/* SATA PHY config for register block 1 0x0065 .. 0x006e */
+static const u8 sata_phy_config1[]  = {
+	0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
+};
+
+/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
+static const u8 sata_phy_config2[]  = {
+	0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
+	0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
+	0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
+	0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
+	0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
+	0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
+	0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
+};
+
+const int sata_phy_debug = 0;	/* set to verify PHY writes */
+
+static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
+{
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(1u << 31) | (physel << 24) | (data << 16) | addr);
+	udelay(850);
+}
+
+static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
+{
+	u32 val;
+
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(0 << 31) | (physel << 24) | (0 << 16) | addr);
+	udelay(850);
+	val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
+	return (val >> 16) & 0xff;
+}
+
+static void config_sata_phy(u64 regbase)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
+	}
+}
+
+static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
+{
+	u8 data;
+
+	data = read_phy_reg(regbase, addr, physel);
+	pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
+		addr, physel, data, data == xdata ? "TRUE" : "FALSE");
+}
+
+static void verify_sata_phy_config(u64 regbase)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			check_phy_register(regbase, reg, port,
+						sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			check_phy_register(regbase, reg, port,
+						sata_phy_config2[i]);
+	}
+}
+
+static void nlm_sata_firmware_init(int node)
+{
+	u32 reg_val;
+	u64 regbase;
+	int n;
+
+	pr_info("Initializing XLP9XX On-chip AHCI...\n");
+	regbase = nlm_get_sata_regbase(node);
+
+	/* Reset port0 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+
+	/* port1 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+	udelay(300);
+
+	/* Set PHY */
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	udelay(1000);
+
+	/* setup PHY */
+	config_sata_phy(regbase);
+	if (sata_phy_debug)
+		verify_sata_phy_config(regbase);
+
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	udelay(300);
+
+	/* Override reset in serial PHY mode */
+	sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
+	/* Set reset SATA */
+	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
+	sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
+
+	pr_debug("Waiting for PHYs to come up.\n");
+	n = 10000;
+	do {
+		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+		if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
+			break;
+		udelay(10);
+	} while (--n > 0);
+
+	if (reg_val  & P0_PHY_READY)
+		pr_info("PHY0 is up.\n");
+	else
+		pr_info("PHY0 is down.\n");
+	if (reg_val  & P1_PHY_READY)
+		pr_info("PHY1 is up.\n");
+	else
+		pr_info("PHY1 is down.\n");
+
+	pr_info("XLP AHCI Init Done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+	int node;
+
+	if (!cpu_is_xlp9xx())
+		return 0;
+	for (node = 0; node < NLM_NR_NODES; node++)
+		if (nlm_node_present(node))
+			nlm_sata_firmware_init(node);
+	return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+	u64 regbase;
+	u32 val;
+	int node;
+
+	node = data->irq / NLM_IRQS_PER_NODE;
+	regbase = nlm_get_sata_regbase(node);
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+	dev->resource[5] = dev->resource[0];
+	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+	u32 val;
+	u64 regbase;
+	int node;
+
+	/* Find end bridge function to find node */
+	node = xlp_socdev_to_node(dev);
+	regbase = nlm_get_sata_regbase(node);
+
+	/* clear pending interrupts and then enable them */
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+
+	/* Enable only the core interrupt */
+	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+	dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
+	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_bar);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_final);
-- 
1.7.9.5

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

* [PATCH v2 17/17] MIPS: Netlogic: XLP9XX on-chip SATA support
@ 2014-05-09 11:06     ` Jayachandran C
  0 siblings, 0 replies; 49+ messages in thread
From: Jayachandran C @ 2014-05-09 11:06 UTC (permalink / raw)
  To: linux-mips; +Cc: Ganesan Ramalingam, ralf, Jayachandran C

From: Ganesan Ramalingam <ganesanr@broadcom.com>

The XLP9XX SoC has an on-chip SATA controller with two ports. Add
ahci-init-xlp2.c to initialize the controller, setup the glue logic
registers, fixup PCI quirks and setup interrupt ack logic.

Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
[v2: Change '#if 0' to use a variable, and fix code which was commented
 with the macro]

 arch/mips/netlogic/xlp/Makefile         |    1 +
 arch/mips/netlogic/xlp/ahci-init-xlp2.c |  377 +++++++++++++++++++++++++++++++
 2 files changed, 378 insertions(+)
 create mode 100644 arch/mips/netlogic/xlp/ahci-init-xlp2.c

diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index 0cb53af..be358a8 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SMP)		+= wakeup.o
 obj-$(CONFIG_USB)		+= usb-init.o
 obj-$(CONFIG_USB)		+= usb-init-xlp2.o
 obj-$(CONFIG_SATA_AHCI)		+= ahci-init.o
+obj-$(CONFIG_SATA_AHCI)		+= ahci-init-xlp2.o
diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
new file mode 100644
index 0000000..c83dbf3
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/nodemask.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/mips-extns.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+
+#define SATA_CTL		0x0
+#define SATA_STATUS		0x1 /* Status Reg */
+#define SATA_INT		0x2 /* Interrupt Reg */
+#define SATA_INT_MASK		0x3 /* Interrupt Mask Reg */
+#define SATA_BIU_TIMEOUT	0x4
+#define AXIWRSPERRLOG		0x5
+#define AXIRDSPERRLOG		0x6
+#define BiuTimeoutLow		0x7
+#define BiuTimeoutHi		0x8
+#define BiuSlvErLow		0x9
+#define BiuSlvErHi		0xa
+#define IO_CONFIG_SWAP_DIS	0xb
+#define CR_REG_TIMER		0xc
+#define CORE_ID			0xd
+#define AXI_SLAVE_OPT1		0xe
+#define PHY_MEM_ACCESS		0xf
+#define PHY0_CNTRL		0x10
+#define PHY0_STAT		0x11
+#define PHY0_RX_ALIGN		0x12
+#define PHY0_RX_EQ_LO		0x13
+#define PHY0_RX_EQ_HI		0x14
+#define PHY0_BIST_LOOP		0x15
+#define PHY1_CNTRL		0x16
+#define PHY1_STAT		0x17
+#define PHY1_RX_ALIGN		0x18
+#define PHY1_RX_EQ_LO		0x19
+#define PHY1_RX_EQ_HI		0x1a
+#define PHY1_BIST_LOOP		0x1b
+#define RdExBase		0x1c
+#define RdExLimit		0x1d
+#define CacheAllocBase		0x1e
+#define CacheAllocLimit		0x1f
+#define BiuSlaveCmdGstNum	0x20
+
+/*SATA_CTL Bits */
+#define SATA_RST_N		BIT(0)  /* Active low reset sata_core phy */
+#define SataCtlReserve0		BIT(1)
+#define M_CSYSREQ		BIT(2)  /* AXI master low power, not used */
+#define S_CSYSREQ		BIT(3)  /* AXI slave low power, not used */
+#define P0_CP_DET		BIT(8)  /* Reserved, bring in from pad */
+#define P0_MP_SW		BIT(9)  /* Mech Switch */
+#define P0_DISABLE		BIT(10) /* disable p0 */
+#define P0_ACT_LED_EN		BIT(11) /* Active LED enable */
+#define P0_IRST_HARD_SYNTH	BIT(12) /* PHY hard synth reset */
+#define P0_IRST_HARD_TXRX	BIT(13) /* PHY lane hard reset */
+#define P0_IRST_POR		BIT(14) /* PHY power on reset*/
+#define P0_IPDTXL		BIT(15) /* PHY Tx lane dis/power down */
+#define P0_IPDRXL		BIT(16) /* PHY Rx lane dis/power down */
+#define P0_IPDIPDMSYNTH		BIT(17) /* PHY synthesizer dis/porwer down */
+#define P0_CP_POD_EN		BIT(18) /* CP_POD enable */
+#define P0_AT_BYPASS		BIT(19) /* P0 address translation by pass */
+#define P1_CP_DET		BIT(20) /* Reserved,Cold Detect */
+#define P1_MP_SW		BIT(21) /* Mech Switch */
+#define P1_DISABLE		BIT(22) /* disable p1 */
+#define P1_ACT_LED_EN		BIT(23) /* Active LED enable */
+#define P1_IRST_HARD_SYNTH	BIT(24) /* PHY hard synth reset */
+#define P1_IRST_HARD_TXRX	BIT(25) /* PHY lane hard reset */
+#define P1_IRST_POR		BIT(26) /* PHY power on reset*/
+#define P1_IPDTXL		BIT(27) /* PHY Tx lane dis/porwer down */
+#define P1_IPDRXL		BIT(28) /* PHY Rx lane dis/porwer down */
+#define P1_IPDIPDMSYNTH		BIT(29) /* PHY synthesizer dis/porwer down */
+#define P1_CP_POD_EN		BIT(30)
+#define P1_AT_BYPASS		BIT(31) /* P1 address translation by pass */
+
+/* Status register */
+#define M_CACTIVE		BIT(0)  /* m_cactive, not used */
+#define S_CACTIVE		BIT(1)  /* s_cactive, not used */
+#define P0_PHY_READY		BIT(8)  /* phy is ready */
+#define P0_CP_POD		BIT(9)  /* Cold PowerOn */
+#define P0_SLUMBER		BIT(10) /* power mode slumber */
+#define P0_PATIAL		BIT(11) /* power mode patial */
+#define P0_PHY_SIG_DET		BIT(12) /* phy dignal detect */
+#define P0_PHY_CALI		BIT(13) /* phy calibration done */
+#define P1_PHY_READY		BIT(16) /* phy is ready */
+#define P1_CP_POD		BIT(17) /* Cold PowerOn */
+#define P1_SLUMBER		BIT(18) /* power mode slumber */
+#define P1_PATIAL		BIT(19) /* power mode patial */
+#define P1_PHY_SIG_DET		BIT(20) /* phy dignal detect */
+#define P1_PHY_CALI		BIT(21) /* phy calibration done */
+
+/* SATA CR_REG_TIMER bits */
+#define CR_TIME_SCALE		(0x1000 << 0)
+
+/* SATA PHY specific registers start and end address */
+#define RXCDRCALFOSC0		0x0065
+#define CALDUTY			0x006e
+#define RXDPIF			0x8065
+#define PPMDRIFTMAX_HI		0x80A4
+
+#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node)	\
+		nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
+#define nlm_get_sata_regbase(node)	\
+		(nlm_get_sata_pcibase(node) + 0x100)
+
+/* SATA PHY config for register block 1 0x0065 .. 0x006e */
+static const u8 sata_phy_config1[]  = {
+	0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
+};
+
+/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
+static const u8 sata_phy_config2[]  = {
+	0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
+	0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
+	0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
+	0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
+	0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
+	0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
+	0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
+};
+
+const int sata_phy_debug = 0;	/* set to verify PHY writes */
+
+static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+	u32 reg_val;
+
+	reg_val = nlm_read_sata_reg(regbase, off);
+	nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
+{
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(1u << 31) | (physel << 24) | (data << 16) | addr);
+	udelay(850);
+}
+
+static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
+{
+	u32 val;
+
+	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+		(0 << 31) | (physel << 24) | (0 << 16) | addr);
+	udelay(850);
+	val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
+	return (val >> 16) & 0xff;
+}
+
+static void config_sata_phy(u64 regbase)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
+	}
+}
+
+static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
+{
+	u8 data;
+
+	data = read_phy_reg(regbase, addr, physel);
+	pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
+		addr, physel, data, data == xdata ? "TRUE" : "FALSE");
+}
+
+static void verify_sata_phy_config(u64 regbase)
+{
+	u32 port, i, reg;
+
+	for (port = 0; port < 2; port++) {
+		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+			check_phy_register(regbase, reg, port,
+						sata_phy_config1[i]);
+
+		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+			check_phy_register(regbase, reg, port,
+						sata_phy_config2[i]);
+	}
+}
+
+static void nlm_sata_firmware_init(int node)
+{
+	u32 reg_val;
+	u64 regbase;
+	int n;
+
+	pr_info("Initializing XLP9XX On-chip AHCI...\n");
+	regbase = nlm_get_sata_regbase(node);
+
+	/* Reset port0 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+
+	/* port1 */
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+	udelay(300);
+
+	/* Set PHY */
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+	udelay(1000);
+
+	/* setup PHY */
+	config_sata_phy(regbase);
+	if (sata_phy_debug)
+		verify_sata_phy_config(regbase);
+
+	udelay(1000);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+	udelay(300);
+
+	/* Override reset in serial PHY mode */
+	sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
+	/* Set reset SATA */
+	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+	sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
+	sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
+
+	pr_debug("Waiting for PHYs to come up.\n");
+	n = 10000;
+	do {
+		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+		if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
+			break;
+		udelay(10);
+	} while (--n > 0);
+
+	if (reg_val  & P0_PHY_READY)
+		pr_info("PHY0 is up.\n");
+	else
+		pr_info("PHY0 is down.\n");
+	if (reg_val  & P1_PHY_READY)
+		pr_info("PHY1 is up.\n");
+	else
+		pr_info("PHY1 is down.\n");
+
+	pr_info("XLP AHCI Init Done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+	int node;
+
+	if (!cpu_is_xlp9xx())
+		return 0;
+	for (node = 0; node < NLM_NR_NODES; node++)
+		if (nlm_node_present(node))
+			nlm_sata_firmware_init(node);
+	return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+	u64 regbase;
+	u32 val;
+	int node;
+
+	node = data->irq / NLM_IRQS_PER_NODE;
+	regbase = nlm_get_sata_regbase(node);
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+	dev->resource[5] = dev->resource[0];
+	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+	u32 val;
+	u64 regbase;
+	int node;
+
+	/* Find end bridge function to find node */
+	node = xlp_socdev_to_node(dev);
+	regbase = nlm_get_sata_regbase(node);
+
+	/* clear pending interrupts and then enable them */
+	val = nlm_read_sata_reg(regbase, SATA_INT);
+	sata_set_glue_reg(regbase, SATA_INT, val);
+
+	/* Enable only the core interrupt */
+	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+	dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
+	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_bar);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+		nlm_sata_fixup_final);
-- 
1.7.9.5

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

end of thread, other threads:[~2014-05-09 10:59 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-29 14:37 [PATCH 00/17] Broadcom XLP changes for 3.16 Jayachandran C
2014-04-29 14:37 ` Jayachandran C
2014-04-29 14:37 ` [PATCH 01/17] MIPS: Support upto 256 CPUs Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 02/17] MIPS: Netlogic: Fix uniprocessor compilation Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 03/17] MIPS: Netlogic: Move coremask setup to nlm_node_init Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 04/17] MIPS: Netlogic: Warn on invalid irq Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 05/17] MIPS: Netlogic: Update function to read DRAM BARs Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 06/17] MIPS: Netlogic: Use cpumask_scnprintf for wakup_mask Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-05-09 11:04   ` [PATCH v2 06/17] MIPS: Netlogic: Use cpumask_scnprintf for wakeup_mask Jayachandran C
2014-05-09 11:04     ` Jayachandran C
2014-04-29 14:37 ` [PATCH 07/17] MIPS: Netlogic: Reduce size of reset code Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-05-09 11:05   ` [PATCH v2 " Jayachandran C
2014-05-09 11:05     ` Jayachandran C
2014-04-29 14:37 ` [PATCH 08/17] MIPS: Netlogic: Enable access to more than 64GB Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 09/17] MIPS: Netlogic: IRQ mapping for some more SoC blocks Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-05-09 11:05   ` [PATCH v2 " Jayachandran C
2014-05-09 11:05     ` Jayachandran C
2014-04-29 14:37 ` [PATCH 10/17] MIPS: Netlogic: Use PRID_IMP_MASK macro Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 11/17] MIPS: Netlogic: Fix XLP9XX pic entry Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 17:36   ` Sergei Shtylyov
2014-04-30  9:56     ` Jayachandran C.
2014-04-30  9:56       ` Jayachandran C.
2014-04-29 14:37 ` [PATCH 12/17] MIPS: Netlogic: PIC freq calculation for XLP 9XX/2XX Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 13/17] MIPS: Netlogic: Update XLP9XX/2XX core freq calculation Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 14/17] MIPS: Netlogic: Add support for XLP5XX Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 15/17] MIPS: Add MSI support for XLP9XX Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-05-09 11:05   ` [PATCH v2 " Jayachandran C
2014-05-09 11:05     ` Jayachandran C
2014-04-29 14:37 ` [PATCH 16/17] MIPS: Netlogic: Support for XLP3XX on-chip SATA Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-04-29 14:37 ` [PATCH 17/17] MIPS: Netlogic: XLP9XX on-chip SATA support Jayachandran C
2014-04-29 14:37   ` Jayachandran C
2014-05-09 11:06   ` [PATCH v2 " Jayachandran C
2014-05-09 11:06     ` Jayachandran C

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.