📄 setup.c
字号:
/* * 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/init.h>#include <linux/types.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/console.h>#include <linux/pci.h>#include <linux/pm.h>#include <linux/platform_device.h>#include <linux/clk.h>#include <asm/wbflush.h>#include <asm/reboot.h>#include <asm/irq.h>#include <asm/time.h>#include <asm/txx9tmr.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>#endif#include <linux/spi/spi.h>#include <asm/tx4938/spi.h>#include <asm/gpio.h>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 = bus.sysdata = 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++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -