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