Home | History | Annotate | Line # | Download | only in marvell
armadaxp.c revision 1.13
      1  1.13  hsuenaga /*	$NetBSD: armadaxp.c,v 1.13 2015/05/14 05:39:32 hsuenaga Exp $	*/
      2   1.1   rkujawa /*******************************************************************************
      3   1.1   rkujawa Copyright (C) Marvell International Ltd. and its affiliates
      4   1.1   rkujawa 
      5   1.1   rkujawa Developed by Semihalf
      6   1.1   rkujawa 
      7   1.1   rkujawa ********************************************************************************
      8   1.1   rkujawa Marvell BSD License
      9   1.1   rkujawa 
     10   1.1   rkujawa If you received this File from Marvell, you may opt to use, redistribute and/or
     11   1.1   rkujawa modify this File under the following licensing terms.
     12   1.1   rkujawa Redistribution and use in source and binary forms, with or without modification,
     13   1.1   rkujawa are permitted provided that the following conditions are met:
     14   1.1   rkujawa 
     15   1.1   rkujawa     *   Redistributions of source code must retain the above copyright notice,
     16   1.1   rkujawa             this list of conditions and the following disclaimer.
     17   1.1   rkujawa 
     18   1.1   rkujawa     *   Redistributions in binary form must reproduce the above copyright
     19   1.1   rkujawa         notice, this list of conditions and the following disclaimer in the
     20   1.1   rkujawa         documentation and/or other materials provided with the distribution.
     21   1.1   rkujawa 
     22   1.1   rkujawa     *   Neither the name of Marvell nor the names of its contributors may be
     23   1.1   rkujawa         used to endorse or promote products derived from this software without
     24   1.1   rkujawa         specific prior written permission.
     25   1.1   rkujawa 
     26   1.1   rkujawa THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     27   1.1   rkujawa ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     28   1.1   rkujawa WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     29   1.1   rkujawa DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     30   1.1   rkujawa ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     31   1.1   rkujawa (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     32   1.1   rkujawa LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     33   1.1   rkujawa ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     34   1.1   rkujawa (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     35   1.1   rkujawa SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     36   1.1   rkujawa 
     37   1.1   rkujawa *******************************************************************************/
     38   1.1   rkujawa 
     39   1.1   rkujawa #include <sys/cdefs.h>
     40  1.13  hsuenaga __KERNEL_RCSID(0, "$NetBSD: armadaxp.c,v 1.13 2015/05/14 05:39:32 hsuenaga Exp $");
     41   1.1   rkujawa 
     42   1.1   rkujawa #define _INTR_PRIVATE
     43   1.1   rkujawa 
     44   1.1   rkujawa #include "opt_mvsoc.h"
     45   1.1   rkujawa 
     46   1.1   rkujawa #include <sys/param.h>
     47   1.1   rkujawa #include <sys/bus.h>
     48   1.1   rkujawa 
     49   1.1   rkujawa #include <machine/intr.h>
     50   1.1   rkujawa 
     51   1.1   rkujawa #include <arm/pic/picvar.h>
     52   1.1   rkujawa #include <arm/pic/picvar.h>
     53   1.1   rkujawa 
     54   1.1   rkujawa #include <arm/armreg.h>
     55   1.1   rkujawa #include <arm/cpu.h>
     56   1.1   rkujawa #include <arm/cpufunc.h>
     57   1.1   rkujawa 
     58   1.1   rkujawa #include <arm/marvell/mvsocreg.h>
     59   1.1   rkujawa #include <arm/marvell/mvsocvar.h>
     60   1.3  kiyohara #include <arm/marvell/armadaxpreg.h>
     61   1.9  hsuenaga #include <arm/marvell/armadaxpvar.h>
     62   1.1   rkujawa 
     63   1.1   rkujawa #include <dev/marvell/marvellreg.h>
     64   1.1   rkujawa 
     65   1.7  kiyohara #define EXTRACT_XP_CPU_FREQ_FIELD(sar)	(((0x01 & (sar >> 52)) << 3) | \
     66   1.1   rkujawa 					    (0x07 & (sar >> 21)))
     67   1.7  kiyohara #define EXTRACT_XP_FAB_FREQ_FIELD(sar)	(((0x01 & (sar >> 51)) << 4) | \
     68   1.1   rkujawa 					    (0x0F & (sar >> 24)))
     69   1.7  kiyohara #define EXTRACT_370_CPU_FREQ_FIELD(sar)	((sar >> 11) & 0xf)
     70   1.7  kiyohara #define EXTRACT_370_FAB_FREQ_FIELD(sar)	((sar >> 15) & 0x1f)
     71   1.1   rkujawa 
     72   1.1   rkujawa #define	MPIC_WRITE(reg, val)		(bus_space_write_4(&mvsoc_bs_tag, \
     73   1.1   rkujawa 					    mpic_handle, reg, val))
     74   1.1   rkujawa #define	MPIC_CPU_WRITE(reg, val)	(bus_space_write_4(&mvsoc_bs_tag, \
     75   1.1   rkujawa 					    mpic_cpu_handle, reg, val))
     76   1.1   rkujawa 
     77   1.1   rkujawa #define	MPIC_READ(reg)			(bus_space_read_4(&mvsoc_bs_tag, \
     78   1.1   rkujawa 					    mpic_handle, reg))
     79   1.1   rkujawa #define	MPIC_CPU_READ(reg)		(bus_space_read_4(&mvsoc_bs_tag, \
     80   1.1   rkujawa 					    mpic_cpu_handle, reg))
     81   1.1   rkujawa 
     82   1.1   rkujawa #define	L2_WRITE(reg, val)		(bus_space_write_4(&mvsoc_bs_tag, \
     83   1.1   rkujawa 					    l2_handle, reg, val))
     84   1.1   rkujawa #define	L2_READ(reg)			(bus_space_read_4(&mvsoc_bs_tag, \
     85   1.1   rkujawa 					    l2_handle, reg))
     86   1.1   rkujawa bus_space_handle_t mpic_cpu_handle;
     87   1.1   rkujawa static bus_space_handle_t mpic_handle, l2_handle;
     88   1.1   rkujawa int l2cache_state = 0;
     89   1.1   rkujawa int iocc_state = 0;
     90   1.5  kiyohara #define read_miscreg(r)		(*(volatile uint32_t *)(misc_base + (r)))
     91   1.5  kiyohara vaddr_t misc_base;
     92  1.13  hsuenaga vaddr_t armadaxp_l2_barrier_reg;
     93   1.1   rkujawa 
     94   1.1   rkujawa extern void (*mvsoc_intr_init)(void);
     95   1.1   rkujawa static void armadaxp_intr_init(void);
     96   1.1   rkujawa 
     97   1.1   rkujawa static void armadaxp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     98   1.1   rkujawa static void armadaxp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     99   1.1   rkujawa static void armadaxp_pic_establish_irq(struct pic_softc *, struct intrsource *);
    100   1.4  kiyohara static void armadaxp_pic_set_priority(struct pic_softc *, int);
    101   1.1   rkujawa 
    102   1.4  kiyohara static int armadaxp_find_pending_irqs(void);
    103   1.4  kiyohara static void armadaxp_pic_block_irq(struct pic_softc *, size_t);
    104   1.1   rkujawa 
    105   1.1   rkujawa struct vco_freq_ratio {
    106   1.1   rkujawa 	uint8_t	vco_cpu;	/* VCO to CLK0(CPU) clock ratio */
    107   1.1   rkujawa 	uint8_t	vco_l2c;	/* VCO to NB(L2 cache) clock ratio */
    108   1.1   rkujawa 	uint8_t	vco_hcl;	/* VCO to HCLK(DDR controller) clock ratio */
    109   1.1   rkujawa 	uint8_t	vco_ddr;	/* VCO to DR(DDR memory) clock ratio */
    110   1.1   rkujawa };
    111   1.1   rkujawa 
    112   1.1   rkujawa static struct vco_freq_ratio freq_conf_table[] = {
    113   1.1   rkujawa /*00*/	{ 1, 1,	 4,  2 },
    114   1.1   rkujawa /*01*/	{ 1, 2,	 2,  2 },
    115   1.1   rkujawa /*02*/	{ 2, 2,	 6,  3 },
    116   1.1   rkujawa /*03*/	{ 2, 2,	 3,  3 },
    117   1.1   rkujawa /*04*/	{ 1, 2,	 3,  3 },
    118   1.1   rkujawa /*05*/	{ 1, 2,	 4,  2 },
    119   1.1   rkujawa /*06*/	{ 1, 1,	 2,  2 },
    120   1.1   rkujawa /*07*/	{ 2, 3,	 6,  6 },
    121   1.1   rkujawa /*08*/	{ 2, 3,	 5,  5 },
    122   1.1   rkujawa /*09*/	{ 1, 2,	 6,  3 },
    123   1.1   rkujawa /*10*/	{ 2, 4,	10,  5 },
    124   1.1   rkujawa /*11*/	{ 1, 3,	 6,  6 },
    125   1.1   rkujawa /*12*/	{ 1, 2,	 5,  5 },
    126   1.1   rkujawa /*13*/	{ 1, 3,	 6,  3 },
    127   1.1   rkujawa /*14*/	{ 1, 2,	 5,  5 },
    128   1.1   rkujawa /*15*/	{ 2, 2,	 5,  5 },
    129   1.1   rkujawa /*16*/	{ 1, 1,	 3,  3 },
    130   1.1   rkujawa /*17*/	{ 2, 5,	10, 10 },
    131   1.1   rkujawa /*18*/	{ 1, 3,	 8,  4 },
    132   1.1   rkujawa /*19*/	{ 1, 1,	 2,  1 },
    133   1.1   rkujawa /*20*/	{ 2, 3,	 6,  3 },
    134   1.1   rkujawa /*21*/	{ 1, 2,	 8,  4 },
    135   1.1   rkujawa /*22*/	{ 2, 5,	10,  5 }
    136   1.1   rkujawa };
    137   1.1   rkujawa 
    138   1.7  kiyohara static uint16_t clock_table_xp[] = {
    139   1.7  kiyohara 	1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000,
    140   1.7  kiyohara 	 600,  667,  800, 1600, 2133, 2200, 2400
    141   1.7  kiyohara };
    142   1.7  kiyohara static uint16_t clock_table_370[] = {
    143   1.7  kiyohara 	 400,  533,  667,  800, 1000, 1067, 1200, 1333,
    144   1.7  kiyohara 	1500, 1600, 1667, 1800, 2000,  333,  600,  900,
    145   1.7  kiyohara 	   0
    146   1.7  kiyohara };
    147   1.1   rkujawa 
    148   1.1   rkujawa static struct pic_ops armadaxp_picops = {
    149   1.1   rkujawa 	.pic_unblock_irqs = armadaxp_pic_unblock_irqs,
    150   1.1   rkujawa 	.pic_block_irqs = armadaxp_pic_block_irqs,
    151   1.1   rkujawa 	.pic_establish_irq = armadaxp_pic_establish_irq,
    152   1.4  kiyohara 	.pic_set_priority = armadaxp_pic_set_priority,
    153   1.1   rkujawa };
    154   1.1   rkujawa 
    155   1.1   rkujawa static struct pic_softc armadaxp_pic = {
    156   1.1   rkujawa 	.pic_ops = &armadaxp_picops,
    157   1.1   rkujawa 	.pic_name = "armadaxp",
    158   1.1   rkujawa };
    159   1.1   rkujawa 
    160   1.6  kiyohara static struct {
    161   1.6  kiyohara 	bus_size_t offset;
    162   1.6  kiyohara 	uint32_t bits;
    163   1.6  kiyohara } clkgatings[]= {
    164   1.6  kiyohara 	{ ARMADAXP_GBE3_BASE,	(1 << 1) },
    165   1.6  kiyohara 	{ ARMADAXP_GBE2_BASE,	(1 << 2) },
    166   1.6  kiyohara 	{ ARMADAXP_GBE1_BASE,	(1 << 3) },
    167   1.6  kiyohara 	{ ARMADAXP_GBE0_BASE,	(1 << 4) },
    168   1.6  kiyohara 	{ MVSOC_PEX_BASE,	(1 << 5) },
    169   1.6  kiyohara 	{ ARMADAXP_PEX01_BASE,	(1 << 6) },
    170   1.6  kiyohara 	{ ARMADAXP_PEX02_BASE,	(1 << 7) },
    171   1.6  kiyohara 	{ ARMADAXP_PEX03_BASE,	(1 << 8) },
    172   1.6  kiyohara 	{ ARMADAXP_PEX10_BASE,	(1 << 9) },
    173   1.6  kiyohara 	{ ARMADAXP_PEX11_BASE,	(1 << 10) },
    174   1.6  kiyohara 	{ ARMADAXP_PEX12_BASE,	(1 << 11) },
    175   1.6  kiyohara 	{ ARMADAXP_PEX13_BASE,	(1 << 12) },
    176   1.6  kiyohara #if 0
    177   1.6  kiyohara 	{ NetA, (1 << 13) },
    178   1.6  kiyohara #endif
    179   1.6  kiyohara 	{ ARMADAXP_SATAHC_BASE,	(1 << 14) | (1 << 15) | (1 << 29) | (1 << 30) },
    180   1.6  kiyohara 	{ ARMADAXP_LCD_BASE,	(1 << 16) },
    181   1.6  kiyohara 	{ ARMADAXP_SDIO_BASE,	(1 << 17) },
    182   1.6  kiyohara 	{ ARMADAXP_USB1_BASE,	(1 << 19) },
    183   1.6  kiyohara 	{ ARMADAXP_USB2_BASE,	(1 << 20) },
    184   1.6  kiyohara 	{ ARMADAXP_PEX2_BASE,	(1 << 26) },
    185   1.6  kiyohara 	{ ARMADAXP_PEX3_BASE,	(1 << 27) },
    186   1.6  kiyohara #if 0
    187   1.6  kiyohara 	{ DDR, (1 << 28) },
    188   1.6  kiyohara #endif
    189   1.6  kiyohara };
    190   1.6  kiyohara 
    191   1.1   rkujawa /*
    192   1.1   rkujawa  * armadaxp_intr_bootstrap:
    193   1.1   rkujawa  *
    194   1.1   rkujawa  *	Initialize the rest of the interrupt subsystem, making it
    195   1.1   rkujawa  *	ready to handle interrupts from devices.
    196   1.1   rkujawa  */
    197   1.1   rkujawa void
    198   1.3  kiyohara armadaxp_intr_bootstrap(bus_addr_t pbase)
    199   1.1   rkujawa {
    200   1.1   rkujawa 	int i;
    201   1.1   rkujawa 
    202   1.1   rkujawa 	/* Map MPIC base and MPIC percpu base registers */
    203   1.3  kiyohara 	if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_BASE,
    204   1.3  kiyohara 	    0x500, 0, &mpic_handle) != 0)
    205   1.1   rkujawa 		panic("%s: Could not map MPIC registers", __func__);
    206   1.3  kiyohara 	if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_CPU_BASE,
    207   1.3  kiyohara 	    0x800, 0, &mpic_cpu_handle) != 0)
    208   1.1   rkujawa 		panic("%s: Could not map MPIC percpu registers", __func__);
    209   1.1   rkujawa 
    210   1.1   rkujawa 	/* Disable all interrupts */
    211   1.1   rkujawa 	for (i = 0; i < 116; i++)
    212   1.1   rkujawa 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
    213   1.1   rkujawa 
    214   1.1   rkujawa 	mvsoc_intr_init = armadaxp_intr_init;
    215   1.1   rkujawa }
    216   1.1   rkujawa 
    217   1.1   rkujawa static void
    218   1.1   rkujawa armadaxp_intr_init(void)
    219   1.1   rkujawa {
    220   1.1   rkujawa 	int ctrl;
    221   1.1   rkujawa 
    222   1.1   rkujawa 	/* Get max interrupts */
    223   1.1   rkujawa 	armadaxp_pic.pic_maxsources =
    224   1.1   rkujawa 	    ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
    225   1.1   rkujawa 
    226   1.1   rkujawa 	if (!armadaxp_pic.pic_maxsources)
    227   1.1   rkujawa 		armadaxp_pic.pic_maxsources = 116;
    228   1.1   rkujawa 
    229   1.1   rkujawa 	pic_add(&armadaxp_pic, 0);
    230   1.1   rkujawa 
    231   1.1   rkujawa 	ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
    232   1.1   rkujawa 	/* Enable IRQ prioritization */
    233   1.1   rkujawa 	ctrl |= (1 << 0);
    234   1.1   rkujawa 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
    235   1.4  kiyohara 
    236   1.4  kiyohara 	find_pending_irqs = armadaxp_find_pending_irqs;
    237   1.1   rkujawa }
    238   1.1   rkujawa 
    239   1.1   rkujawa static void
    240   1.1   rkujawa armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    241   1.1   rkujawa     uint32_t irq_mask)
    242   1.1   rkujawa {
    243   1.1   rkujawa 	int n;
    244   1.1   rkujawa 
    245   1.1   rkujawa 	while (irq_mask != 0) {
    246   1.1   rkujawa 		n = ffs(irq_mask) - 1;
    247   1.1   rkujawa 		KASSERT(pic->pic_maxsources >= n + irqbase);
    248   1.1   rkujawa 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
    249   1.1   rkujawa 		MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
    250   1.1   rkujawa 		if ((n + irqbase) == 0)
    251   1.1   rkujawa 			MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
    252   1.1   rkujawa 			    0xffffffff);
    253   1.1   rkujawa 		irq_mask &= ~__BIT(n);
    254   1.1   rkujawa 	}
    255   1.1   rkujawa }
    256   1.1   rkujawa 
    257   1.1   rkujawa static void
    258   1.1   rkujawa armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    259   1.1   rkujawa     uint32_t irq_mask)
    260   1.1   rkujawa {
    261   1.1   rkujawa 	int n;
    262   1.1   rkujawa 
    263   1.1   rkujawa 	while (irq_mask != 0) {
    264   1.1   rkujawa 		n = ffs(irq_mask) - 1;
    265   1.1   rkujawa 		KASSERT(pic->pic_maxsources >= n + irqbase);
    266   1.1   rkujawa 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
    267   1.1   rkujawa 		MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
    268   1.1   rkujawa 		irq_mask &= ~__BIT(n);
    269   1.1   rkujawa 	}
    270   1.1   rkujawa }
    271   1.1   rkujawa 
    272   1.1   rkujawa static void
    273   1.1   rkujawa armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    274   1.1   rkujawa {
    275   1.1   rkujawa 	int tmp;
    276   1.1   rkujawa 	KASSERT(pic->pic_maxsources >= is->is_irq);
    277   1.1   rkujawa 	tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
    278   1.1   rkujawa 	/* Clear previous priority */
    279   1.1   rkujawa 	tmp &= ~(0xf << MPIC_ISCR_SHIFT);
    280   1.1   rkujawa 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
    281   1.1   rkujawa 	    tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
    282   1.1   rkujawa }
    283   1.1   rkujawa 
    284   1.4  kiyohara static void
    285   1.4  kiyohara armadaxp_pic_set_priority(struct pic_softc *pic, int ipl)
    286   1.4  kiyohara {
    287   1.4  kiyohara 	int ctp;
    288   1.4  kiyohara 
    289   1.4  kiyohara 	ctp = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_CTP);
    290   1.4  kiyohara 	ctp &= ~(0xf << MPIC_CTP_SHIFT);
    291   1.4  kiyohara 	ctp |= (ipl << MPIC_CTP_SHIFT);
    292   1.4  kiyohara 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, ctp);
    293   1.4  kiyohara }
    294   1.4  kiyohara 
    295   1.4  kiyohara static int
    296   1.4  kiyohara armadaxp_find_pending_irqs(void)
    297   1.1   rkujawa {
    298   1.1   rkujawa 	struct intrsource *is;
    299   1.1   rkujawa 	int irq;
    300   1.1   rkujawa 
    301   1.1   rkujawa 	irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
    302   1.1   rkujawa 
    303   1.1   rkujawa 	/* Is it a spurious interrupt ?*/
    304   1.1   rkujawa 	if (irq == 0x3ff)
    305   1.4  kiyohara 		return 0;
    306   1.1   rkujawa 	is = armadaxp_pic.pic_sources[irq];
    307   1.4  kiyohara 	if (is == NULL) {
    308   1.4  kiyohara 		printf("stray interrupt: %d\n", irq);
    309   1.4  kiyohara 		return 0;
    310   1.1   rkujawa 	}
    311   1.4  kiyohara 
    312   1.4  kiyohara 	armadaxp_pic_block_irq(&armadaxp_pic, irq);
    313   1.4  kiyohara 	pic_mark_pending(&armadaxp_pic, irq);
    314   1.4  kiyohara 
    315   1.4  kiyohara 	return is->is_ipl;
    316   1.4  kiyohara }
    317   1.4  kiyohara 
    318   1.4  kiyohara static void
    319   1.4  kiyohara armadaxp_pic_block_irq(struct pic_softc *pic, size_t irq)
    320   1.4  kiyohara {
    321   1.4  kiyohara 
    322   1.4  kiyohara 	KASSERT(pic->pic_maxsources >= irq);
    323   1.4  kiyohara 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, irq);
    324   1.4  kiyohara 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, irq);
    325   1.1   rkujawa }
    326   1.1   rkujawa 
    327   1.1   rkujawa /*
    328   1.1   rkujawa  * Clock functions
    329   1.1   rkujawa  */
    330   1.1   rkujawa 
    331   1.1   rkujawa void
    332   1.1   rkujawa armadaxp_getclks(void)
    333   1.1   rkujawa {
    334   1.1   rkujawa 	uint64_t sar_reg;
    335   1.7  kiyohara 	uint8_t  sar_cpu_freq, sar_fab_freq;
    336   1.1   rkujawa 
    337   1.1   rkujawa 	if (cputype == CPU_ID_MV88SV584X_V7)
    338   1.1   rkujawa 		mvTclk = 250000000; /* 250 MHz */
    339   1.1   rkujawa 	else
    340   1.1   rkujawa 		mvTclk = 200000000; /* 200 MHz */
    341   1.1   rkujawa 
    342   1.1   rkujawa 	sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
    343   1.1   rkujawa 	    read_miscreg(ARMADAXP_MISC_SAR_LO);
    344   1.1   rkujawa 
    345   1.7  kiyohara 	sar_cpu_freq = EXTRACT_XP_CPU_FREQ_FIELD(sar_reg);
    346   1.7  kiyohara 	sar_fab_freq = EXTRACT_XP_FAB_FREQ_FIELD(sar_reg);
    347   1.1   rkujawa 
    348   1.1   rkujawa 	/* Check if CPU frequency field has correct value */
    349   1.7  kiyohara 	if (sar_cpu_freq >= __arraycount(clock_table_xp))
    350   1.1   rkujawa 		panic("Reserved value in cpu frequency configuration field: "
    351   1.1   rkujawa 		    "%d", sar_cpu_freq);
    352   1.1   rkujawa 
    353   1.1   rkujawa 	/* Check if fabric frequency field has correct value */
    354   1.7  kiyohara 	if (sar_fab_freq >= __arraycount(freq_conf_table))
    355   1.1   rkujawa 		panic("Reserved value in fabric frequency configuration field: "
    356   1.1   rkujawa 		    "%d", sar_fab_freq);
    357   1.1   rkujawa 
    358   1.1   rkujawa 	/* Get CPU clock frequency */
    359   1.7  kiyohara 	mvPclk = clock_table_xp[sar_cpu_freq] *
    360   1.1   rkujawa 	    freq_conf_table[sar_fab_freq].vco_cpu;
    361   1.1   rkujawa 
    362   1.1   rkujawa 	/* Get L2CLK clock frequency and use as system clock (mvSysclk) */
    363   1.1   rkujawa 	mvSysclk = mvPclk / freq_conf_table[sar_fab_freq].vco_l2c;
    364   1.1   rkujawa 
    365   1.1   rkujawa 	/* Round mvSysclk value to integer MHz */
    366   1.1   rkujawa 	if (((mvPclk % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
    367   1.1   rkujawa 	    freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
    368   1.1   rkujawa 		mvSysclk++;
    369   1.1   rkujawa 
    370   1.7  kiyohara 	mvPclk *= 1000000;
    371   1.7  kiyohara 	mvSysclk *= 1000000;
    372   1.8      matt 
    373   1.8      matt 	curcpu()->ci_data.cpu_cc_freq = mvPclk;
    374   1.7  kiyohara }
    375   1.7  kiyohara 
    376   1.7  kiyohara void
    377   1.7  kiyohara armada370_getclks(void)
    378   1.7  kiyohara {
    379   1.7  kiyohara 	uint32_t sar;
    380   1.7  kiyohara 	uint8_t  cpu_freq, fab_freq;
    381   1.7  kiyohara 
    382   1.7  kiyohara 	sar = read_miscreg(ARMADAXP_MISC_SAR_LO);
    383   1.7  kiyohara 	if (sar & 0x00100000)
    384   1.7  kiyohara 		mvTclk = 200000000; /* 200 MHz */
    385   1.7  kiyohara 	else
    386   1.7  kiyohara 		mvTclk = 166666667; /* 166 MHz */
    387   1.7  kiyohara 
    388   1.7  kiyohara 	cpu_freq = EXTRACT_370_CPU_FREQ_FIELD(sar);
    389   1.7  kiyohara 	fab_freq = EXTRACT_370_FAB_FREQ_FIELD(sar);
    390   1.7  kiyohara 
    391   1.7  kiyohara 	/* Check if CPU frequency field has correct value */
    392   1.7  kiyohara 	if (cpu_freq >= __arraycount(clock_table_370))
    393   1.7  kiyohara 		panic("Reserved value in cpu frequency configuration field: "
    394   1.7  kiyohara 		    "%d", cpu_freq);
    395   1.7  kiyohara 
    396   1.7  kiyohara 	/* Check if fabric frequency field has correct value */
    397   1.7  kiyohara 	if (fab_freq >= __arraycount(freq_conf_table))
    398   1.7  kiyohara 		panic("Reserved value in fabric frequency configuration field: "
    399   1.7  kiyohara 		    "%d", fab_freq);
    400   1.7  kiyohara 
    401   1.7  kiyohara 	/* Get CPU clock frequency */
    402   1.7  kiyohara 	mvPclk = clock_table_370[cpu_freq] *
    403   1.7  kiyohara 	    freq_conf_table[fab_freq].vco_cpu;
    404   1.7  kiyohara 
    405   1.7  kiyohara 	/* Get L2CLK clock frequency and use as system clock (mvSysclk) */
    406   1.7  kiyohara 	mvSysclk = mvPclk / freq_conf_table[fab_freq].vco_l2c;
    407   1.7  kiyohara 
    408   1.7  kiyohara 	/* Round mvSysclk value to integer MHz */
    409   1.7  kiyohara 	if (((mvPclk % freq_conf_table[fab_freq].vco_l2c) * 10 /
    410   1.7  kiyohara 	    freq_conf_table[fab_freq].vco_l2c) >= 5)
    411   1.7  kiyohara 		mvSysclk++;
    412   1.7  kiyohara 
    413   1.7  kiyohara 	mvPclk *= 1000000;
    414   1.7  kiyohara 	mvSysclk *= 1000000;
    415   1.1   rkujawa }
    416   1.1   rkujawa 
    417   1.1   rkujawa /*
    418   1.1   rkujawa  * L2 Cache initialization
    419   1.1   rkujawa  */
    420   1.1   rkujawa 
    421   1.1   rkujawa int
    422   1.3  kiyohara armadaxp_l2_init(bus_addr_t pbase)
    423   1.1   rkujawa {
    424   1.1   rkujawa 	u_int32_t reg;
    425   1.1   rkujawa 	int ret;
    426   1.1   rkujawa 
    427   1.1   rkujawa 	/* Map L2 space */
    428   1.3  kiyohara 	ret = bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_L2_BASE,
    429   1.3  kiyohara 	    0x1000, 0, &l2_handle);
    430   1.1   rkujawa 	if (ret) {
    431   1.1   rkujawa 		printf("%s: Cannot map L2 register space, ret:%d\n",
    432   1.1   rkujawa 		    __func__, ret);
    433   1.1   rkujawa 		return (-1);
    434   1.1   rkujawa 	}
    435   1.1   rkujawa 
    436  1.13  hsuenaga 	/* Variables for cpufunc_asm_pj4b.S */
    437  1.13  hsuenaga 	armadaxp_l2_barrier_reg = mlmb_base + MVSOC_MLMB_CIB_BARRIER_TRIGGER;
    438  1.13  hsuenaga 
    439   1.1   rkujawa 	/* Set L2 policy */
    440   1.1   rkujawa 	reg = L2_READ(ARMADAXP_L2_AUX_CTRL);
    441  1.13  hsuenaga 	reg &= ~(L2_AUX_WBWT_MODE_MASK);
    442  1.13  hsuenaga 	reg &= ~(L2_AUX_REP_STRAT_MASK);
    443  1.13  hsuenaga 	reg |= L2_AUX_WBWT_MODE_WB;
    444  1.13  hsuenaga 	reg |= L2_AUX_ECC_ENABLE;
    445  1.13  hsuenaga 	reg |= L2_AUX_PARITY_ENABLE;
    446  1.13  hsuenaga 	reg |= L2_AUX_FORCE_WA;
    447  1.13  hsuenaga 	reg |= L2_AUX_REP_STRAT_SEMIPLRU;
    448   1.1   rkujawa 	L2_WRITE(ARMADAXP_L2_AUX_CTRL, reg);
    449   1.1   rkujawa 
    450   1.1   rkujawa 	/* Invalidate L2 cache */
    451   1.1   rkujawa 	L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
    452   1.1   rkujawa 
    453   1.1   rkujawa 	/* Clear pending L2 interrupts */
    454   1.1   rkujawa 	L2_WRITE(ARMADAXP_L2_INT_CAUSE, 0x1ff);
    455   1.1   rkujawa 
    456   1.1   rkujawa 	/* Enable Cache and TLB maintenance broadcast */
    457   1.1   rkujawa 	__asm__ __volatile__ ("mrc p15, 1, %0, c15, c2, 0" : "=r"(reg));
    458   1.1   rkujawa 	reg |= (1 << 8);
    459   1.1   rkujawa 	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c2, 0" : :"r"(reg));
    460   1.1   rkujawa 
    461   1.1   rkujawa 	/*
    462   1.1   rkujawa 	 * Set the Point of Coherency and Point of Unification to DRAM.
    463   1.1   rkujawa 	 * This is a reset value but anyway, configure this just in case.
    464   1.1   rkujawa 	 */
    465   1.1   rkujawa 	reg = read_mlmbreg(ARMADAXP_L2_CFU);
    466   1.1   rkujawa 	reg |= (1 << 17) | (1 << 18);
    467   1.1   rkujawa 	write_mlmbreg(ARMADAXP_L2_CFU, reg);
    468   1.1   rkujawa 
    469   1.1   rkujawa 	/* Enable L2 cache */
    470   1.1   rkujawa 	reg = L2_READ(ARMADAXP_L2_CTRL);
    471  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_CTRL, reg | L2_CTRL_ENABLE);
    472   1.1   rkujawa 
    473   1.1   rkujawa 	/* Mark as enabled */
    474   1.1   rkujawa 	l2cache_state = 1;
    475   1.1   rkujawa 
    476   1.1   rkujawa #ifdef DEBUG
    477   1.1   rkujawa 	/* Configure and enable counter */
    478   1.1   rkujawa 	L2_WRITE(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
    479   1.1   rkujawa 	L2_WRITE(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
    480   1.1   rkujawa 	L2_WRITE(ARMADAXP_L2_CNTR_CTRL, 0x303);
    481   1.1   rkujawa #endif
    482   1.1   rkujawa 
    483   1.1   rkujawa 	return (0);
    484   1.1   rkujawa }
    485   1.1   rkujawa 
    486   1.1   rkujawa void
    487   1.9  hsuenaga armadaxp_sdcache_inv_all(void)
    488   1.9  hsuenaga {
    489   1.9  hsuenaga 	L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
    490   1.9  hsuenaga }
    491   1.9  hsuenaga 
    492   1.9  hsuenaga void
    493   1.9  hsuenaga armadaxp_sdcache_wb_all(void)
    494   1.9  hsuenaga {
    495   1.9  hsuenaga 	L2_WRITE(ARMADAXP_L2_WB_WAY, L2_ALL_WAYS);
    496  1.10  hsuenaga 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    497   1.9  hsuenaga 	__asm__ __volatile__("dsb");
    498   1.9  hsuenaga }
    499   1.9  hsuenaga 
    500   1.9  hsuenaga void
    501   1.9  hsuenaga armadaxp_sdcache_wbinv_all(void)
    502   1.9  hsuenaga {
    503   1.9  hsuenaga 	L2_WRITE(ARMADAXP_L2_WBINV_WAY, L2_ALL_WAYS);
    504  1.10  hsuenaga 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    505   1.9  hsuenaga 	__asm__ __volatile__("dsb");
    506   1.9  hsuenaga }
    507   1.9  hsuenaga 
    508  1.13  hsuenaga static paddr_t
    509  1.13  hsuenaga armadaxp_sdcache_wbalign_base(vaddr_t va, paddr_t pa, psize_t sz)
    510  1.13  hsuenaga {
    511  1.13  hsuenaga 	paddr_t line_start = pa & ~ARMADAXP_L2_ALIGN;
    512  1.13  hsuenaga 	vaddr_t save_start;
    513  1.13  hsuenaga 	uint8_t save_buf[ARMADAXP_L2_LINE_SIZE];
    514  1.13  hsuenaga 	size_t unalign;
    515  1.13  hsuenaga 
    516  1.13  hsuenaga 	unalign = va & ARMADAXP_L2_ALIGN;
    517  1.13  hsuenaga 	if (unalign == 0)
    518  1.13  hsuenaga 		return line_start;  /* request is aligned to cache line size */
    519  1.13  hsuenaga 
    520  1.13  hsuenaga 	/* save data that is not intended to invalidate */
    521  1.13  hsuenaga 	save_start = va & ~ARMADAXP_L2_ALIGN;
    522  1.13  hsuenaga 	memcpy(save_buf, (void *)save_start, unalign);
    523  1.13  hsuenaga 
    524  1.13  hsuenaga 	/* invalidate include saved data */
    525  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_INV_PHYS, line_start);
    526  1.13  hsuenaga 
    527  1.13  hsuenaga 	/* write back saved data */
    528  1.13  hsuenaga 	memcpy((void *)save_start, save_buf, unalign);
    529  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_WB_PHYS, line_start);
    530  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    531  1.13  hsuenaga 	__asm__ __volatile__("dsb");
    532  1.13  hsuenaga 
    533  1.13  hsuenaga 	return line_start;
    534  1.13  hsuenaga }
    535  1.13  hsuenaga 
    536  1.13  hsuenaga static paddr_t
    537  1.13  hsuenaga armadaxp_sdcache_wbalign_end(vaddr_t va, paddr_t pa, psize_t sz)
    538  1.13  hsuenaga {
    539  1.13  hsuenaga 	paddr_t line_start = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
    540  1.13  hsuenaga 	vaddr_t save_start = va + sz;
    541  1.13  hsuenaga 	uint8_t save_buf[ARMADAXP_L2_LINE_SIZE];
    542  1.13  hsuenaga 	size_t save_len;
    543  1.13  hsuenaga 	size_t unalign;
    544  1.13  hsuenaga 
    545  1.13  hsuenaga 	unalign = save_start & ARMADAXP_L2_ALIGN;
    546  1.13  hsuenaga 	if (unalign == 0)
    547  1.13  hsuenaga 		return line_start; /* request is aligned to cache line size */
    548  1.13  hsuenaga 
    549  1.13  hsuenaga 	/* save data that is not intended to invalidate */
    550  1.13  hsuenaga 	save_len = ARMADAXP_L2_LINE_SIZE - unalign;
    551  1.13  hsuenaga 	memcpy(save_buf, (void *)save_start, save_len);
    552  1.13  hsuenaga 
    553  1.13  hsuenaga 	/* invalidate include saved data */
    554  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_INV_PHYS, line_start);
    555  1.13  hsuenaga 
    556  1.13  hsuenaga 	/* write back saved data */
    557  1.13  hsuenaga 	memcpy((void *)save_start, save_buf, save_len);
    558  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_WB_PHYS, line_start);
    559  1.13  hsuenaga 	__asm__ __volatile__("dsb");
    560  1.13  hsuenaga 
    561  1.13  hsuenaga 	return line_start;
    562  1.13  hsuenaga }
    563  1.13  hsuenaga 
    564   1.9  hsuenaga void
    565   1.9  hsuenaga armadaxp_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t sz)
    566   1.9  hsuenaga {
    567  1.13  hsuenaga 	paddr_t pa_base;
    568  1.13  hsuenaga 	paddr_t pa_end;
    569   1.9  hsuenaga 
    570  1.13  hsuenaga 	/* align and write-back the boundary */
    571  1.13  hsuenaga 	pa_base = armadaxp_sdcache_wbalign_base(va, pa, sz);
    572  1.13  hsuenaga 	pa_end = armadaxp_sdcache_wbalign_end(va, pa, sz);
    573  1.12  hsuenaga 
    574  1.12  hsuenaga 	/* invalidate other cache */
    575  1.13  hsuenaga 	if (pa_base == pa_end) {
    576  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_INV_PHYS, pa_base);
    577  1.13  hsuenaga 		return;
    578  1.12  hsuenaga 	}
    579  1.13  hsuenaga 
    580  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    581  1.13  hsuenaga 	L2_WRITE(ARMADAXP_L2_INV_RANGE, pa_end);
    582   1.9  hsuenaga }
    583   1.9  hsuenaga 
    584   1.9  hsuenaga void
    585   1.9  hsuenaga armadaxp_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t sz)
    586   1.9  hsuenaga {
    587  1.13  hsuenaga 	paddr_t pa_base = pa & ~ARMADAXP_L2_ALIGN;
    588  1.13  hsuenaga 	paddr_t pa_end  = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
    589   1.9  hsuenaga 
    590  1.12  hsuenaga 	if (pa_base == pa_end)
    591  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_WB_PHYS, pa_base);
    592  1.12  hsuenaga 	else {
    593  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    594  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_WB_RANGE, pa_end);
    595  1.12  hsuenaga 	}
    596  1.10  hsuenaga 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    597   1.9  hsuenaga 	__asm__ __volatile__("dsb");
    598   1.9  hsuenaga }
    599   1.9  hsuenaga 
    600   1.9  hsuenaga void
    601   1.9  hsuenaga armadaxp_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t sz)
    602   1.9  hsuenaga {
    603  1.13  hsuenaga 	paddr_t pa_base = pa & ~ARMADAXP_L2_ALIGN;;
    604  1.13  hsuenaga 	paddr_t pa_end  = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
    605   1.9  hsuenaga 
    606  1.12  hsuenaga 	if (pa_base == pa_end)
    607  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_WBINV_PHYS, pa_base);
    608  1.12  hsuenaga 	else {
    609  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    610  1.12  hsuenaga 		L2_WRITE(ARMADAXP_L2_WBINV_RANGE, pa_end);
    611  1.12  hsuenaga 	}
    612  1.10  hsuenaga 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    613   1.9  hsuenaga 	__asm__ __volatile__("dsb");
    614   1.9  hsuenaga }
    615   1.9  hsuenaga 
    616   1.9  hsuenaga void
    617   1.1   rkujawa armadaxp_io_coherency_init(void)
    618   1.1   rkujawa {
    619   1.1   rkujawa 	uint32_t reg;
    620   1.1   rkujawa 
    621   1.1   rkujawa 	/* set CIB read snoop command to ReadUnique */
    622   1.1   rkujawa 	reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
    623  1.13  hsuenaga 	reg |= MVSOC_MLMB_CIB_CTRL_CFG_WB_EN;
    624   1.1   rkujawa 	write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
    625  1.13  hsuenaga 
    626   1.1   rkujawa 	/* enable CPUs in SMP group on Fabric coherency */
    627  1.13  hsuenaga 	reg = read_mlmbreg(MVSOC_MLMB_CFU_CTRL);
    628  1.13  hsuenaga 	reg |= MVSOC_MLMB_CFU_CTRL_SNOOP_CPU0;
    629  1.13  hsuenaga 	write_mlmbreg(MVSOC_MLMB_CFU_CTRL, reg);
    630  1.13  hsuenaga 
    631  1.13  hsuenaga 	/* send all snoop request to L2 cache */
    632  1.13  hsuenaga 	reg = read_mlmbreg(MVSOC_MLMB_CFU_CFG);
    633  1.13  hsuenaga #ifdef L2CACHE_ENABLE
    634  1.13  hsuenaga 	reg |= MVSOC_MLMB_CFU_CFG_L2_NOTIFY;
    635  1.13  hsuenaga #else
    636  1.13  hsuenaga 	reg &= ~MVSOC_MLMB_CFU_CFG_L2_NOTIFY;
    637  1.13  hsuenaga #endif
    638  1.13  hsuenaga 	write_mlmbreg(MVSOC_MLMB_CFU_CFG, reg);
    639   1.1   rkujawa 
    640   1.1   rkujawa 	/* Mark as enabled */
    641   1.1   rkujawa 	iocc_state = 1;
    642   1.1   rkujawa }
    643   1.6  kiyohara 
    644   1.7  kiyohara int
    645   1.6  kiyohara armadaxp_clkgating(struct marvell_attach_args *mva)
    646   1.6  kiyohara {
    647   1.6  kiyohara 	uint32_t val;
    648   1.6  kiyohara 	int i;
    649   1.6  kiyohara 
    650   1.6  kiyohara 	for (i = 0; i < __arraycount(clkgatings); i++) {
    651   1.6  kiyohara 		if (clkgatings[i].offset == mva->mva_offset) {
    652   1.6  kiyohara 			val = read_miscreg(ARMADAXP_MISC_PMCGC);
    653   1.6  kiyohara 			if ((val & clkgatings[i].bits) == clkgatings[i].bits)
    654   1.6  kiyohara 				/* Clock enabled */
    655   1.7  kiyohara 				return 0;
    656   1.6  kiyohara 			return 1;
    657   1.6  kiyohara 		}
    658   1.7  kiyohara 	}
    659   1.6  kiyohara 	/* Clock Gating not support */
    660   1.6  kiyohara 	return 0;
    661   1.6  kiyohara }
    662