[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/arch/mips/sni/pcimt.c b/src/kernel/linux/v4.14/arch/mips/sni/pcimt.c
new file mode 100644
index 0000000..12336c2
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/mips/sni/pcimt.c
@@ -0,0 +1,332 @@
+/*
+ * PCIMT specific code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+
+#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF)
+#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE)
+
+static void __init sni_pcimt_sc_init(void)
+{
+	unsigned int scsiz, sc_size;
+
+	scsiz = cacheconf & 7;
+	if (scsiz == 0) {
+		printk("Second level cache is deactivated.\n");
+		return;
+	}
+	if (scsiz >= 6) {
+		printk("Invalid second level cache size configured, "
+		       "deactivating second level cache.\n");
+		cacheconf = 0;
+		return;
+	}
+
+	sc_size = 128 << scsiz;
+	printk("%dkb second level cache detected, deactivating.\n", sc_size);
+	cacheconf = 0;
+}
+
+
+/*
+ * A bit more gossip about the iron we're running on ...
+ */
+static inline void sni_pcimt_detect(void)
+{
+	char boardtype[80];
+	unsigned char csmsr;
+	char *p = boardtype;
+	unsigned int asic;
+
+	csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
+
+	p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300");
+	if ((csmsr & 0x80) == 0)
+		p += sprintf(p, ", board revision %s",
+			     (csmsr & 0x20) ? "D" : "C");
+	asic = csmsr & 0x80;
+	asic = (csmsr & 0x08) ? asic : !asic;
+	p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
+	printk("%s.\n", boardtype);
+}
+
+#define PORT(_base,_irq)				\
+	{						\
+		.iobase		= _base,		\
+		.irq		= _irq,			\
+		.uartclk	= 1843200,		\
+		.iotype		= UPIO_PORT,		\
+		.flags		= UPF_BOOT_AUTOCONF,	\
+	}
+
+static struct plat_serial8250_port pcimt_data[] = {
+	PORT(0x3f8, 4),
+	PORT(0x2f8, 3),
+	{ },
+};
+
+static struct platform_device pcimt_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= pcimt_data,
+	},
+};
+
+static struct resource pcimt_cmos_rsrc[] = {
+	{
+		.start = 0x70,
+		.end   = 0x71,
+		.flags = IORESOURCE_IO
+	},
+	{
+		.start = 8,
+		.end   = 8,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device pcimt_cmos_device = {
+	.name		= "rtc_cmos",
+	.num_resources	= ARRAY_SIZE(pcimt_cmos_rsrc),
+	.resource	= pcimt_cmos_rsrc
+};
+
+
+static struct resource sni_io_resource = {
+	.start	= 0x00000000UL,
+	.end	= 0x03bfffffUL,
+	.name	= "PCIMT IO MEM",
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pcimt_io_resources[] = {
+	{
+		.start	= 0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x60,
+		.end	= 0x6f,
+		.name	= "keyboard",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xcfc,
+		.end	= 0xcff,
+		.name	= "PCI config data",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
+static struct resource pcimt_mem_resources[] = {
+	{
+		/*
+		 * this region should only be 4 bytes long,
+		 * but it's 16MB on all RM300C I've checked
+		 */
+		.start	= 0x1a000000,
+		.end	= 0x1affffff,
+		.name	= "PCI INT ACK",
+		.flags	= IORESOURCE_BUSY
+	}
+};
+
+static struct resource sni_mem_resource = {
+	.start	= 0x18000000UL,
+	.end	= 0x1fbfffffUL,
+	.name	= "PCIMT PCI MEM",
+	.flags	= IORESOURCE_MEM
+};
+
+static void __init sni_pcimt_resource_init(void)
+{
+	int i;
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
+		request_resource(&sni_io_resource, pcimt_io_resources + i);
+	/* request MEM space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+		request_resource(&sni_mem_resource, pcimt_mem_resources + i);
+}
+
+extern struct pci_ops sni_pcimt_ops;
+
+#ifdef CONFIG_PCI
+static struct pci_controller sni_controller = {
+	.pci_ops	= &sni_pcimt_ops,
+	.mem_resource	= &sni_mem_resource,
+	.mem_offset	= 0x00000000UL,
+	.io_resource	= &sni_io_resource,
+	.io_offset	= 0x00000000UL,
+	.io_map_base	= SNI_PORT_BASE
+};
+#endif
+
+static void enable_pcimt_irq(struct irq_data *d)
+{
+	unsigned int mask = 1 << (d->irq - PCIMT_IRQ_INT2);
+
+	*(volatile u8 *) PCIMT_IRQSEL |= mask;
+}
+
+void disable_pcimt_irq(struct irq_data *d)
+{
+	unsigned int mask = ~(1 << (d->irq - PCIMT_IRQ_INT2));
+
+	*(volatile u8 *) PCIMT_IRQSEL &= mask;
+}
+
+static struct irq_chip pcimt_irq_type = {
+	.name = "PCIMT",
+	.irq_mask = disable_pcimt_irq,
+	.irq_unmask = enable_pcimt_irq,
+};
+
+/*
+ * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
+ * button interrupts.  Later ...
+ */
+static void pcimt_hwint0(void)
+{
+	panic("Received int0 but no handler yet ...");
+}
+
+/*
+ * hwint 1 deals with EISA and SCSI interrupts,
+ *
+ * The EISA_INT bit in CSITPEND is high active, all others are low active.
+ */
+static void pcimt_hwint1(void)
+{
+	u8 pend = *(volatile char *)PCIMT_CSITPEND;
+	unsigned long flags;
+
+	if (pend & IT_EISA) {
+		int irq;
+		/*
+		 * Note: ASIC PCI's builtin interrupt acknowledge feature is
+		 * broken.  Using it may result in loss of some or all i8259
+		 * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
+		 */
+		irq = i8259_irq();
+		if (unlikely(irq < 0))
+			return;
+
+		do_IRQ(irq);
+	}
+
+	if (!(pend & IT_SCSI)) {
+		flags = read_c0_status();
+		clear_c0_status(ST0_IM);
+		do_IRQ(PCIMT_IRQ_SCSI);
+		write_c0_status(flags);
+	}
+}
+
+/*
+ * hwint 3 should deal with the PCI A - D interrupts,
+ */
+static void pcimt_hwint3(void)
+{
+	u8 pend = *(volatile char *)PCIMT_CSITPEND;
+	int irq;
+
+	pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
+	pend ^= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
+	clear_c0_status(IE_IRQ3);
+	irq = PCIMT_IRQ_INT2 + ffs(pend) - 1;
+	do_IRQ(irq);
+	set_c0_status(IE_IRQ3);
+}
+
+static void sni_pcimt_hwint(void)
+{
+	u32 pending = read_c0_cause() & read_c0_status();
+
+	if (pending & C_IRQ5)
+		do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+	else if (pending & C_IRQ4)
+		do_IRQ(MIPS_CPU_IRQ_BASE + 6);
+	else if (pending & C_IRQ3)
+		pcimt_hwint3();
+	else if (pending & C_IRQ1)
+		pcimt_hwint1();
+	else if (pending & C_IRQ0) {
+		pcimt_hwint0();
+	}
+}
+
+void __init sni_pcimt_irq_init(void)
+{
+	int i;
+
+	*(volatile u8 *) PCIMT_IRQSEL = IT_ETH | IT_EISA;
+	mips_cpu_irq_init();
+	/* Actually we've got more interrupts to handle ...  */
+	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++)
+		irq_set_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
+	sni_hwint = sni_pcimt_hwint;
+	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
+}
+
+void __init sni_pcimt_init(void)
+{
+	sni_pcimt_detect();
+	sni_pcimt_sc_init();
+	ioport_resource.end = sni_io_resource.end;
+#ifdef CONFIG_PCI
+	PCIBIOS_MIN_IO = 0x9000;
+	register_pci_controller(&sni_controller);
+#endif
+	sni_pcimt_resource_init();
+}
+
+static int __init snirm_pcimt_setup_devinit(void)
+{
+	switch (sni_brd_type) {
+	case SNI_BRD_PCI_MTOWER:
+	case SNI_BRD_PCI_DESKTOP:
+	case SNI_BRD_PCI_MTOWER_CPLUS:
+		platform_device_register(&pcimt_serial8250_device);
+		platform_device_register(&pcimt_cmos_device);
+		break;
+	}
+
+	return 0;
+}
+
+device_initcall(snirm_pcimt_setup_devinit);