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

📄 setup.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/arch/mips/tx4938/toshiba_rbtx4938/setup.c * * Setup pointers to hardware-dependent routines. * Copyright (C) 2000-2001 Toshiba Corporation * * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the * terms of the GNU General Public License version 2. This program is * licensed "as is" without any warranty of any kind, whether express * or implied. * * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) */#include <linux/config.h>#include <linux/init.h>#include <linux/types.h>#include <linux/ioport.h>#include <linux/proc_fs.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/console.h>#include <linux/pci.h>#include <asm/wbflush.h>#include <asm/reboot.h>#include <asm/irq.h>#include <asm/time.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/bootinfo.h>#include <asm/tx4938/rbtx4938.h>#ifdef CONFIG_SERIAL_TXX9#include <linux/tty.h>#include <linux/serial.h>#include <linux/serial_core.h>#endifextern void rbtx4938_time_init(void) __init;extern char * __init prom_getcmdline(void);static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr);/* These functions are used for rebooting or halting the machine*/extern void rbtx4938_machine_restart(char *command);extern void rbtx4938_machine_halt(void);extern void rbtx4938_machine_power_off(void);/* clocks */unsigned int txx9_master_clock;unsigned int txx9_cpu_clock;unsigned int txx9_gbus_clock;unsigned long rbtx4938_ce_base[8];unsigned long rbtx4938_ce_size[8];int txboard_pci66_mode;static int tx4938_pcic_trdyto;	/* default: disabled */static int tx4938_pcic_retryto;	/* default: disabled */static int tx4938_ccfg_toeon = 1;struct tx4938_pcic_reg *pcicptrs[4] = {       tx4938_pcicptr  /* default setting for TX4938 */};static struct {	unsigned long base;	unsigned long size;} phys_regions[16] __initdata;static int num_phys_regions  __initdata;#define PHYS_REGION_MINSIZE	0x10000void rbtx4938_machine_halt(void){        printk(KERN_NOTICE "System Halted\n");	local_irq_disable();	while (1)		__asm__(".set\tmips3\n\t"			"wait\n\t"			".set\tmips0");}void rbtx4938_machine_power_off(void){        rbtx4938_machine_halt();        /* no return */}void rbtx4938_machine_restart(char *command){	local_irq_disable();	printk("Rebooting...");	*rbtx4938_softresetlock_ptr = 1;	*rbtx4938_sfvol_ptr = 1;	*rbtx4938_softreset_ptr = 1;	wbflush();	while(1);}void __inittxboard_add_phys_region(unsigned long base, unsigned long size){	if (num_phys_regions >= ARRAY_SIZE(phys_regions)) {		printk("phys_region overflow\n");		return;	}	phys_regions[num_phys_regions].base = base;	phys_regions[num_phys_regions].size = size;	num_phys_regions++;}unsigned long __inittxboard_find_free_phys_region(unsigned long begin, unsigned long end,			      unsigned long size){	unsigned long base;	int i;	for (base = begin / size * size; base < end; base += size) {		for (i = 0; i < num_phys_regions; i++) {			if (phys_regions[i].size &&			    base <= phys_regions[i].base + (phys_regions[i].size - 1) &&			    base + (size - 1) >= phys_regions[i].base)				break;		}		if (i == num_phys_regions)			return base;	}	return 0;}unsigned long __inittxboard_find_free_phys_region_shrink(unsigned long begin, unsigned long end,				     unsigned long *size){	unsigned long sz, base;	for (sz = *size; sz >= PHYS_REGION_MINSIZE; sz /= 2) {		base = txboard_find_free_phys_region(begin, end, sz);		if (base) {			*size = sz;			return base;		}	}	return 0;}unsigned long __inittxboard_request_phys_region_range(unsigned long begin, unsigned long end,				  unsigned long size){	unsigned long base;	base = txboard_find_free_phys_region(begin, end, size);	if (base)		txboard_add_phys_region(base, size);	return base;}unsigned long __inittxboard_request_phys_region(unsigned long size){	unsigned long base;	unsigned long begin = 0, end = 0x20000000;	/* search low 512MB */	base = txboard_find_free_phys_region(begin, end, size);	if (base)		txboard_add_phys_region(base, size);	return base;}unsigned long __inittxboard_request_phys_region_shrink(unsigned long *size){	unsigned long base;	unsigned long begin = 0, end = 0x20000000;	/* search low 512MB */	base = txboard_find_free_phys_region_shrink(begin, end, size);	if (base)		txboard_add_phys_region(base, *size);	return base;}#ifdef CONFIG_PCIvoid __inittx4938_pcic_setup(struct tx4938_pcic_reg *pcicptr,		  struct pci_controller *channel,		  unsigned long pci_io_base,		  int extarb){	int i;	/* Disable All Initiator Space */	pcicptr->pciccfg &= ~(TX4938_PCIC_PCICCFG_G2PMEN(0)|			      TX4938_PCIC_PCICCFG_G2PMEN(1)|			      TX4938_PCIC_PCICCFG_G2PMEN(2)|			      TX4938_PCIC_PCICCFG_G2PIOEN);	/* GB->PCI mappings */	pcicptr->g2piomask = (channel->io_resource->end - channel->io_resource->start) >> 4;	pcicptr->g2piogbase = pci_io_base |#ifdef __BIG_ENDIAN		TX4938_PCIC_G2PIOGBASE_ECHG#else		TX4938_PCIC_G2PIOGBASE_BSDIS#endif		;	pcicptr->g2piopbase = 0;	for (i = 0; i < 3; i++) {		pcicptr->g2pmmask[i] = 0;		pcicptr->g2pmgbase[i] = 0;		pcicptr->g2pmpbase[i] = 0;	}	if (channel->mem_resource->end) {		pcicptr->g2pmmask[0] = (channel->mem_resource->end - channel->mem_resource->start) >> 4;		pcicptr->g2pmgbase[0] = channel->mem_resource->start |#ifdef __BIG_ENDIAN			TX4938_PCIC_G2PMnGBASE_ECHG#else			TX4938_PCIC_G2PMnGBASE_BSDIS#endif			;		pcicptr->g2pmpbase[0] = channel->mem_resource->start;	}	/* PCI->GB mappings (I/O 256B) */	pcicptr->p2giopbase = 0; /* 256B */	pcicptr->p2giogbase = 0;	/* PCI->GB mappings (MEM 512MB (64MB on R1.x)) */	pcicptr->p2gm0plbase = 0;	pcicptr->p2gm0pubase = 0;	pcicptr->p2gmgbase[0] = 0 |		TX4938_PCIC_P2GMnGBASE_TMEMEN |#ifdef __BIG_ENDIAN		TX4938_PCIC_P2GMnGBASE_TECHG#else		TX4938_PCIC_P2GMnGBASE_TBSDIS#endif		;	/* PCI->GB mappings (MEM 16MB) */	pcicptr->p2gm1plbase = 0xffffffff;	pcicptr->p2gm1pubase = 0xffffffff;	pcicptr->p2gmgbase[1] = 0;	/* PCI->GB mappings (MEM 1MB) */	pcicptr->p2gm2pbase = 0xffffffff; /* 1MB */	pcicptr->p2gmgbase[2] = 0;	pcicptr->pciccfg &= TX4938_PCIC_PCICCFG_GBWC_MASK;	/* Enable Initiator Memory Space */	if (channel->mem_resource->end)		pcicptr->pciccfg |= TX4938_PCIC_PCICCFG_G2PMEN(0);	/* Enable Initiator I/O Space */	if (channel->io_resource->end)		pcicptr->pciccfg |= TX4938_PCIC_PCICCFG_G2PIOEN;	/* Enable Initiator Config */	pcicptr->pciccfg |=		TX4938_PCIC_PCICCFG_ICAEN |		TX4938_PCIC_PCICCFG_TCAR;	/* Do not use MEMMUL, MEMINF: YMFPCI card causes M_ABORT. */	pcicptr->pcicfg1 = 0;	pcicptr->g2ptocnt &= ~0xffff;	if (tx4938_pcic_trdyto >= 0) {		pcicptr->g2ptocnt &= ~0xff;		pcicptr->g2ptocnt |= (tx4938_pcic_trdyto & 0xff);	}	if (tx4938_pcic_retryto >= 0) {		pcicptr->g2ptocnt &= ~0xff00;		pcicptr->g2ptocnt |= ((tx4938_pcic_retryto<<8) & 0xff00);	}	/* Clear All Local Bus Status */	pcicptr->pcicstatus = TX4938_PCIC_PCICSTATUS_ALL;	/* Enable All Local Bus Interrupts */	pcicptr->pcicmask = TX4938_PCIC_PCICSTATUS_ALL;	/* Clear All Initiator Status */	pcicptr->g2pstatus = TX4938_PCIC_G2PSTATUS_ALL;	/* Enable All Initiator Interrupts */	pcicptr->g2pmask = TX4938_PCIC_G2PSTATUS_ALL;	/* Clear All PCI Status Error */	pcicptr->pcistatus =		(pcicptr->pcistatus & 0x0000ffff) |		(TX4938_PCIC_PCISTATUS_ALL << 16);	/* Enable All PCI Status Error Interrupts */	pcicptr->pcimask = TX4938_PCIC_PCISTATUS_ALL;	if (!extarb) {		/* Reset Bus Arbiter */		pcicptr->pbacfg = TX4938_PCIC_PBACFG_RPBA;		pcicptr->pbabm = 0;		/* Enable Bus Arbiter */		pcicptr->pbacfg = TX4938_PCIC_PBACFG_PBAEN;	}      /* PCIC Int => IRC IRQ16 */	pcicptr->pcicfg2 =		    (pcicptr->pcicfg2 & 0xffffff00) | TX4938_IR_PCIC;	pcicptr->pcistatus = PCI_COMMAND_MASTER |		PCI_COMMAND_MEMORY |		PCI_COMMAND_PARITY | PCI_COMMAND_SERR;}int __inittx4938_report_pciclk(void){	unsigned long pcode = TX4938_REV_PCODE();	int pciclk = 0;	printk("TX%lx PCIC --%s PCICLK:",	       pcode,	       (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI66) ? " PCI66" : "");	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_PCICLKEN_ALL) {		switch ((unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIDIVMODE_MASK) {		case TX4938_CCFG_PCIDIVMODE_4:			pciclk = txx9_cpu_clock / 4; break;		case TX4938_CCFG_PCIDIVMODE_4_5:			pciclk = txx9_cpu_clock * 2 / 9; break;		case TX4938_CCFG_PCIDIVMODE_5:			pciclk = txx9_cpu_clock / 5; break;		case TX4938_CCFG_PCIDIVMODE_5_5:			pciclk = txx9_cpu_clock * 2 / 11; break;		case TX4938_CCFG_PCIDIVMODE_8:			pciclk = txx9_cpu_clock / 8; break;		case TX4938_CCFG_PCIDIVMODE_9:			pciclk = txx9_cpu_clock / 9; break;		case TX4938_CCFG_PCIDIVMODE_10:			pciclk = txx9_cpu_clock / 10; break;		case TX4938_CCFG_PCIDIVMODE_11:			pciclk = txx9_cpu_clock / 11; break;		}		printk("Internal(%dMHz)", pciclk / 1000000);	} else {		printk("External");		pciclk = -1;	}	printk("\n");	return pciclk;}void __init set_tx4938_pcicptr(int ch, struct tx4938_pcic_reg *pcicptr){	pcicptrs[ch] = pcicptr;}struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch){       return pcicptrs[ch];}static struct pci_dev *fake_pci_dev(struct pci_controller *hose,                                    int top_bus, int busnr, int devfn){	static struct pci_dev dev;	static struct pci_bus bus;	dev.sysdata = (void *)hose;	dev.devfn = devfn;	bus.number = busnr;	bus.ops = hose->pci_ops;	bus.parent = NULL;	dev.bus = &bus;	return &dev;}#define EARLY_PCI_OP(rw, size, type)                                    \static int early_##rw##_config_##size(struct pci_controller *hose,      \        int top_bus, int bus, int devfn, int offset, type value)        \{                                                                       \        return pci_##rw##_config_##size(                                \                fake_pci_dev(hose, top_bus, bus, devfn),                \                offset, value);                                         \}EARLY_PCI_OP(read, word, u16 *)int txboard_pci66_check(struct pci_controller *hose, int top_bus, int current_bus){	u32 pci_devfn;	unsigned short vid;	int devfn_start = 0;	int devfn_stop = 0xff;	int cap66 = -1;	u16 stat;	printk("PCI: Checking 66MHz capabilities...\n");	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {		early_read_config_word(hose, top_bus, current_bus, pci_devfn,				       PCI_VENDOR_ID, &vid);		if (vid == 0xffff) continue;		/* check 66MHz capability */		if (cap66 < 0)			cap66 = 1;		if (cap66) {			early_read_config_word(hose, top_bus, current_bus, pci_devfn,					       PCI_STATUS, &stat);			if (!(stat & PCI_STATUS_66MHZ)) {				printk(KERN_DEBUG "PCI: %02x:%02x not 66MHz capable.\n",				       current_bus, pci_devfn);				cap66 = 0;				break;			}		}	}	return cap66 > 0;}int __inittx4938_pciclk66_setup(void){	int pciclk;	/* Assert M66EN */	tx4938_ccfgptr->ccfg |= TX4938_CCFG_PCI66;	/* Double PCICLK (if possible) */	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_PCICLKEN_ALL) {		unsigned int pcidivmode =			tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIDIVMODE_MASK;		switch (pcidivmode) {		case TX4938_CCFG_PCIDIVMODE_8:		case TX4938_CCFG_PCIDIVMODE_4:			pcidivmode = TX4938_CCFG_PCIDIVMODE_4;			pciclk = txx9_cpu_clock / 4;			break;		case TX4938_CCFG_PCIDIVMODE_9:		case TX4938_CCFG_PCIDIVMODE_4_5:			pcidivmode = TX4938_CCFG_PCIDIVMODE_4_5;			pciclk = txx9_cpu_clock * 2 / 9;			break;		case TX4938_CCFG_PCIDIVMODE_10:		case TX4938_CCFG_PCIDIVMODE_5:			pcidivmode = TX4938_CCFG_PCIDIVMODE_5;			pciclk = txx9_cpu_clock / 5;			break;		case TX4938_CCFG_PCIDIVMODE_11:		case TX4938_CCFG_PCIDIVMODE_5_5:		default:			pcidivmode = TX4938_CCFG_PCIDIVMODE_5_5;			pciclk = txx9_cpu_clock * 2 / 11;			break;		}		tx4938_ccfgptr->ccfg =			(tx4938_ccfgptr->ccfg & ~TX4938_CCFG_PCIDIVMODE_MASK)			| pcidivmode;		printk(KERN_DEBUG "PCICLK: ccfg:%08lx\n",		       (unsigned long)tx4938_ccfgptr->ccfg);	} else {		pciclk = -1;	}	return pciclk;}extern struct pci_controller tx4938_pci_controller[];static int __init tx4938_pcibios_init(void){	unsigned long mem_base[2];	unsigned long mem_size[2] = {TX4938_PCIMEM_SIZE_0,TX4938_PCIMEM_SIZE_1}; /* MAX 128M,64K */	unsigned long io_base[2];	unsigned long io_size[2] = {TX4938_PCIIO_SIZE_0,TX4938_PCIIO_SIZE_1}; /* MAX 16M,64K */	/* TX4938 PCIC1: 64K MEM/IO is enough for ETH0,ETH1 */	int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);	PCIBIOS_MIN_IO = 0x00001000UL;	PCIBIOS_MIN_MEM = 0x01000000UL;	mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);	io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);	printk("TX4938 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n",	       (unsigned short)(tx4938_pcicptr->pciid >> 16),	       (unsigned short)(tx4938_pcicptr->pciid & 0xffff),	       (unsigned short)(tx4938_pcicptr->pciccrev & 0xff),	       extarb ? "External" : "Internal");	/* setup PCI area */	tx4938_pci_controller[0].io_resource->start = io_base[0];	tx4938_pci_controller[0].io_resource->end = (io_base[0] + io_size[0]) - 1;	tx4938_pci_controller[0].mem_resource->start = mem_base[0];	tx4938_pci_controller[0].mem_resource->end = mem_base[0] + mem_size[0] - 1;	set_tx4938_pcicptr(0, tx4938_pcicptr);	register_pci_controller(&tx4938_pci_controller[0]);	if (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI66) {		printk("TX4938_CCFG_PCI66 already configured\n");		txboard_pci66_mode = -1; /* already configured */	}	/* Reset PCI Bus */	*rbtx4938_pcireset_ptr = 0;	/* Reset PCIC */	tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST;	if (txboard_pci66_mode > 0)		tx4938_pciclk66_setup();	mdelay(10);	/* clear PCIC reset */	tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST;	*rbtx4938_pcireset_ptr = 1;	wbflush();	tx4938_report_pcic_status1(tx4938_pcicptr);	tx4938_report_pciclk();	tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb);	if (txboard_pci66_mode == 0 &&	    txboard_pci66_check(&tx4938_pci_controller[0], 0, 0)) {		/* Reset PCI Bus */		*rbtx4938_pcireset_ptr = 0;		/* Reset PCIC */		tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST;		tx4938_pciclk66_setup();		mdelay(10);		/* clear PCIC reset */		tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST;		*rbtx4938_pcireset_ptr = 1;		wbflush();		/* Reinitialize PCIC */		tx4938_report_pciclk();		tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb);	}

⌨️ 快捷键说明

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