Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm Add support for Armada XP PIC.



details:   https://anonhg.NetBSD.org/src/rev/7b9d0a12ff95
branches:  trunk
changeset: 787025:7b9d0a12ff95
user:      rkujawa <rkujawa%NetBSD.org@localhost>
date:      Wed May 29 22:35:34 2013 +0000

description:
Add support for Armada XP PIC.

Obtained from Marvell, Semihalf.

diffstat:

 sys/arch/arm/marvell/armadaxp.c      |  399 +++++++++++++++++++++++++++++++++++
 sys/arch/arm/marvell/files.marvell   |    3 +-
 sys/arch/arm/pic/armadaxp_splfuncs.c |  156 +++++++++++++
 sys/arch/arm/pic/files.pic           |    7 +-
 4 files changed, 561 insertions(+), 4 deletions(-)

diffs (truncated from 598 to 300 lines):

diff -r 2bf1e6000ba4 -r 7b9d0a12ff95 sys/arch/arm/marvell/armadaxp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/marvell/armadaxp.c   Wed May 29 22:35:34 2013 +0000
@@ -0,0 +1,399 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+Developed by Semihalf
+
+********************************************************************************
+Marvell BSD License
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+            this list of conditions and the following disclaimer.
+
+    *   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.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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 <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: armadaxp.c,v 1.1 2013/05/29 22:35:34 rkujawa Exp $");
+
+#define _INTR_PRIVATE
+
+#include "opt_mvsoc.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <machine/intr.h>
+
+#include <arm/pic/picvar.h>
+#include <arm/pic/picvar.h>
+
+#include <arm/armreg.h>
+#include <arm/cpu.h>
+#include <arm/cpufunc.h>
+
+#include <arm/marvell/mvsocreg.h>
+#include <arm/marvell/mvsocvar.h>
+#include <evbarm/armadaxp/armadaxpreg.h>
+
+#include <evbarm/marvell/marvellreg.h>
+#include <dev/marvell/marvellreg.h>
+
+#define EXTRACT_CPU_FREQ_FIELD(sar)    (((0x01 & (sar >> 52)) << 3) | \
+                                           (0x07 & (sar >> 21)))
+#define EXTRACT_FAB_FREQ_FIELD(sar)    (((0x01 & (sar >> 51)) << 4) | \
+                                           (0x0F & (sar >> 24)))
+
+#define        MPIC_WRITE(reg, val)            (bus_space_write_4(&mvsoc_bs_tag, \
+                                           mpic_handle, reg, val))
+#define        MPIC_CPU_WRITE(reg, val)        (bus_space_write_4(&mvsoc_bs_tag, \
+                                           mpic_cpu_handle, reg, val))
+
+#define        MPIC_READ(reg)                  (bus_space_read_4(&mvsoc_bs_tag, \
+                                           mpic_handle, reg))
+#define        MPIC_CPU_READ(reg)              (bus_space_read_4(&mvsoc_bs_tag, \
+                                           mpic_cpu_handle, reg))
+
+#define        L2_WRITE(reg, val)              (bus_space_write_4(&mvsoc_bs_tag, \
+                                           l2_handle, reg, val))
+#define        L2_READ(reg)                    (bus_space_read_4(&mvsoc_bs_tag, \
+                                           l2_handle, reg))
+bus_space_handle_t mpic_cpu_handle;
+static bus_space_handle_t mpic_handle, l2_handle;
+int l2cache_state = 0;
+int iocc_state = 0;
+
+extern void (*mvsoc_intr_init)(void);
+static void armadaxp_intr_init(void);
+
+static void armadaxp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
+static void armadaxp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
+static void armadaxp_pic_establish_irq(struct pic_softc *, struct intrsource *);
+
+void armadaxp_handle_irq(void *);
+void armadaxp_io_coherency_init(void);
+int armadaxp_l2_init(void);
+
+struct vco_freq_ratio {
+       uint8_t vco_cpu;        /* VCO to CLK0(CPU) clock ratio */
+       uint8_t vco_l2c;        /* VCO to NB(L2 cache) clock ratio */
+       uint8_t vco_hcl;        /* VCO to HCLK(DDR controller) clock ratio */
+       uint8_t vco_ddr;        /* VCO to DR(DDR memory) clock ratio */
+};
+
+static struct vco_freq_ratio freq_conf_table[] = {
+/*00*/ { 1, 1,  4,  2 },
+/*01*/ { 1, 2,  2,  2 },
+/*02*/ { 2, 2,  6,  3 },
+/*03*/ { 2, 2,  3,  3 },
+/*04*/ { 1, 2,  3,  3 },
+/*05*/ { 1, 2,  4,  2 },
+/*06*/ { 1, 1,  2,  2 },
+/*07*/ { 2, 3,  6,  6 },
+/*08*/ { 2, 3,  5,  5 },
+/*09*/ { 1, 2,  6,  3 },
+/*10*/ { 2, 4, 10,  5 },
+/*11*/ { 1, 3,  6,  6 },
+/*12*/ { 1, 2,  5,  5 },
+/*13*/ { 1, 3,  6,  3 },
+/*14*/ { 1, 2,  5,  5 },
+/*15*/ { 2, 2,  5,  5 },
+/*16*/ { 1, 1,  3,  3 },
+/*17*/ { 2, 5, 10, 10 },
+/*18*/ { 1, 3,  8,  4 },
+/*19*/ { 1, 1,  2,  1 },
+/*20*/ { 2, 3,  6,  3 },
+/*21*/ { 1, 2,  8,  4 },
+/*22*/ { 2, 5, 10,  5 }
+};
+
+static uint16_t        cpu_clock_table[] = {
+    1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000, 600,  667,  800,  1600,
+    2133, 2200, 2400 };
+
+static struct pic_ops armadaxp_picops = {
+       .pic_unblock_irqs = armadaxp_pic_unblock_irqs,
+       .pic_block_irqs = armadaxp_pic_block_irqs,
+       .pic_establish_irq = armadaxp_pic_establish_irq,
+};
+
+static struct pic_softc armadaxp_pic = {
+       .pic_ops = &armadaxp_picops,
+       .pic_name = "armadaxp",
+};
+
+/*
+ * armadaxp_intr_bootstrap:
+ *
+ *     Initialize the rest of the interrupt subsystem, making it
+ *     ready to handle interrupts from devices.
+ */
+void
+armadaxp_intr_bootstrap(void)
+{
+       int i;
+
+       /* Map MPIC base and MPIC percpu base registers */
+       if (bus_space_map(&mvsoc_bs_tag, MARVELL_INTERREGS_PBASE +
+           ARMADAXP_MLMB_MPIC_BASE, 0x500, 0, &mpic_handle) != 0)
+               panic("%s: Could not map MPIC registers", __func__);
+       if (bus_space_map(&mvsoc_bs_tag, MARVELL_INTERREGS_PBASE +
+           ARMADAXP_MLMB_MPIC_CPU_BASE, 0x800, 0, &mpic_cpu_handle) != 0)
+               panic("%s: Could not map MPIC percpu registers", __func__);
+
+       /* Disable all interrupts */
+       for (i = 0; i < 116; i++)
+               MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
+
+       mvsoc_intr_init = armadaxp_intr_init;
+}
+
+static void
+armadaxp_intr_init(void)
+{
+       int ctrl;
+
+       /* Get max interrupts */
+       armadaxp_pic.pic_maxsources =
+           ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
+
+       if (!armadaxp_pic.pic_maxsources)
+               armadaxp_pic.pic_maxsources = 116;
+
+       pic_add(&armadaxp_pic, 0);
+
+       ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
+       /* Enable IRQ prioritization */
+       ctrl |= (1 << 0);
+       MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
+       MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, curcpl() << MPIC_CTP_SHIFT);
+}
+
+static void
+armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
+    uint32_t irq_mask)
+{
+       int n;
+
+       while (irq_mask != 0) {
+               n = ffs(irq_mask) - 1;
+               KASSERT(pic->pic_maxsources >= n + irqbase);
+               MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
+               MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
+               if ((n + irqbase) == 0)
+                       MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
+                           0xffffffff);
+               irq_mask &= ~__BIT(n);
+       }
+}
+
+static void
+armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
+    uint32_t irq_mask)
+{
+       int n;
+
+       while (irq_mask != 0) {
+               n = ffs(irq_mask) - 1;
+               KASSERT(pic->pic_maxsources >= n + irqbase);
+               MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
+               MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
+               irq_mask &= ~__BIT(n);
+       }
+}
+
+static void
+armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
+{
+       int tmp;
+       KASSERT(pic->pic_maxsources >= is->is_irq);
+       tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
+       /* Clear previous priority */
+       tmp &= ~(0xf << MPIC_ISCR_SHIFT);
+       MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
+           tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
+}
+
+void
+armadaxp_handle_irq(void *frame)
+{
+       struct intrsource *is;
+       int irq;
+       u_int irqstate;
+
+       irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
+
+       /* Is it a spurious interrupt ?*/
+       if (irq == 0x3ff)
+               return;
+
+       is = armadaxp_pic.pic_sources[irq];
+       if (is != NULL)  {
+               KASSERT(is->is_ipl > curcpu()->ci_cpl);
+               /* Dispatch irq */
+               irqstate = disable_interrupts(I32_bit);
+               pic_dispatch(is, frame);
+               restore_interrupts(irqstate);
+       }
+#ifdef __HAVE_FAST_SOFTINTS
+       cpu_dosoftints();
+#endif
+}
+
+/*
+ * Clock functions
+ */
+
+void
+armadaxp_getclks(void)
+{
+       uint64_t sar_reg;
+       uint8_t  sar_cpu_freq, sar_fab_freq, array_size;
+
+       if (cputype == CPU_ID_MV88SV584X_V7)
+               mvTclk = 250000000; /* 250 MHz */
+       else
+               mvTclk = 200000000; /* 200 MHz */
+
+       sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
+           read_miscreg(ARMADAXP_MISC_SAR_LO);
+
+       sar_cpu_freq = EXTRACT_CPU_FREQ_FIELD(sar_reg);
+       sar_fab_freq = EXTRACT_FAB_FREQ_FIELD(sar_reg);
+
+       /* Check if CPU frequency field has correct value */
+       array_size = sizeof(cpu_clock_table) / sizeof(cpu_clock_table[0]);
+       if (sar_cpu_freq >= array_size)
+               panic("Reserved value in cpu frequency configuration field: "
+                   "%d", sar_cpu_freq);
+
+       /* Check if fabric frequency field has correct value */
+       array_size = sizeof(freq_conf_table) / sizeof(freq_conf_table[0]);
+       if (sar_fab_freq >= array_size)
+               panic("Reserved value in fabric frequency configuration field: "
+                   "%d", sar_fab_freq);



Home | Main Index | Thread Index | Old Index