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