From: Andy P. <at...@us...> - 2002-04-10 18:30:55
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/mips/ddb5xxx/common In directory usw-pr-cvs1:/tmp/cvs-serv20728/mips/ddb5xxx/common Added Files: Makefile irq.c irq_cpu.c nile4.c pci.c pci_auto.c prom.c rtc_ds1386.c Log Message: synch 2.4.15 commit 39 --- NEW FILE --- # # Makefile for the common code of NEC DDB-Vrc5xxx board # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # .S.s: $(CPP) $(CFLAGS) $< -o $*.s .S.o: $(CC) $(CFLAGS) -c $< -o $*.o O_TARGET:= ddb5xxx.o obj-y += irq.o irq_cpu.o nile4.o prom.o pci.o pci_auto.o rtc_ds1386.o include $(TOPDIR)/Rules.make --- NEW FILE --- /* * Copyright 2001 MontaVista Software Inc. * Author: js...@mv... or js...@ju... * * arch/mips/ddb5xxx/common/irq.c * Common irq code for DDB boards. This really should belong * arch/mips/kernel/irq.c. Need to talk to Ralf. * * 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/config.h> #include <linux/init.h> void (*irq_setup)(void); void __init init_IRQ(void) { #ifdef CONFIG_REMOTE_DEBUG extern void breakpoint(void); extern void set_debug_traps(void); printk("Wait for gdb client connection ...\n"); set_debug_traps(); breakpoint(); #endif /* invoke board-specific irq setup */ irq_setup(); } --- NEW FILE --- /*********************************************************************** * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, js...@mv... or js...@ju... * * arch/mips/ddb5xxx/common/irq_cpu.c * This file define the irq handler for MIPS CPU interrupts. * * 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. *********************************************************************** */ /* * Almost all MIPS CPUs define 8 interrupt sources. They are typically * level triggered (i.e., cannot be cleared from CPU; must be cleared from * device). The first two are software interrupts. The last one is * usually cpu timer interrupt if coutner register is present. * * This file exports one global function: * mips_cpu_irq_init(u32 irq_base); */ #include <linux/irq.h> #include <linux/types.h> #include <linux/kernel.h> #include <asm/mipsregs.h> /* [jsun] sooner or later we should move this debug stuff to MIPS common */ #include <asm/ddb5xxx/debug.h> static int mips_cpu_irq_base=-1; static void mips_cpu_irq_enable(unsigned int irq) { MIPS_ASSERT(mips_cpu_irq_base != -1); MIPS_ASSERT(irq >= mips_cpu_irq_base); MIPS_ASSERT(irq < mips_cpu_irq_base+8); clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8)); set_cp0_status(1 << (irq - mips_cpu_irq_base + 8)); } static void mips_cpu_irq_disable(unsigned int irq) { MIPS_ASSERT(mips_cpu_irq_base != -1); MIPS_ASSERT(irq >= mips_cpu_irq_base); MIPS_ASSERT(irq < mips_cpu_irq_base+8); clear_cp0_status(1 << (irq - mips_cpu_irq_base + 8)); } static unsigned int mips_cpu_irq_startup(unsigned int irq) { mips_cpu_irq_enable(irq); return 0; } #define mips_cpu_irq_shutdown mips_cpu_irq_disable static void mips_cpu_irq_ack(unsigned int irq) { MIPS_ASSERT(mips_cpu_irq_base != -1); MIPS_ASSERT(irq >= mips_cpu_irq_base); MIPS_ASSERT(irq < mips_cpu_irq_base+8); /* although we attemp to clear the IP bit in cause reigster, I think * usually it is cleared by device (irq source) */ clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8)); /* I am not fully convinced that I should disable irq here */ } static void mips_cpu_irq_end(unsigned int irq) { MIPS_ASSERT(mips_cpu_irq_base != -1); MIPS_ASSERT(irq >= mips_cpu_irq_base); MIPS_ASSERT(irq < mips_cpu_irq_base+8); /* I am not fully convinced that I should enable irq here */ } static hw_irq_controller mips_cpu_irq_controller = { "CPU_irq", mips_cpu_irq_startup, mips_cpu_irq_shutdown, mips_cpu_irq_enable, mips_cpu_irq_disable, mips_cpu_irq_ack, mips_cpu_irq_end, NULL /* no affinity stuff for UP */ }; void mips_cpu_irq_init(u32 irq_base) { extern irq_desc_t irq_desc[]; u32 i; for (i= irq_base; i< irq_base+8; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].handler = &mips_cpu_irq_controller; } mips_cpu_irq_base = irq_base; } --- NEW FILE --- /*********************************************************************** * * Copyright 2001 MontaVista Software Inc. * Author: js...@mv... or js...@ju... * * arch/mips/ddb5xxx/common/nile4.c * misc low-level routines for vrc-5xxx controllers. * * derived from original code by Geert Uytterhoeven <ge...@so...> * * 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/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <asm/ddb5xxx/ddb5xxx.h> #include <asm/ddb5xxx/debug.h> u32 ddb_calc_pdar(u32 phys, u32 size, int width, int on_memory_bus, int pci_visible) { u32 maskbits; u32 widthbits; switch (size) { #if 0 /* We don't support 4 GB yet */ case 0x100000000: /* 4 GB */ maskbits = 4; break; #endif case 0x80000000: /* 2 GB */ maskbits = 5; break; case 0x40000000: /* 1 GB */ maskbits = 6; break; case 0x20000000: /* 512 MB */ maskbits = 7; break; case 0x10000000: /* 256 MB */ maskbits = 8; break; case 0x08000000: /* 128 MB */ maskbits = 9; break; case 0x04000000: /* 64 MB */ maskbits = 10; break; case 0x02000000: /* 32 MB */ maskbits = 11; break; case 0x01000000: /* 16 MB */ maskbits = 12; break; case 0x00800000: /* 8 MB */ maskbits = 13; break; case 0x00400000: /* 4 MB */ maskbits = 14; break; case 0x00200000: /* 2 MB */ maskbits = 15; break; case 0: /* OFF */ maskbits = 0; break; default: panic("nile4_set_pdar: unsupported size %p\n", (void *) size); } switch (width) { case 8: widthbits = 0; break; case 16: widthbits = 1; break; case 32: widthbits = 2; break; case 64: widthbits = 3; break; default: panic("nile4_set_pdar: unsupported width %d\n", width); } return maskbits | (on_memory_bus ? 0x10 : 0) | (pci_visible ? 0x20 : 0) | (widthbits << 6) | (phys & 0xffe00000); } void ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width, int on_memory_bus, int pci_visible) { u32 temp= ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible); ddb_out32(pdar, temp); ddb_out32(pdar + 4, 0); /* * When programming a PDAR, the register should be read immediately * after writing it. This ensures that address decoders are properly * configured. * [jsun] is this really necesary? */ ddb_in32(pdar); ddb_in32(pdar + 4); } /* * routines that mess with PCIINITx registers */ void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options) { switch (type) { case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */ case DDB_PCICMD_IO: /* PCI I/O Space */ case DDB_PCICMD_MEM: /* PCI Memory Space */ case DDB_PCICMD_CFG: /* PCI Configuration Space */ break; default: panic("nile4_set_pmr: invalid type %d\n", type); } ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options ); ddb_out32(pmr + 4, 0); } --- NEW FILE --- /*********************************************************************** * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, js...@mv... or js...@ju... * * arch/mips/ddb5xxx/common/pci.c * Common PCI routines for DDB5xxx - as a matter of fact, meant for all * MIPS machines. * * 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. *********************************************************************** */ /* * This file contains common PCI routines meant to be shared for * all MIPS machines. * * Strategies: * * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) * TODO: this shold be optional for some machines where they do have * a real "pcibios" that does resource assignment. * * . We then use pci_scan_bus() to "discover" all the resources for * later use by Linux. * * . We finally reply on a board supplied function, pcibios_fixup_irq(), to * to assign the interrupts. We may use setup-irq.c under drivers/pci * later. * * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), * because we assume all PCI devices should have the resources correctly * assigned and recorded. * * Limitations: * * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus * into a contiguous range. * * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical * address space. * * . In the case of IO space, it starts from 0, and the beginning address * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. * * . These are the current MIPS limitations (by ioremap, etc). In the * future, we may remove them. * * Credits: * Most of the code are derived from the pci routines from PPC and Alpha, * which were mostly writtne by * Cort Dougan, co...@fs... * Matt Porter, mp...@mv... * Dave Rusling dav...@re... * David Mosberger da...@cs... */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> #include <linux/pci.h> #include <asm/ddb5xxx/pci.h> #include <asm/ddb5xxx/debug.h> struct pci_fixup pcibios_fixups[] = { {0} }; extern int pciauto_assign_resources(int busno, struct pci_channel * hose); void __init pcibios_init(void) { struct pci_channel *p; struct pci_bus *bus; int busno; /* assign resources */ busno=0; for (p= mips_pci_channels; p->pci_ops != NULL; p++) { busno = pciauto_assign_resources(busno, p) + 1; } /* scan the buses */ busno = 0; for (p= mips_pci_channels; p->pci_ops != NULL; p++) { bus = pci_scan_bus(busno, p->pci_ops, p); busno = bus->subordinate+1; } /* fixup irqs (board specific routines) */ pcibios_fixup_irqs(); /* * should we do a fixup of ioport_resource and iomem_resource * based on mips_pci_channels? * Let us wait and see if this is a common need and whether there * are exceptions. Until then, each board should adjust them * perhaps in their setup() function. */ } int pcibios_enable_device(struct pci_dev *dev) { /* pciauto_assign_resources() will enable all devices found */ return 0; } unsigned long __init pci_bridge_check_io(struct pci_dev *bridge) { u16 io; pci_read_config_word(bridge, PCI_IO_BASE, &io); if (!io) { pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); pci_read_config_word(bridge, PCI_IO_BASE, &io); pci_write_config_word(bridge, PCI_IO_BASE, 0x0); } if (io) return IORESOURCE_IO; printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", bridge->name); return 0; } void __init pcibios_fixup_bus(struct pci_bus *bus) { /* Propogate hose info into the subordinate devices. */ struct pci_channel *hose = bus->sysdata; struct pci_dev *dev = bus->self; if (!dev) { /* Root bus */ bus->resource[0] = hose->io_resource; bus->resource[1] = hose->mem_resource; } else { /* This is a bridge. Do not care how it's initialized, just link its resources to the bus ones */ int i; for(i=0; i<3; i++) { bus->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; bus->resource[i]->name = bus->name; } bus->resource[0]->flags |= pci_bridge_check_io(dev); bus->resource[1]->flags |= IORESOURCE_MEM; /* For now, propogate hose limits to the bus; we'll adjust them later. */ bus->resource[0]->end = hose->io_resource->end; bus->resource[1]->end = hose->mem_resource->end; /* Turn off downstream PF memory address range by default */ bus->resource[2]->start = 1024*1024; bus->resource[2]->end = bus->resource[2]->start - 1; } } char *pcibios_setup(char *str) { return str; } void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { /* this should not be called */ MIPS_ASSERT(1 == 0); } void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *res, int resource) { /* this should not be called */ MIPS_ASSERT(1 == 0); } --- NEW FILE --- /* * arch/ppc/kernel/pci_auto.c * * PCI autoconfiguration library * * Author: Matt Porter <mp...@mv...> * * Copyright 2000, 2001 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. */ /* * Modified for MIPS by Jun Sun, js...@mv... * * . Simplify the interface between pci_auto and the rest: a single function. * . Assign resources from low address to upper address. * . change most int to u32. */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> #include <linux/pci.h> #include <asm/ddb5xxx/pci.h> #include <asm/ddb5xxx/debug.h> #define DEBUG #ifdef DEBUG #define DBG(x...) printk(x) #else #define DBG(x...) #endif /* These are used for config access before all the PCI probing has been done. */ int early_read_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 *val); int early_read_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 *val); int early_read_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 *val); int early_write_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 val); int early_write_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 val); int early_write_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 val); static u32 pciauto_lower_iospc; static u32 pciauto_upper_iospc; static u32 pciauto_lower_memspc; static u32 pciauto_upper_memspc; void __init pciauto_setup_bars(struct pci_channel *hose, int current_bus, int pci_devfn) { u32 bar_response, bar_size, bar_value; u32 bar, addr_mask, bar_nr = 0; u32 * upper_limit; u32 * lower_limit; int found_mem64 = 0; DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n", current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) ); for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) { /* Tickle the BAR and get the response */ early_write_config_dword(hose, current_bus, pci_devfn, bar, 0xffffffff); early_read_config_dword(hose, current_bus, pci_devfn, bar, &bar_response); /* If BAR is not implemented go to the next BAR */ if (!bar_response) continue; /* Check the BAR type and set our address mask */ if (bar_response & PCI_BASE_ADDRESS_SPACE) { addr_mask = PCI_BASE_ADDRESS_IO_MASK; upper_limit = &pciauto_upper_iospc; lower_limit = &pciauto_lower_iospc; DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr); } else { if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) found_mem64 = 1; addr_mask = PCI_BASE_ADDRESS_MEM_MASK; upper_limit = &pciauto_upper_memspc; lower_limit = &pciauto_lower_memspc; DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr); } /* Calculate requested size */ bar_size = ~(bar_response & addr_mask) + 1; /* Allocate a base address */ bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; MIPS_ASSERT(bar_value + bar_size <= *upper_limit); /* Write it out and update our limit */ early_write_config_dword(hose, current_bus, pci_devfn, bar, bar_value); *lower_limit = bar_value + bar_size; /* * If we are a 64-bit decoder then increment to the * upper 32 bits of the bar and force it to locate * in the lower 4GB of memory. */ if (found_mem64) { bar += 4; early_write_config_dword(hose, current_bus, pci_devfn, bar, 0x00000000); } bar_nr++; DBG("size=0x%x, address=0x%x\n", bar_size, bar_value); } } void __init pciauto_prescan_setup_bridge(struct pci_channel *hose, int current_bus, int pci_devfn, int sub_bus) { int cmdstat; /* Configure bus number registers */ early_write_config_byte(hose, current_bus, pci_devfn, PCI_PRIMARY_BUS, current_bus); early_write_config_byte(hose, current_bus, pci_devfn, PCI_SECONDARY_BUS, sub_bus + 1); early_write_config_byte(hose, current_bus, pci_devfn, PCI_SUBORDINATE_BUS, 0xff); /* Round memory allocator to 1MB boundary */ pciauto_upper_memspc &= ~(0x100000 - 1); /* Round I/O allocator to 4KB boundary */ pciauto_upper_iospc &= ~(0x1000 - 1); /* Set up memory and I/O filter limits, assume 32-bit I/O space */ early_write_config_word(hose, current_bus, pci_devfn, PCI_MEMORY_LIMIT, ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16); early_write_config_byte(hose, current_bus, pci_devfn, PCI_IO_LIMIT, ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8); early_write_config_word(hose, current_bus, pci_devfn, PCI_IO_LIMIT_UPPER16, ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16); /* We don't support prefetchable memory for now, so disable */ early_write_config_word(hose, current_bus, pci_devfn, PCI_PREF_MEMORY_BASE, 0x1000); early_write_config_word(hose, current_bus, pci_devfn, PCI_PREF_MEMORY_LIMIT, 0x1000); /* Enable memory and I/O accesses, enable bus master */ early_read_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, &cmdstat); early_write_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, cmdstat | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); } void __init pciauto_postscan_setup_bridge(struct pci_channel *hose, int current_bus, int pci_devfn, int sub_bus) { /* Configure bus number registers */ early_write_config_byte(hose, current_bus, pci_devfn, PCI_SUBORDINATE_BUS, sub_bus); /* Round memory allocator to 1MB boundary */ pciauto_upper_memspc &= ~(0x100000 - 1); early_write_config_word(hose, current_bus, pci_devfn, PCI_MEMORY_BASE, pciauto_upper_memspc >> 16); /* Round I/O allocator to 4KB boundary */ pciauto_upper_iospc &= ~(0x1000 - 1); early_write_config_byte(hose, current_bus, pci_devfn, PCI_IO_BASE, (pciauto_upper_iospc & 0x0000f000) >> 8); early_write_config_word(hose, current_bus, pci_devfn, PCI_IO_BASE_UPPER16, pciauto_upper_iospc >> 16); } #define PCIAUTO_IDE_MODE_MASK 0x05 int __init pciauto_bus_scan(struct pci_channel *hose, int current_bus) { int sub_bus; u32 pci_devfn, pci_class, cmdstat, found_multi=0; unsigned short vid; unsigned char header_type; sub_bus = current_bus; for (pci_devfn=0; pci_devfn<0xff; pci_devfn++) { if (PCI_FUNC(pci_devfn) && !found_multi) continue; early_read_config_byte(hose, current_bus, pci_devfn, PCI_HEADER_TYPE, &header_type); if (!PCI_FUNC(pci_devfn)) found_multi = header_type & 0x80; early_read_config_word(hose, current_bus, pci_devfn, PCI_VENDOR_ID, &vid); if (vid == 0xffff) continue; early_read_config_dword(hose, current_bus, pci_devfn, PCI_CLASS_REVISION, &pci_class); if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI ) { DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn)); pciauto_prescan_setup_bridge(hose, current_bus, pci_devfn, sub_bus); sub_bus = pciauto_bus_scan(hose, sub_bus+1); pciauto_postscan_setup_bridge(hose, current_bus, pci_devfn, sub_bus); } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { unsigned char prg_iface; early_read_config_byte(hose, current_bus, pci_devfn, PCI_CLASS_PROG, &prg_iface); if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n"); continue; } } /* * Found a peripheral, enable some standard * settings */ early_read_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, &cmdstat); early_write_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, cmdstat | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); early_write_config_byte(hose, current_bus, pci_devfn, PCI_LATENCY_TIMER, 0x80); /* Allocate PCI I/O and/or memory space */ pciauto_setup_bars(hose, current_bus, pci_devfn); } return sub_bus; } int __init pciauto_assign_resources(int busno, struct pci_channel *hose) { /* setup resource limits */ pciauto_lower_iospc = hose->io_resource->start; pciauto_upper_iospc = hose->io_resource->end + 1; pciauto_lower_memspc = hose->mem_resource->start; pciauto_upper_memspc = hose->mem_resource->end + 1; return pciauto_bus_scan(hose, busno); } /* * These functions are used early on before PCI scanning is done * and all of the pci_dev and pci_bus structures have been created. */ static struct pci_dev * fake_pci_dev(struct pci_channel *hose, int busnr, int devfn) { static struct pci_dev dev; static struct pci_bus bus; dev.bus = &bus; dev.sysdata = hose; dev.devfn = devfn; bus.number = busnr; bus.ops = hose->pci_ops; return &dev; } #define EARLY_PCI_OP(rw, size, type) \ int early_##rw##_config_##size(struct pci_channel *hose, int bus, \ int devfn, int offset, type value) \ { \ return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \ offset, value); \ } EARLY_PCI_OP(read, byte, u8 *) EARLY_PCI_OP(read, word, u16 *) EARLY_PCI_OP(read, dword, u32 *) EARLY_PCI_OP(write, byte, u8) EARLY_PCI_OP(write, word, u16) EARLY_PCI_OP(write, dword, u32) --- NEW FILE --- /*********************************************************************** * * Copyright 2001 MontaVista Software Inc. * Author: js...@mv... or js...@ju... * * arch/mips/ddb5xxx/common/prom.c * prom.c file. * * 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/config.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/bootmem.h> #include <asm/addrspace.h> #include <asm/bootinfo.h> #include <asm/ddb5xxx/ddb5xxx.h> char arcs_cmdline[COMMAND_LINE_SIZE]; /* [js...@ju...] PMON passes arguments in C main() style */ void __init prom_init(int argc, const char **arg) { int i; /* arg[0] is "g", the rest is boot parameters */ arcs_cmdline[0] = '\0'; for (i = 1; i < argc; i++) { if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >= sizeof(arcs_cmdline)) break; strcat(arcs_cmdline, arg[i]); strcat(arcs_cmdline, " "); } mips_machgroup = MACH_GROUP_NEC_DDB; #if defined(CONFIG_DDB5074) mips_machtype = MACH_NEC_DDB5074; #elif defined(CONFIG_DDB5476) mips_machtype = MACH_NEC_DDB5476; #elif defined(CONFIG_DDB5477) mips_machtype = MACH_NEC_DDB5477; #endif add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); } void __init prom_free_prom_memory(void) { } --- NEW FILE --- /* * Copyright 2001 MontaVista Software Inc. * Author: js...@mv... or js...@ju... * * arch/mips/ddb5xxx/common/rtc_ds1386.c * low-level RTC hookups for s for Dallas 1396 chip. * * 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. */ /* * This file exports a function, rtc_ds1386_init(), which expects an * uncached base address as the argument. It will set the two function * pointers expected by the MIPS generic timer code. */ #include <linux/types.h> #include <linux/time.h> #include <asm/time.h> #include <asm/addrspace.h> #include <asm/ddb5xxx/debug.h> #define EPOCH 2000 #undef BCD_TO_BIN #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) #undef BIN_TO_BCD #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) #define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x) #define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y static unsigned long rtc_base; static unsigned long rtc_ds1386_get_time(void) { u8 byte; u8 temp; unsigned int year, month, day, hour, minute, second; /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; WRITE_RTC(0xB, byte); /* read time data */ year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH; month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f); day = BCD_TO_BIN(READ_RTC(0x8)); minute = BCD_TO_BIN(READ_RTC(0x2)); second = BCD_TO_BIN(READ_RTC(0x1)); /* hour is special - deal with it later */ temp = READ_RTC(0x4); /* enable time transfer */ byte |= 0x80; WRITE_RTC(0xB, byte); /* calc hour */ if (temp & 0x40) { /* 12 hour format */ hour = BCD_TO_BIN(temp & 0x1f); if (temp & 0x20) hour += 12; /* PM */ } else { /* 24 hour format */ hour = BCD_TO_BIN(temp & 0x3f); } return mktime(year, month, day, hour, minute, second); } static int rtc_ds1386_set_time(unsigned long t) { struct rtc_time tm; u8 byte; u8 temp; u8 year, month, day, hour, minute, second; /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; WRITE_RTC(0xB, byte); /* convert */ to_tm(t, &tm); /* check each field one by one */ year = BIN_TO_BCD(tm.tm_year - EPOCH); if (year != READ_RTC(0xA)) { WRITE_RTC(0xA, year); } temp = READ_RTC(0x9); month = BIN_TO_BCD(tm.tm_mon); if (month != (temp & 0x1f)) { WRITE_RTC( 0x9, (month & 0x1f) | (temp & ~0x1f) ); } day = BIN_TO_BCD(tm.tm_mday); if (day != READ_RTC(0x8)) { WRITE_RTC(0x8, day); } temp = READ_RTC(0x4); if (temp & 0x40) { /* 12 hour format */ hour = 0x40; if (tm.tm_hour > 12) { hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f); } else { hour |= BIN_TO_BCD(tm.tm_hour); } } else { /* 24 hour format */ hour = BIN_TO_BCD(tm.tm_hour) & 0x3f; } if (hour != temp) WRITE_RTC(0x4, hour); minute = BIN_TO_BCD(tm.tm_min); if (minute != READ_RTC(0x2)) { WRITE_RTC(0x2, minute); } second = BIN_TO_BCD(tm.tm_sec); if (second != READ_RTC(0x1)) { WRITE_RTC(0x1, second); } return 0; } void rtc_ds1386_init(unsigned long base) { unsigned char byte; /* remember the base */ rtc_base = base; MIPS_ASSERT((rtc_base & 0xe0000000) == KSEG1); /* turn on RTC if it is not on */ byte = READ_RTC(0x9); if (byte & 0x80) { byte &= 0x7f; WRITE_RTC(0x9, byte); } /* enable time transfer */ byte = READ_RTC(0xB); byte |= 0x80; WRITE_RTC(0xB, byte); /* set the function pointers */ rtc_get_time = rtc_ds1386_get_time; rtc_set_time = rtc_ds1386_set_time; } |