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