⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 katana.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * arch/ppc/platforms/katana.c * * Board setup routines for the Artesyn Katana cPCI boards. * * Author: Tim Montgomery <timm@artesyncp.com> * Maintained by: Mark A. Greer <mgreer@mvista.com> * * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il * Based on code done by - Mark A. Greer <mgreer@mvista.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. *//* * Supports the Artesyn 750i, 752i, and 3750.  The 752i is virtually identical * to the 750i except that it has an mv64460 bridge. */#include <linux/config.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/kdev_t.h>#include <linux/console.h>#include <linux/initrd.h>#include <linux/root_dev.h>#include <linux/delay.h>#include <linux/seq_file.h>#include <linux/mtd/physmap.h>#include <linux/mv643xx.h>#include <linux/platform_device.h>#ifdef CONFIG_BOOTIMG#include <linux/bootimg.h>#endif#include <asm/io.h>#include <asm/unistd.h>#include <asm/page.h>#include <asm/time.h>#include <asm/smp.h>#include <asm/todc.h>#include <asm/bootinfo.h>#include <asm/ppcboot.h>#include <asm/mv64x60.h>#include <platforms/katana.h>#include <asm/machdep.h>static struct mv64x60_handle	bh;static katana_id_t		katana_id;static void __iomem		*cpld_base;static void __iomem		*sram_base;static u32			katana_flash_size_0;static u32			katana_flash_size_1;static u32			katana_bus_frequency;static struct pci_controller	katana_hose_a;unsigned char	__res[sizeof(bd_t)];/* PCI Interrupt routing */static int __initkatana_irq_lookup_750i(unsigned char idsel, unsigned char pin){	static char pci_irq_table[][4] = {		/*		 * PCI IDSEL/INTPIN->INTLINE		 *       A   B   C   D		 */		/* IDSEL 4  (PMC 1) */		{ KATANA_PCI_INTB_IRQ_750i, KATANA_PCI_INTC_IRQ_750i,			KATANA_PCI_INTD_IRQ_750i, KATANA_PCI_INTA_IRQ_750i },		/* IDSEL 5  (PMC 2) */		{ KATANA_PCI_INTC_IRQ_750i, KATANA_PCI_INTD_IRQ_750i,			KATANA_PCI_INTA_IRQ_750i, KATANA_PCI_INTB_IRQ_750i },		/* IDSEL 6 (T8110) */		{KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },		/* IDSEL 7 (unused) */		{0, 0, 0, 0 },		/* IDSEL 8 (Intel 82544) (752i only but doesn't harm 750i) */		{KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },	};	const long min_idsel = 4, max_idsel = 8, irqs_per_slot = 4;	return PCI_IRQ_TABLE_LOOKUP;}static int __initkatana_irq_lookup_3750(unsigned char idsel, unsigned char pin){	static char pci_irq_table[][4] = {		/*		 * PCI IDSEL/INTPIN->INTLINE		 *       A   B   C   D		 */		{ KATANA_PCI_INTA_IRQ_3750, 0, 0, 0 }, /* IDSEL 3 (BCM5691) */		{ KATANA_PCI_INTB_IRQ_3750, 0, 0, 0 }, /* IDSEL 4 (MV64360 #2)*/		{ KATANA_PCI_INTC_IRQ_3750, 0, 0, 0 }, /* IDSEL 5 (MV64360 #3)*/	};	const long min_idsel = 3, max_idsel = 5, irqs_per_slot = 4;	return PCI_IRQ_TABLE_LOOKUP;}static int __initkatana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin){	switch (katana_id) {	case KATANA_ID_750I:	case KATANA_ID_752I:		return katana_irq_lookup_750i(idsel, pin);	case KATANA_ID_3750:		return katana_irq_lookup_3750(idsel, pin);	default:		printk(KERN_ERR "Bogus board ID\n");		return 0;	}}/* Board info retrieval routines */void __initkatana_get_board_id(void){	switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) {	case KATANA_PRODUCT_ID_3750:		katana_id = KATANA_ID_3750;		break;	case KATANA_PRODUCT_ID_750i:		katana_id = KATANA_ID_750I;		break;	case KATANA_PRODUCT_ID_752i:		katana_id = KATANA_ID_752I;		break;	default:		printk(KERN_ERR "Unsupported board\n");	}}int __initkatana_get_proc_num(void){	u16		val;	u8		save_exclude;	static int	proc = -1;	static u8	first_time = 1;	if (first_time) {		if (katana_id != KATANA_ID_3750)			proc = 0;		else {			save_exclude = mv64x60_pci_exclude_bridge;			mv64x60_pci_exclude_bridge = 0;			early_read_config_word(bh.hose_b, 0,				PCI_DEVFN(0,0), PCI_DEVICE_ID, &val);			mv64x60_pci_exclude_bridge = save_exclude;			switch(val) {			case PCI_DEVICE_ID_KATANA_3750_PROC0:				proc = 0;				break;			case PCI_DEVICE_ID_KATANA_3750_PROC1:				proc = 1;				break;			case PCI_DEVICE_ID_KATANA_3750_PROC2:				proc = 2;				break;			default:				printk(KERN_ERR "Bogus Device ID\n");			}		}		first_time = 0;	}	return proc;}static inline intkatana_is_monarch(void){	return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) &		KATANA_CPLD_BD_CFG_3_MONARCH;}static void __initkatana_setup_bridge(void){	struct pci_controller hose;	struct mv64x60_setup_info si;	void __iomem *vaddr;	int i;	u32 v;	u16 val, type;	u8 save_exclude;	/*	 * Some versions of the Katana firmware mistakenly change the vendor	 * & device id fields in the bridge's pci device (visible via pci	 * config accesses).  This breaks mv64x60_init() because those values	 * are used to identify the type of bridge that's there.  Artesyn	 * claims that the subsystem vendor/device id's will have the correct	 * Marvell values so this code puts back the correct values from there.	 */	memset(&hose, 0, sizeof(hose));	vaddr = ioremap(CONFIG_MV64X60_NEW_BASE, MV64x60_INTERNAL_SPACE_SIZE);	setup_indirect_pci_nomap(&hose, vaddr + MV64x60_PCI0_CONFIG_ADDR,		vaddr + MV64x60_PCI0_CONFIG_DATA);	save_exclude = mv64x60_pci_exclude_bridge;	mv64x60_pci_exclude_bridge = 0;	early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val);	if (val != PCI_VENDOR_ID_MARVELL) {		early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),			PCI_SUBSYSTEM_VENDOR_ID, &val);		early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),			PCI_VENDOR_ID, val);		early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),			PCI_SUBSYSTEM_ID, &val);		early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),			PCI_DEVICE_ID, val);	}	/*	 * While we're in here, set the hotswap register correctly.	 * Turn off blue LED; mask ENUM#, clear insertion & extraction bits.	 */	early_read_config_dword(&hose, 0, PCI_DEVFN(0, 0),		MV64360_PCICFG_CPCI_HOTSWAP, &v);	v &= ~(1<<19);	v |= ((1<<17) | (1<<22) | (1<<23));	early_write_config_dword(&hose, 0, PCI_DEVFN(0, 0),		MV64360_PCICFG_CPCI_HOTSWAP, v);	/* While we're at it, grab the bridge type for later */	early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_DEVICE_ID, &type);	mv64x60_pci_exclude_bridge = save_exclude;	iounmap(vaddr);	memset(&si, 0, sizeof(si));	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;	si.pci_1.enable_bus = 1;	si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR;	si.pci_1.pci_io.pci_base_hi = 0;	si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR;	si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE;	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;	si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR;	si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR;	si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR;	si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE;	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;	si.pci_1.pci_cmd_bits = 0;	si.pci_1.latency_timer = 0x80;	for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {#if defined(CONFIG_NOT_COHERENT_CACHE)		si.cpu_prot_options[i] = 0;		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;		si.pci_1.acc_cntl_options[i] =			MV64360_PCI_ACC_CNTL_SNOOP_NONE |			MV64360_PCI_ACC_CNTL_SWAP_NONE |			MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |			MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;#else		si.cpu_prot_options[i] = 0;		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;		si.pci_1.acc_cntl_options[i] =			MV64360_PCI_ACC_CNTL_SNOOP_WB |			MV64360_PCI_ACC_CNTL_SWAP_NONE |			MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |			((type == PCI_DEVICE_ID_MARVELL_MV64360) ?				MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES :				MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES);#endif	}	/* Lookup PCI host bridges */	if (mv64x60_init(&bh, &si))		printk(KERN_WARNING "Bridge initialization failed.\n");	pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */	ppc_md.pci_swizzle = common_swizzle;	ppc_md.pci_map_irq = katana_map_irq;	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;	mv64x60_set_bus(&bh, 1, 0);	bh.hose_b->first_busno = 0;	bh.hose_b->last_busno = 0xff;	/*	 * Need to access hotswap reg which is in the pci config area of the	 * bridge's hose 0.  Note that pcibios_alloc_controller() can't be used	 * to alloc hose_a b/c that would make hose 0 known to the generic	 * pci code which we don't want.	 */	bh.hose_a = &katana_hose_a;	setup_indirect_pci_nomap(bh.hose_a,		bh.v_base + MV64x60_PCI0_CONFIG_ADDR,		bh.v_base + MV64x60_PCI0_CONFIG_DATA);}/* Bridge & platform setup routines */void __initkatana_intr_setup(void){	if (bh.type == MV64x60_TYPE_MV64460) /* As per instns from Marvell */		mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, 1 << 15);	/* MPP 8, 9, and 10 */	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff);	/* MPP 14 */	if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I))		mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0x0f000000);	/*	 * Define GPP 8,9,and 10 interrupt polarity as active low	 * input signal and level triggered	 */	mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x700);	mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, 0x700);	if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) {		mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, (1<<14));		mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, (1<<14));	}	/* Config GPP intr ctlr to respond to level trigger */	mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10));	if (bh.type == MV64x60_TYPE_MV64360) {		/* Erratum FEr PCI-#9 */		mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD,				(1<<4) | (1<<5) | (1<<6) | (1<<7));		mv64x60_set_bits(&bh, MV64x60_PCI1_CMD, (1<<8) | (1<<9));	} else {		mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<6) | (1<<7));		mv64x60_set_bits(&bh, MV64x60_PCI1_CMD,				(1<<4) | (1<<5) | (1<<8) | (1<<9));	}	/*	 * Dismiss and then enable interrupt on GPP interrupt cause	 * for CPU #0	 */	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~0x700);	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, 0x700);	if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) {		mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1<<14));		mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1<<14));	}	/*	 * Dismiss and then enable interrupt on CPU #0 high cause reg	 * BIT25 summarizes GPP interrupts 8-15	 */	mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25));}void __initkatana_setup_peripherals(void){	u32 base;	/* Set up windows for boot CS, soldered & socketed flash, and CPLD */	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,		 KATANA_BOOT_WINDOW_BASE, KATANA_BOOT_WINDOW_SIZE, 0);	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);	/* Assume firmware set up window sizes correctly for dev 0 & 1 */	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base,		&katana_flash_size_0);	if (katana_flash_size_0 > 0) {		mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,			 KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0);		bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);	}	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base,		&katana_flash_size_1);	if (katana_flash_size_1 > 0) {		mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,			 (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0),			 katana_flash_size_1, 0);		bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);	}	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,		 KATANA_SOCKET_BASE, KATANA_SOCKETED_FLASH_SIZE, 0);	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,		 KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0);	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);	cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,		 KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);	sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);	/* Set up Enet->SRAM window */	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,		KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0x2);	bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);	/* Give enet r/w access to memory region */	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1)));	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1)));	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1)));	mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));	mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,			 ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));	/* Must wait until window set up before retrieving board id */	katana_get_board_id();	/* Enumerate pci bus (must know board id before getting proc number) */	if (katana_get_proc_num() == 0)		bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, 0);#if defined(CONFIG_NOT_COHERENT_CACHE)	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000);#else	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);#endif	/*	 * Setting the SRAM to 0. Note that this generates parity errors on	 * internal data path in SRAM since it's first time accessing it	 * while after reset it's not configured.	 */	memset(sram_base, 0, MV64360_SRAM_SIZE);	/* Only processor zero [on 3750] is an PCI interrupt controller */	if (katana_get_proc_num() == 0)		katana_intr_setup();}static void __initkatana_enable_ipmi(void){	u8 reset_out;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -