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

📄 ixdp2800.c

📁 linux 内核源代码
💻 C
字号:
/* * arch/arm/mach-ixp2000/ixdp2800.c * * IXDP2800 platform support * * Original Author: Jeffrey Daly <jeffrey.daly@intel.com> * Maintainer: Deepak Saxena <dsaxena@plexity.net> * * Copyright (C) 2002 Intel Corp. * Copyright (C) 2003-2004 MontaVista Software, Inc. * *  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. */#include <linux/kernel.h>#include <linux/init.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/device.h>#include <linux/bitops.h>#include <linux/pci.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/delay.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/pgtable.h>#include <asm/page.h>#include <asm/system.h>#include <asm/hardware.h>#include <asm/mach-types.h>#include <asm/mach/pci.h>#include <asm/mach/map.h>#include <asm/mach/irq.h>#include <asm/mach/time.h>#include <asm/mach/flash.h>#include <asm/mach/arch.h>/************************************************************************* * IXDP2800 timer tick *************************************************************************/static void __init ixdp2800_timer_init(void){	ixp2000_init_time(50000000);}static struct sys_timer ixdp2800_timer = {	.init		= ixdp2800_timer_init,	.offset		= ixp2000_gettimeoffset,};/************************************************************************* * IXDP2800 PCI *************************************************************************/static void __init ixdp2800_slave_disable_pci_master(void){	*IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);}static void __init ixdp2800_master_wait_for_slave(void){	volatile u32 *addr;	printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure "			 "its BAR sizes\n");	addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,					PCI_BASE_ADDRESS_1);	do {		*addr = 0xffffffff;		cpu_relax();	} while (*addr != 0xfe000008);	addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,					PCI_BASE_ADDRESS_2);	do {		*addr = 0xffffffff;		cpu_relax();	} while (*addr != 0xc0000008);	/*	 * Configure the slave's SDRAM BAR by hand.	 */	*addr = 0x40000008;}static void __init ixdp2800_slave_wait_for_master_enable(void){	printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n");	while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0)		cpu_relax();}void __init ixdp2800_pci_preinit(void){	printk("ixdp2x00_pci_preinit called\n");	*IXP2000_PCI_ADDR_EXT = 0x0001e000;	if (!ixdp2x00_master_npu())		ixdp2800_slave_disable_pci_master();	*IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;	*IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;	ixp2000_pci_preinit();	if (ixdp2x00_master_npu()) {		/*		 * Wait until the slave set its SRAM/SDRAM BAR sizes		 * correctly before we proceed to scan and enumerate		 * the bus.		 */		ixdp2800_master_wait_for_slave();		/*		 * We configure the SDRAM BARs by hand because they		 * are 1G and fall outside of the regular allocated		 * PCI address space.		 */		*IXP2000_PCI_SDRAM_BAR = 0x00000008;	} else {		/*		 * Wait for the master to complete scanning the bus		 * and assigning resources before we proceed to scan		 * the bus ourselves.  Set pci=firmware to honor the		 * master's resource assignment.		 */		ixdp2800_slave_wait_for_master_enable();		pcibios_setup("firmware");	}}/* * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside * of the regular PCI window, because there's only 512M of outbound PCI * memory window on each IXP, while we need 1G for each of the BARs. */static void __devinit ixp2800_pci_fixup(struct pci_dev *dev){	if (machine_is_ixdp2800()) {		dev->resource[2].start = 0;		dev->resource[2].end   = 0;		dev->resource[2].flags = 0;	}}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, ixp2800_pci_fixup);static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys){	sys->mem_offset = 0x00000000;	ixp2000_pci_setup(nr, sys);	return 1;}static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin){	if (ixdp2x00_master_npu()) {		/*		 * Root bus devices.  Slave NPU is only one with interrupt.		 * Everything else, we just return -1 which is invalid.		 */		if(!dev->bus->self) {			if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )				return IRQ_IXDP2800_INGRESS_NPU;			return -1;		}		/*		 * Bridge behind the PMC slot.		 */		if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&			dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&			!dev->bus->parent->self->bus->parent)				  return IRQ_IXDP2800_PMC;		/*		 * Device behind the first bridge		 */		if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {			switch(dev->devfn) {				case IXDP2X00_PMC_DEVFN:					return IRQ_IXDP2800_PMC;								case IXDP2800_MASTER_ENET_DEVFN:					return IRQ_IXDP2800_EGRESS_ENET;				case IXDP2800_SWITCH_FABRIC_DEVFN:					return IRQ_IXDP2800_FABRIC;			}		}		return -1;	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */}static void __init ixdp2800_master_enable_slave(void){	volatile u32 *addr;	printk(KERN_INFO "IXDP2800: enabling slave NPU\n");	addr = (volatile u32 *)ixp2000_pci_config_addr(0,					IXDP2X00_SLAVE_NPU_DEVFN,					PCI_COMMAND);	*addr |= PCI_COMMAND_MASTER;}static void __init ixdp2800_master_wait_for_slave_bus_scan(void){	volatile u32 *addr;	printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n");	addr = (volatile u32 *)ixp2000_pci_config_addr(0,					IXDP2X00_SLAVE_NPU_DEVFN,					PCI_COMMAND);	while ((*addr & PCI_COMMAND_MEMORY) == 0)		cpu_relax();}static void __init ixdp2800_slave_signal_bus_scan_completion(void){	printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n");	*IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY;}static void __init ixdp2800_pci_postinit(void){	if (!ixdp2x00_master_npu()) {		ixdp2x00_slave_pci_postinit();		ixdp2800_slave_signal_bus_scan_completion();	}}struct __initdata hw_pci ixdp2800_pci __initdata = {	.nr_controllers	= 1,	.setup		= ixdp2800_pci_setup,	.preinit	= ixdp2800_pci_preinit,	.postinit	= ixdp2800_pci_postinit,	.scan		= ixp2000_pci_scan_bus,	.map_irq	= ixdp2800_pci_map_irq,};int __init ixdp2800_pci_init(void){	if (machine_is_ixdp2800()) {		struct pci_dev *dev;		pci_common_init(&ixdp2800_pci);		if (ixdp2x00_master_npu()) {			dev = pci_get_bus_and_slot(1, IXDP2800_SLAVE_ENET_DEVFN);			pci_remove_bus_device(dev);			pci_dev_put(dev);			ixdp2800_master_enable_slave();			ixdp2800_master_wait_for_slave_bus_scan();		} else {			dev = pci_get_bus_and_slot(1, IXDP2800_MASTER_ENET_DEVFN);			pci_remove_bus_device(dev);			pci_dev_put(dev);		}	}	return 0;}subsys_initcall(ixdp2800_pci_init);void __init ixdp2800_init_irq(void){	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);}MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")	/* Maintainer: MontaVista Software, Inc. */	.phys_io	= IXP2000_UART_PHYS_BASE,	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,	.boot_params	= 0x00000100,	.map_io		= ixdp2x00_map_io,	.init_irq	= ixdp2800_init_irq,	.timer		= &ixdp2800_timer,	.init_machine	= ixdp2x00_init_machine,MACHINE_END

⌨️ 快捷键说明

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