Home | History | Annotate | Line # | Download | only in marvell
mv78xx0.c revision 1.1.10.3
      1  1.1.10.2       tls /*	$NetBSD: mv78xx0.c,v 1.1.10.3 2017/12/03 11:35:54 jdolecek Exp $	*/
      2  1.1.10.2       tls /*
      3  1.1.10.2       tls  * Copyright (c) 2010 KIYOHARA Takashi
      4  1.1.10.2       tls  * All rights reserved.
      5  1.1.10.2       tls  *
      6  1.1.10.2       tls  * Redistribution and use in source and binary forms, with or without
      7  1.1.10.2       tls  * modification, are permitted provided that the following conditions
      8  1.1.10.2       tls  * are met:
      9  1.1.10.2       tls  * 1. Redistributions of source code must retain the above copyright
     10  1.1.10.2       tls  *    notice, this list of conditions and the following disclaimer.
     11  1.1.10.2       tls  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1.10.2       tls  *    notice, this list of conditions and the following disclaimer in the
     13  1.1.10.2       tls  *    documentation and/or other materials provided with the distribution.
     14  1.1.10.2       tls  *
     15  1.1.10.2       tls  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  1.1.10.2       tls  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.1.10.2       tls  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.1.10.2       tls  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  1.1.10.2       tls  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  1.1.10.2       tls  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.1.10.2       tls  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.1.10.2       tls  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  1.1.10.2       tls  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  1.1.10.2       tls  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  1.1.10.2       tls  * POSSIBILITY OF SUCH DAMAGE.
     26  1.1.10.2       tls  */
     27  1.1.10.2       tls 
     28  1.1.10.2       tls #include <sys/cdefs.h>
     29  1.1.10.2       tls __KERNEL_RCSID(0, "$NetBSD: mv78xx0.c,v 1.1.10.3 2017/12/03 11:35:54 jdolecek Exp $");
     30  1.1.10.2       tls 
     31  1.1.10.2       tls #define _INTR_PRIVATE
     32  1.1.10.2       tls 
     33  1.1.10.2       tls #include "mvsocgpp.h"
     34  1.1.10.2       tls 
     35  1.1.10.2       tls #include <sys/param.h>
     36  1.1.10.2       tls #include <sys/bus.h>
     37  1.1.10.2       tls #include <sys/cpu.h>
     38  1.1.10.2       tls 
     39  1.1.10.2       tls #include <machine/intr.h>
     40  1.1.10.2       tls 
     41  1.1.10.2       tls #include <arm/pic/picvar.h>
     42  1.1.10.2       tls #include <arm/pic/picvar.h>
     43  1.1.10.2       tls 
     44  1.1.10.2       tls #include <arm/marvell/mvsocreg.h>
     45  1.1.10.2       tls #include <arm/marvell/mvsocvar.h>
     46  1.1.10.2       tls #include <arm/marvell/mv78xx0reg.h>
     47  1.1.10.2       tls 
     48  1.1.10.2       tls #include <dev/marvell/marvellreg.h>
     49  1.1.10.2       tls 
     50  1.1.10.2       tls #define MV78XX0_ICI_MICR(g)	(MV78XX0_ICI_MICLR + ((g) << 2))
     51  1.1.10.2       tls #define MV78XX0_ICI_IRQIMR(g)	(MV78XX0_ICI_IRQIMLR + ((g) << 2))
     52  1.1.10.2       tls 
     53  1.1.10.2       tls static void mv78xx0_intr_init(void);
     54  1.1.10.2       tls 
     55  1.1.10.2       tls static void mv78xx0_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     56  1.1.10.2       tls static void mv78xx0_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     57  1.1.10.2       tls static void mv78xx0_pic_establish_irq(struct pic_softc *, struct intrsource *);
     58  1.1.10.2       tls static void mv78xx0_pic_source_name(struct pic_softc *, int, char *, size_t);
     59  1.1.10.2       tls 
     60  1.1.10.2       tls static int mv78xx0_find_pending_irqs(void);
     61  1.1.10.2       tls 
     62  1.1.10.3  jdolecek static void mv78xx0_getclks(vaddr_t);
     63  1.1.10.3  jdolecek 
     64  1.1.10.2       tls static const char * const sources[64] = {
     65  1.1.10.2       tls     "ErrSum(0)",       "SPI(1)",          "TWSI0(2)",        "TWSI1(3)",
     66  1.1.10.2       tls     "IDMA0(4)",        "IDMA1(5)",        "IDMA2(6)",        "IDMA3(7)",
     67  1.1.10.2       tls     "Timer0(8)",       "Timer1(9)",       "Timer2(10)",      "Timer3(11)",
     68  1.1.10.2       tls     "UART0(12)",       "UART1(13)",       "UART2(14)",       "UART3(15)",
     69  1.1.10.2       tls     "USB0(16)",        "USB1(17)",        "USB2(18)",        "Crypto(19)",
     70  1.1.10.2       tls     "Reserved(20)",    "Reserved(21)",    "XOR0(22)",        "XOR1(23)",
     71  1.1.10.2       tls     "Reserved(24)",    "Reserved(25)",    "SATA(26)",        "TDMI_INT(27)",
     72  1.1.10.2       tls     "Reserved(28)",    "Reserved(29)",    "Reserved(30)",    "Reserved(31)"
     73  1.1.10.2       tls 
     74  1.1.10.2       tls     "PEX00INTA(32)",   "PEX01INTA(33)",   "PEX02INTA(34)",   "PEX03INTA(35)"
     75  1.1.10.2       tls     "PEX10INTA(36)",   "PEX11INTA(37)",   "PEX12INTA(38)",   "PEX13INTA(39)"
     76  1.1.10.2       tls     "GE00Sum(40)",     "GE00Rx(41)",      "GE00Tx(42)",      "GE00Misc(43)"
     77  1.1.10.2       tls     "GE01Sum(44)",     "GE01Rx(45)",      "GE01Tx(46)",      "GE01Misc(47)"
     78  1.1.10.2       tls     "GE10Sum(48)",     "GE10Rx(49)",      "GE10Tx(50)",      "GE10Misc(51)"
     79  1.1.10.2       tls     "GE11Sum(52)",     "GE11Rx(53)",      "GE11Tx(54)",      "GE11Misc(55)"
     80  1.1.10.2       tls     "GPIO0_7(56)",     "GPIO8_15(57)",    "GPIO16_23(58)",   "GPIO24_31(59)"
     81  1.1.10.2       tls     "DB_INT(60)",      "DB_OUT(61)",      "Reserved(62)",    "Reserved(63)"
     82  1.1.10.2       tls };
     83  1.1.10.2       tls 
     84  1.1.10.2       tls static struct pic_ops mv78xx0_picops = {
     85  1.1.10.2       tls 	.pic_unblock_irqs = mv78xx0_pic_unblock_irqs,
     86  1.1.10.2       tls 	.pic_block_irqs = mv78xx0_pic_block_irqs,
     87  1.1.10.2       tls 	.pic_establish_irq = mv78xx0_pic_establish_irq,
     88  1.1.10.2       tls 	.pic_source_name = mv78xx0_pic_source_name,
     89  1.1.10.2       tls };
     90  1.1.10.2       tls static struct pic_softc mv78xx0_pic = {
     91  1.1.10.2       tls 	.pic_ops = &mv78xx0_picops,
     92  1.1.10.2       tls 	.pic_maxsources = 64,
     93  1.1.10.2       tls 	.pic_name = "mv78xx0_pic",
     94  1.1.10.2       tls };
     95  1.1.10.2       tls 
     96  1.1.10.2       tls 
     97  1.1.10.2       tls /*
     98  1.1.10.3  jdolecek  * mv78xx0_bootstrap:
     99  1.1.10.2       tls  *
    100  1.1.10.3  jdolecek  *	Initialize the rest of the Discovery Innovation dependencies, making it
    101  1.1.10.2       tls  *	ready to handle interrupts from devices.
    102  1.1.10.2       tls  */
    103  1.1.10.2       tls void
    104  1.1.10.3  jdolecek mv78xx0_bootstrap(vaddr_t iobase)
    105  1.1.10.2       tls {
    106  1.1.10.2       tls 
    107  1.1.10.2       tls 	/* disable all interrupts */
    108  1.1.10.2       tls 	write_mlmbreg(MV78XX0_ICI_IRQIMER, 0);
    109  1.1.10.2       tls 	write_mlmbreg(MV78XX0_ICI_IRQIMLR, 0);
    110  1.1.10.2       tls 	write_mlmbreg(MV78XX0_ICI_IRQIMHR, 0);
    111  1.1.10.2       tls 
    112  1.1.10.2       tls 	/* disable all bridge interrupts */
    113  1.1.10.2       tls 	write_mlmbreg(MVSOC_MLMB_MLMBIMR, 0);
    114  1.1.10.2       tls 
    115  1.1.10.2       tls 	mvsoc_intr_init = mv78xx0_intr_init;
    116  1.1.10.2       tls 
    117  1.1.10.3  jdolecek #if NMVSOCGPP > 0
    118  1.1.10.2       tls 	gpp_npins = 32;
    119  1.1.10.2       tls 	gpp_irqbase = 64;	/* Main Low(32) + High(32) */
    120  1.1.10.3  jdolecek #endif
    121  1.1.10.3  jdolecek 
    122  1.1.10.3  jdolecek 	mv78xx0_getclks(iobase);
    123  1.1.10.2       tls }
    124  1.1.10.2       tls 
    125  1.1.10.2       tls static void
    126  1.1.10.2       tls mv78xx0_intr_init(void)
    127  1.1.10.2       tls {
    128  1.1.10.2       tls 
    129  1.1.10.2       tls 	pic_add(&mv78xx0_pic, 0);
    130  1.1.10.2       tls 
    131  1.1.10.2       tls 	find_pending_irqs = mv78xx0_find_pending_irqs;
    132  1.1.10.2       tls }
    133  1.1.10.2       tls 
    134  1.1.10.2       tls /* ARGSUSED */
    135  1.1.10.2       tls static void
    136  1.1.10.2       tls mv78xx0_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    137  1.1.10.2       tls 			 uint32_t irq_mask)
    138  1.1.10.2       tls {
    139  1.1.10.2       tls 	const size_t group = irqbase / 32;
    140  1.1.10.2       tls 
    141  1.1.10.2       tls 	write_mlmbreg(MV78XX0_ICI_IRQIMR(group),
    142  1.1.10.2       tls 	    read_mlmbreg(MV78XX0_ICI_IRQIMR(group)) | irq_mask);
    143  1.1.10.2       tls }
    144  1.1.10.2       tls 
    145  1.1.10.2       tls /* ARGSUSED */
    146  1.1.10.2       tls static void
    147  1.1.10.2       tls mv78xx0_pic_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irq_mask)
    148  1.1.10.2       tls {
    149  1.1.10.2       tls 	const size_t group = irqbase / 32;
    150  1.1.10.2       tls 
    151  1.1.10.2       tls 	write_mlmbreg(MV78XX0_ICI_IRQIMR(group),
    152  1.1.10.2       tls 	    read_mlmbreg(MV78XX0_ICI_IRQIMR(group)) & ~irq_mask);
    153  1.1.10.2       tls }
    154  1.1.10.2       tls 
    155  1.1.10.2       tls /* ARGSUSED */
    156  1.1.10.2       tls static void
    157  1.1.10.2       tls mv78xx0_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    158  1.1.10.2       tls {
    159  1.1.10.2       tls 	uint32_t mlmbim;
    160  1.1.10.2       tls 
    161  1.1.10.2       tls 	/* Also enable MbusL-Mbus Bridge Interrupt Mask, if irq is TimerX. */
    162  1.1.10.2       tls 	if (is->is_irq == MV78XX0_IRQ_TIMER0 ||
    163  1.1.10.2       tls 	    is->is_irq == MV78XX0_IRQ_TIMER1 ||
    164  1.1.10.2       tls 	    is->is_irq == MV78XX0_IRQ_TIMER2 ||
    165  1.1.10.2       tls 	    is->is_irq == MV78XX0_IRQ_TIMER3) {
    166  1.1.10.2       tls 		mlmbim = read_mlmbreg(MVSOC_MLMB_MLMBIMR);
    167  1.1.10.2       tls 		mlmbim |= TIMER_IRQ2MLMBIMR(is->is_irq);
    168  1.1.10.2       tls 		write_mlmbreg(MVSOC_MLMB_MLMBIMR, mlmbim);
    169  1.1.10.2       tls 	}
    170  1.1.10.2       tls }
    171  1.1.10.2       tls 
    172  1.1.10.2       tls static void
    173  1.1.10.2       tls mv78xx0_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
    174  1.1.10.2       tls {
    175  1.1.10.2       tls 
    176  1.1.10.2       tls 	strlcpy(buf, sources[pic->pic_irqbase + irq], len);
    177  1.1.10.2       tls }
    178  1.1.10.2       tls 
    179  1.1.10.2       tls /*
    180  1.1.10.2       tls  * Called with interrupts disabled
    181  1.1.10.2       tls  */
    182  1.1.10.2       tls static int
    183  1.1.10.2       tls mv78xx0_find_pending_irqs(void)
    184  1.1.10.2       tls {
    185  1.1.10.2       tls 	uint32_t pending;
    186  1.1.10.2       tls 	int ipl = 0;
    187  1.1.10.2       tls 
    188  1.1.10.2       tls 	pending = read_mlmbreg(MV78XX0_ICI_MICR(0)) &
    189  1.1.10.2       tls 	    read_mlmbreg(MV78XX0_ICI_IRQIMR(0));
    190  1.1.10.2       tls 	if (pending != 0)
    191  1.1.10.2       tls 		ipl = pic_mark_pending_sources(&mv78xx0_pic, 0, pending);
    192  1.1.10.2       tls 
    193  1.1.10.2       tls 	pending = read_mlmbreg(MV78XX0_ICI_MICR(1)) &
    194  1.1.10.2       tls 	    read_mlmbreg(MV78XX0_ICI_IRQIMR(1));
    195  1.1.10.2       tls 	if (pending != 0)
    196  1.1.10.2       tls 		ipl |= pic_mark_pending_sources(&mv78xx0_pic, 32, pending);
    197  1.1.10.2       tls 
    198  1.1.10.2       tls 	return ipl;
    199  1.1.10.2       tls }
    200  1.1.10.2       tls 
    201  1.1.10.2       tls /*
    202  1.1.10.2       tls  * Clock functions
    203  1.1.10.2       tls  */
    204  1.1.10.2       tls 
    205  1.1.10.3  jdolecek static void
    206  1.1.10.3  jdolecek mv78xx0_getclks(vaddr_t iobase)
    207  1.1.10.2       tls {
    208  1.1.10.2       tls 	const static int sys2cpu_clk_ratio_m[] =	/* Mul constant */
    209  1.1.10.2       tls 	    { 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 6 };
    210  1.1.10.2       tls 	const static int sys2cpu_clk_ratio_n[] =	/* Div constant */
    211  1.1.10.2       tls 	    { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 };
    212  1.1.10.2       tls 	uint32_t reg;
    213  1.1.10.2       tls 	int x;
    214  1.1.10.2       tls 
    215  1.1.10.2       tls #define MHz	* 1000 * 1000
    216  1.1.10.2       tls 
    217  1.1.10.2       tls 	reg = *(volatile uint32_t *)(iobase + MV78XX0_SAMPLE_AT_RESET_HIGH);
    218  1.1.10.2       tls 	switch (reg & 0x180) {
    219  1.1.10.2       tls 	case 0x000: mvTclk = 166666667; break;
    220  1.1.10.2       tls 	case 0x080: mvTclk =   200 MHz; break;
    221  1.1.10.2       tls 	default:    mvTclk =   200 MHz; break;
    222  1.1.10.2       tls 	}
    223  1.1.10.2       tls 
    224  1.1.10.2       tls 	reg = *(volatile uint32_t *)(iobase + MV78XX0_SAMPLE_AT_RESET_LOW);
    225  1.1.10.2       tls 
    226  1.1.10.2       tls 	switch (reg & 0x0e0) {
    227  1.1.10.2       tls 	case 0x020: mvSysclk =   200 MHz; break;
    228  1.1.10.2       tls 	case 0x040: mvSysclk = 266666667; break;
    229  1.1.10.2       tls 	case 0x060: mvSysclk = 333333334; break;
    230  1.1.10.2       tls 	case 0x080: mvSysclk =   400 MHz; break;
    231  1.1.10.2       tls 	case 0x0a0: mvSysclk =   250 MHz; break;
    232  1.1.10.2       tls 	case 0x0c0: mvSysclk =   300 MHz; break;
    233  1.1.10.2       tls 	default:    mvSysclk = 266666667; break;
    234  1.1.10.2       tls 	}
    235  1.1.10.2       tls 
    236  1.1.10.2       tls 	x = (reg & 0xf00) >> 8;
    237  1.1.10.2       tls 	mvPclk = sys2cpu_clk_ratio_m[x] * mvSysclk / sys2cpu_clk_ratio_n[x];
    238  1.1.10.2       tls 
    239  1.1.10.2       tls #undef MHz
    240  1.1.10.2       tls 
    241  1.1.10.2       tls }
    242