Home | History | Annotate | Line # | Download | only in marvell
kirkwood.c revision 1.11
      1  1.11       rin /*	$NetBSD: kirkwood.c,v 1.11 2021/08/30 00:04:30 rin 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.11       rin __KERNEL_RCSID(0, "$NetBSD: kirkwood.c,v 1.11 2021/08/30 00:04:30 rin 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 
     38   1.1  kiyohara #include <machine/intr.h>
     39   1.1  kiyohara 
     40   1.1  kiyohara #include <arm/pic/picvar.h>
     41   1.1  kiyohara #include <arm/pic/picvar.h>
     42   1.1  kiyohara 
     43   1.1  kiyohara #include <arm/marvell/mvsocreg.h>
     44   1.1  kiyohara #include <arm/marvell/mvsocvar.h>
     45   1.1  kiyohara #include <arm/marvell/kirkwoodreg.h>
     46   1.1  kiyohara 
     47   1.1  kiyohara #include <dev/marvell/marvellreg.h>
     48   1.1  kiyohara 
     49   1.1  kiyohara 
     50   1.1  kiyohara static void kirkwood_intr_init(void);
     51   1.1  kiyohara 
     52   1.4      matt static void kirkwood_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     53   1.4      matt static void kirkwood_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     54   1.1  kiyohara static void kirkwood_pic_establish_irq(struct pic_softc *, struct intrsource *);
     55   1.1  kiyohara static void kirkwood_pic_source_name(struct pic_softc *, int, char *, size_t);
     56   1.1  kiyohara 
     57   1.1  kiyohara static int kirkwood_find_pending_irqs(void);
     58   1.1  kiyohara 
     59  1.10  kiyohara static void kirkwood_getclks(vaddr_t);
     60  1.10  kiyohara static int kirkwood_clkgating(struct marvell_attach_args *);
     61  1.10  kiyohara 
     62   1.1  kiyohara static const char * const sources[64] = {
     63   1.1  kiyohara     "MainHighSum(0)",  "Bridge(1)",       "Host2CPU DB(2)",  "CPU2Host DB(3)",
     64   1.1  kiyohara     "Reserved_4(4)",   "Xor0Chan0(5)",    "Xor0Chan1(6)",    "Xor1Chan0(7)",
     65   1.1  kiyohara     "Xor1Chan1(8)",    "PEX0INT(9)",      "Reserved(10)",    "GbE0Sum(11)",
     66   1.1  kiyohara     "GbE0Rx(12)",      "GbE0Tx(13)",      "GbE0Misc(14)",    "GbE1Sum(15)",
     67   1.1  kiyohara     "GbE1Rx(16)",      "GbE1Tx(17)",      "GbE1Misc(18)",    "USB0Cnt(19)",
     68   1.1  kiyohara     "Reserved(20)",    "Sata(21)",        "SecurityInt(22)", "SPIInt(23)",
     69   1.1  kiyohara     "AudioINT(24)",    "Reserved(25)",    "TS0Int(26)",      "Reserved(27)",
     70   1.7   msaitoh     "SDIOInt(28)",     "TWSI(29)",        "AVBInt(30)",      "TDMInt(31)",
     71   1.1  kiyohara 
     72   1.7   msaitoh     "Reserved(32)",    "Uart0Int(33)",    "Uart1Int(34)",    "GPIOLo7_0(35)",
     73   1.7   msaitoh     "GPIOLo8_15(36)",  "GPIOLo16_23(37)", "GPIOLo24_31(38)", "GPIOHi7_0(39)",
     74   1.7   msaitoh     "GPIOHi8_15(40)",  "GPIOHi16_23(41)", "XOR0Err(42)",     "XOR1Err(43)",
     75   1.7   msaitoh     "PEX0Err(44)",     "Reserved(45)",    "GbE0Err(46)",     "GbE1Err(47)",
     76   1.7   msaitoh     "USBErr(48)",      "SecurityErr(49)", "AudioErr(50)",    "Reserved(51)",
     77   1.7   msaitoh     "Reserved(52)",    "RTCInt(53)",      "Reserved(54)",    "Reserved(55)",
     78   1.7   msaitoh     "Reserved(56)",    "Reserved(57)",    "Reserved(58)",    "Reserved(59)",
     79   1.1  kiyohara     "Reserved(60)",    "Reserved(61)",    "Reserved(62)",    "Reserved(63)"
     80   1.1  kiyohara };
     81   1.1  kiyohara 
     82   1.4      matt static struct pic_ops kirkwood_picops = {
     83   1.4      matt 	.pic_unblock_irqs = kirkwood_pic_unblock_irqs,
     84   1.4      matt 	.pic_block_irqs = kirkwood_pic_block_irqs,
     85   1.1  kiyohara 	.pic_establish_irq = kirkwood_pic_establish_irq,
     86   1.1  kiyohara 	.pic_source_name = kirkwood_pic_source_name,
     87   1.1  kiyohara };
     88   1.4      matt static struct pic_softc kirkwood_pic = {
     89   1.4      matt 	.pic_ops = &kirkwood_picops,
     90   1.4      matt 	.pic_maxsources = 64,
     91   1.4      matt 	.pic_name = "kirkwood",
     92   1.1  kiyohara };
     93   1.1  kiyohara 
     94   1.8  kiyohara static struct {
     95   1.8  kiyohara 	bus_size_t offset;
     96   1.8  kiyohara 	uint32_t bits;
     97   1.8  kiyohara } clkgatings[]= {
     98   1.8  kiyohara 	{ KIRKWOOD_GBE0_BASE,	(1 << 0) },
     99   1.8  kiyohara 	{ MVSOC_PEX_BASE,	(1 << 2) },
    100   1.8  kiyohara 	{ KIRKWOOD_USB_BASE,	(1 << 3) },
    101   1.8  kiyohara 	{ KIRKWOOD_SDIO_BASE,	(1 << 4) },
    102   1.8  kiyohara 	{ KIRKWOOD_MTS_BASE,	(1 << 5) },
    103   1.8  kiyohara #if 0
    104   1.8  kiyohara 	{ Dunit, (1 << 6) },	/* SDRAM Unit Clock */
    105   1.8  kiyohara 	{ Runit, (1 << 7) },	/* Runit Clock */
    106   1.8  kiyohara #endif
    107   1.8  kiyohara 	{ KIRKWOOD_IDMAC_BASE,	(1 << 8) | (1 << 16) },
    108   1.8  kiyohara 	{ KIRKWOOD_AUDIO_BASE,	(1 << 9) },
    109   1.8  kiyohara 	{ KIRKWOOD_SATAHC_BASE, (1 << 14) | (1 << 15) },
    110   1.8  kiyohara 	{ KIRKWOOD_CESA_BASE,	(1 << 17) },
    111   1.8  kiyohara 	{ KIRKWOOD_GBE1_BASE,	(1 << 19) },
    112   1.8  kiyohara 	{ KIRKWOOD_TDM_BASE,	(1 << 20) },
    113   1.8  kiyohara };
    114   1.8  kiyohara 
    115   1.1  kiyohara 
    116   1.1  kiyohara /*
    117  1.10  kiyohara  * kirkwood_bootstrap:
    118   1.1  kiyohara  *
    119  1.10  kiyohara  *	Initialize the rest of the Kirkwood dependencies, making it
    120   1.1  kiyohara  *	ready to handle interrupts from devices.
    121   1.1  kiyohara  */
    122   1.1  kiyohara void
    123  1.10  kiyohara kirkwood_bootstrap(vaddr_t iobase)
    124   1.1  kiyohara {
    125   1.1  kiyohara 
    126   1.1  kiyohara 	/* disable all interrupts */
    127   1.1  kiyohara 	write_mlmbreg(KIRKWOOD_MLMB_MIRQIMLR, 0);
    128   1.1  kiyohara 	write_mlmbreg(KIRKWOOD_MLMB_MIRQIMHR, 0);
    129   1.1  kiyohara 
    130   1.1  kiyohara 	/* disable all bridge interrupts */
    131   1.1  kiyohara 	write_mlmbreg(MVSOC_MLMB_MLMBIMR, 0);
    132   1.1  kiyohara 
    133   1.1  kiyohara 	mvsoc_intr_init = kirkwood_intr_init;
    134   1.1  kiyohara 
    135   1.1  kiyohara #if NMVSOCGPP > 0
    136   1.1  kiyohara 	switch (mvsoc_model()) {
    137   1.1  kiyohara 	case MARVELL_KIRKWOOD_88F6180: gpp_npins = 30; break;
    138   1.1  kiyohara 	case MARVELL_KIRKWOOD_88F6192: gpp_npins = 36; break;
    139   1.1  kiyohara 	case MARVELL_KIRKWOOD_88F6281: gpp_npins = 50; break;
    140   1.6  kiyohara 	case MARVELL_KIRKWOOD_88F6282: gpp_npins = 50; break;
    141   1.1  kiyohara 	}
    142   1.1  kiyohara 	gpp_irqbase = 96;	/* Main Low(32) + High(32) + Bridge(32) */
    143   1.1  kiyohara #endif
    144  1.10  kiyohara 
    145  1.10  kiyohara 	kirkwood_getclks(iobase);
    146  1.10  kiyohara 	mvsoc_clkgating = kirkwood_clkgating;
    147   1.1  kiyohara }
    148   1.1  kiyohara 
    149   1.1  kiyohara static void
    150   1.1  kiyohara kirkwood_intr_init(void)
    151   1.1  kiyohara {
    152   1.1  kiyohara 	extern struct pic_softc mvsoc_bridge_pic;
    153   1.9    martin 	void *ih __diagused;
    154   1.1  kiyohara 
    155   1.4      matt 	pic_add(&kirkwood_pic, 0);
    156   1.1  kiyohara 
    157   1.1  kiyohara 	pic_add(&mvsoc_bridge_pic, 64);
    158   1.1  kiyohara 	ih = intr_establish(KIRKWOOD_IRQ_BRIDGE, IPL_HIGH, IST_LEVEL_HIGH,
    159   1.1  kiyohara 	    pic_handle_intr, &mvsoc_bridge_pic);
    160   1.1  kiyohara 	KASSERT(ih != NULL);
    161   1.1  kiyohara 
    162   1.1  kiyohara 	find_pending_irqs = kirkwood_find_pending_irqs;
    163   1.1  kiyohara }
    164   1.1  kiyohara 
    165   1.1  kiyohara /* ARGSUSED */
    166   1.1  kiyohara static void
    167   1.4      matt kirkwood_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    168   1.4      matt 			  uint32_t irq_mask)
    169   1.1  kiyohara {
    170   1.4      matt 	const size_t reg = KIRKWOOD_MLMB_MIRQIMLR
    171   1.4      matt 	   + irqbase * (KIRKWOOD_MLMB_MIRQIMHR - KIRKWOOD_MLMB_MIRQIMLR) / 32;
    172   1.1  kiyohara 
    173   1.4      matt 	KASSERT(irqbase < 64);
    174   1.4      matt 	write_mlmbreg(reg, read_mlmbreg(reg) | irq_mask);
    175   1.1  kiyohara }
    176   1.1  kiyohara 
    177   1.1  kiyohara /* ARGSUSED */
    178   1.1  kiyohara static void
    179   1.4      matt kirkwood_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    180   1.4      matt 			uint32_t irq_mask)
    181   1.1  kiyohara {
    182   1.4      matt 	const size_t reg = KIRKWOOD_MLMB_MIRQIMLR
    183   1.4      matt 	   + irqbase * (KIRKWOOD_MLMB_MIRQIMHR - KIRKWOOD_MLMB_MIRQIMLR) / 32;
    184   1.1  kiyohara 
    185   1.4      matt 	KASSERT(irqbase < 64);
    186   1.4      matt 	write_mlmbreg(reg, read_mlmbreg(reg) & ~irq_mask);
    187   1.1  kiyohara }
    188   1.1  kiyohara 
    189   1.1  kiyohara /* ARGSUSED */
    190   1.1  kiyohara static void
    191   1.1  kiyohara kirkwood_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    192   1.1  kiyohara {
    193   1.1  kiyohara 	/* Nothing */
    194   1.1  kiyohara }
    195   1.1  kiyohara 
    196   1.1  kiyohara static void
    197   1.1  kiyohara kirkwood_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
    198   1.1  kiyohara {
    199   1.1  kiyohara 
    200   1.1  kiyohara 	strlcpy(buf, sources[pic->pic_irqbase + irq], len);
    201   1.1  kiyohara }
    202   1.1  kiyohara 
    203   1.1  kiyohara /*
    204   1.1  kiyohara  * Called with interrupts disabled
    205   1.1  kiyohara  */
    206   1.1  kiyohara static int
    207   1.1  kiyohara kirkwood_find_pending_irqs(void)
    208   1.1  kiyohara {
    209   1.4      matt 	int ipl = 0;
    210   1.4      matt 
    211   1.4      matt 	uint32_t causelow = read_mlmbreg(KIRKWOOD_MLMB_MICLR);
    212   1.4      matt 	uint32_t pendinglow = read_mlmbreg(KIRKWOOD_MLMB_MIRQIMLR);
    213   1.1  kiyohara 
    214   1.4      matt 	pendinglow &= causelow;
    215   1.4      matt 	if (pendinglow != 0)
    216   1.4      matt 		ipl |= pic_mark_pending_sources(&kirkwood_pic, 0, pendinglow);
    217   1.4      matt 
    218   1.5  kiyohara 	if ((causelow & (1 << KIRKWOOD_IRQ_HIGH)) == (1 << KIRKWOOD_IRQ_HIGH)) {
    219   1.4      matt 		uint32_t causehigh = read_mlmbreg(KIRKWOOD_MLMB_MICHR);
    220   1.4      matt 		uint32_t pendinghigh = read_mlmbreg(KIRKWOOD_MLMB_MIRQIMHR);
    221   1.4      matt 		pendinghigh &= causehigh;
    222   1.4      matt 		ipl |= pic_mark_pending_sources(&kirkwood_pic, 32, pendinghigh);
    223   1.4      matt 	}
    224   1.1  kiyohara 
    225   1.4      matt 	return ipl;
    226   1.1  kiyohara }
    227   1.1  kiyohara 
    228   1.1  kiyohara /*
    229   1.1  kiyohara  * Clock functions
    230   1.1  kiyohara  */
    231   1.1  kiyohara 
    232  1.10  kiyohara static void
    233  1.10  kiyohara kirkwood_getclks(vaddr_t iobase)
    234   1.1  kiyohara {
    235   1.1  kiyohara 	uint32_t reg;
    236   1.1  kiyohara 	uint16_t model;
    237   1.1  kiyohara 
    238   1.1  kiyohara #define MHz	* 1000 * 1000
    239   1.1  kiyohara 
    240   1.1  kiyohara 	model = mvsoc_model();
    241   1.6  kiyohara 	if (model == MARVELL_KIRKWOOD_88F6281 ||
    242   1.6  kiyohara 	    model == MARVELL_KIRKWOOD_88F6282)
    243   1.1  kiyohara 		mvTclk = 200 MHz;
    244   1.1  kiyohara 	else		/* 166MHz */
    245   1.1  kiyohara 		mvTclk = 166666667;
    246   1.1  kiyohara 
    247  1.11       rin 	reg = le32toh(*(volatile uint32_t *)(iobase + KIRKWOOD_MPP_BASE +
    248  1.11       rin 	    KIRKWOOD_MPP_SAMPLE_AT_RESET));
    249   1.1  kiyohara 	if (model == MARVELL_KIRKWOOD_88F6180) {
    250   1.1  kiyohara 		switch (reg & 0x0000001c) {
    251   1.2  kiyohara 		case 0x00000014: mvPclk =  600 MHz; break;
    252   1.2  kiyohara 		case 0x00000018: mvPclk =  800 MHz; break;
    253   1.1  kiyohara 		default:
    254   1.1  kiyohara 			panic("unknown mvPclk\n");
    255   1.1  kiyohara 		}
    256   1.1  kiyohara 		mvSysclk = 200 MHz;
    257   1.1  kiyohara 	} else {
    258   1.1  kiyohara 		switch (reg & 0x0040001a) {
    259   1.6  kiyohara 		case 0x00000002: mvPclk =  400 MHz; break;
    260   1.1  kiyohara 		case 0x00000008: mvPclk =  600 MHz; break;
    261   1.1  kiyohara 		case 0x00400008: mvPclk =  800 MHz; break;
    262   1.1  kiyohara 		case 0x0040000a: mvPclk = 1000 MHz; break;
    263   1.1  kiyohara 		case 0x00000012: mvPclk = 1200 MHz; break;
    264   1.6  kiyohara 		case 0x00000018: mvPclk = 1500 MHz; break;
    265   1.6  kiyohara 		case 0x0000001a: mvPclk = 1600 MHz; break;
    266   1.6  kiyohara 		case 0x00400018: mvPclk = 1800 MHz; break;
    267   1.6  kiyohara 		case 0x0040001a: mvPclk = 2000 MHz; break;
    268   1.1  kiyohara 		default:
    269   1.1  kiyohara 			panic("unknown mvPclk\n");
    270   1.1  kiyohara 		}
    271   1.1  kiyohara 
    272   1.1  kiyohara 		switch (reg & 0x000001e0) {
    273   1.6  kiyohara 		case 0x00000000: mvSysclk = mvPclk * 1 / 1; break;
    274   1.6  kiyohara 		case 0x00000040: mvSysclk = mvPclk * 1 / 2; break;
    275   1.1  kiyohara 		case 0x00000060: mvSysclk = mvPclk * 2 / 5; break;
    276   1.1  kiyohara 		case 0x00000080: mvSysclk = mvPclk * 1 / 3; break;
    277   1.1  kiyohara 		case 0x000000c0: mvSysclk = mvPclk * 1 / 4; break;
    278   1.6  kiyohara 		case 0x000000e0: mvSysclk = mvPclk * 2 / 9; break;
    279   1.6  kiyohara 		case 0x00000100: mvSysclk = mvPclk * 1 / 5; break;
    280   1.6  kiyohara 		case 0x00000120: mvSysclk = mvPclk * 1 / 6; break;
    281   1.1  kiyohara 		default:
    282   1.1  kiyohara 			panic("unknown mvSysclk\n");
    283   1.1  kiyohara 		}
    284   1.1  kiyohara 	}
    285   1.1  kiyohara 
    286   1.1  kiyohara #undef MHz
    287   1.1  kiyohara 
    288   1.1  kiyohara }
    289   1.8  kiyohara 
    290  1.10  kiyohara static int
    291   1.8  kiyohara kirkwood_clkgating(struct marvell_attach_args *mva)
    292   1.8  kiyohara {
    293   1.8  kiyohara 	uint32_t val;
    294   1.8  kiyohara 	int i;
    295   1.8  kiyohara 
    296   1.8  kiyohara 	for (i = 0; i < __arraycount(clkgatings); i++) {
    297   1.8  kiyohara 		if (clkgatings[i].offset == mva->mva_offset) {
    298   1.8  kiyohara 			val = read_mlmbreg(MVSOC_MLMB_CLKGATING);
    299   1.8  kiyohara 			if ((val & clkgatings[i].bits) == clkgatings[i].bits)
    300   1.8  kiyohara 				/* Clock enabled */
    301   1.8  kiyohara 				return 0;
    302   1.8  kiyohara 			return 1;
    303   1.8  kiyohara 		}
    304   1.8  kiyohara 	}
    305   1.8  kiyohara 	/* Clock Gating not support */
    306   1.8  kiyohara 	return 0;
    307   1.8  kiyohara }
    308