Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.22-rc4 361 lines 10 kB view raw
1/* 2 * Board setup routines for Motorola PrPMC750 3 * 4 * Author: Matt Porter <mporter@mvista.com> 5 * 6 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under 7 * the terms of the GNU General Public License version 2. This program 8 * is licensed "as is" without any warranty of any kind, whether express 9 * or implied. 10 */ 11 12#include <linux/stddef.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/errno.h> 16#include <linux/reboot.h> 17#include <linux/pci.h> 18#include <linux/kdev_t.h> 19#include <linux/types.h> 20#include <linux/major.h> 21#include <linux/initrd.h> 22#include <linux/console.h> 23#include <linux/delay.h> 24#include <linux/seq_file.h> 25#include <linux/ide.h> 26#include <linux/root_dev.h> 27#include <linux/slab.h> 28#include <linux/serial_reg.h> 29 30#include <asm/byteorder.h> 31#include <asm/system.h> 32#include <asm/pgtable.h> 33#include <asm/page.h> 34#include <asm/dma.h> 35#include <asm/io.h> 36#include <asm/irq.h> 37#include <asm/machdep.h> 38#include <asm/pci-bridge.h> 39#include <asm/uaccess.h> 40#include <asm/time.h> 41#include <asm/open_pic.h> 42#include <asm/bootinfo.h> 43#include <asm/hawk.h> 44 45#include "prpmc750.h" 46 47extern unsigned long loops_per_jiffy; 48 49extern void gen550_progress(char *, unsigned short); 50 51static u_char prpmc750_openpic_initsenses[] __initdata = 52{ 53 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT0 */ 54 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UART */ 55 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_DEBUGINT */ 56 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HAWK_WDT */ 57 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ 58 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_ABORT */ 59 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT1 */ 60 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT2 */ 61 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT3 */ 62 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTA */ 63 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTB */ 64 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTC */ 65 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTD */ 66 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ 67 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ 68 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ 69}; 70 71/* 72 * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier 73 * Combined irq tables. Only Base has IDSEL 14, only Carrier has 21 and 22. 74 */ 75static inline int 76prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) 77{ 78 static char pci_irq_table[][4] = 79 /* 80 * PCI IDSEL/INTPIN->INTLINE 81 * A B C D 82 */ 83 { 84 {12, 0, 0, 0}, /* IDSEL 14 - Ethernet, base */ 85 {0, 0, 0, 0}, /* IDSEL 15 - unused */ 86 {10, 11, 12, 9}, /* IDSEL 16 - PMC A1, PMC1 */ 87 {10, 11, 12, 9}, /* IDSEL 17 - PrPMC-A-B, PMC2-B */ 88 {11, 12, 9, 10}, /* IDSEL 18 - PMC A1-B, PMC1-B */ 89 {0, 0, 0, 0}, /* IDSEL 19 - unused */ 90 {9, 10, 11, 12}, /* IDSEL 20 - P2P Bridge */ 91 {11, 12, 9, 10}, /* IDSEL 21 - PMC A2, carrier */ 92 {12, 9, 10, 11}, /* IDSEL 22 - PMC A2-B, carrier */ 93 }; 94 const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4; 95 return PCI_IRQ_TABLE_LOOKUP; 96}; 97 98static void __init prpmc750_pcibios_fixup(void) 99{ 100 struct pci_dev *dev; 101 unsigned short wtmp; 102 103 /* 104 * Kludge to clean up after PPC6BUG which doesn't 105 * configure the CL5446 VGA card. Also the 106 * resource subsystem doesn't fixup the 107 * PCI mem resources on the CL5446. 108 */ 109 if ((dev = pci_get_device(PCI_VENDOR_ID_CIRRUS, 110 PCI_DEVICE_ID_CIRRUS_5446, 0))) { 111 dev->resource[0].start += PRPMC750_PCI_PHY_MEM_OFFSET; 112 dev->resource[0].end += PRPMC750_PCI_PHY_MEM_OFFSET; 113 pci_read_config_word(dev, PCI_COMMAND, &wtmp); 114 pci_write_config_word(dev, PCI_COMMAND, wtmp | 3); 115 /* Enable Color mode in MISC reg */ 116 outb(0x03, 0x3c2); 117 /* Select DRAM config reg */ 118 outb(0x0f, 0x3c4); 119 /* Set proper DRAM config */ 120 outb(0xdf, 0x3c5); 121 pci_dev_put(dev); 122 } 123} 124 125void __init prpmc750_find_bridges(void) 126{ 127 struct pci_controller *hose; 128 129 hose = pcibios_alloc_controller(); 130 if (!hose) 131 return; 132 133 hose->first_busno = 0; 134 hose->last_busno = 0xff; 135 hose->io_base_virt = (void *)PRPMC750_ISA_IO_BASE; 136 hose->pci_mem_offset = PRPMC750_PCI_PHY_MEM_OFFSET; 137 138 pci_init_resource(&hose->io_resource, 139 PRPMC750_PCI_IO_START, 140 PRPMC750_PCI_IO_END, 141 IORESOURCE_IO, "PCI host bridge"); 142 143 pci_init_resource(&hose->mem_resources[0], 144 PRPMC750_PROC_PCI_MEM_START, 145 PRPMC750_PROC_PCI_MEM_END, 146 IORESOURCE_MEM, "PCI host bridge"); 147 148 hose->io_space.start = PRPMC750_PCI_IO_START; 149 hose->io_space.end = PRPMC750_PCI_IO_END; 150 hose->mem_space.start = PRPMC750_PCI_MEM_START; 151 hose->mem_space.end = PRPMC750_PCI_MEM_END - HAWK_MPIC_SIZE; 152 153 if (hawk_init(hose, PRPMC750_HAWK_PPC_REG_BASE, 154 PRPMC750_PROC_PCI_MEM_START, 155 PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE, 156 PRPMC750_PROC_PCI_IO_START, PRPMC750_PROC_PCI_IO_END, 157 PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1) 158 != 0) { 159 printk(KERN_CRIT "Could not initialize host bridge\n"); 160 } 161 162 hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); 163 164 ppc_md.pcibios_fixup = prpmc750_pcibios_fixup; 165 ppc_md.pci_swizzle = common_swizzle; 166 ppc_md.pci_map_irq = prpmc_map_irq; 167} 168static int prpmc750_show_cpuinfo(struct seq_file *m) 169{ 170 seq_printf(m, "machine\t\t: PrPMC750\n"); 171 172 return 0; 173} 174 175static void __init prpmc750_setup_arch(void) 176{ 177 /* init to some ~sane value until calibrate_delay() runs */ 178 loops_per_jiffy = 50000000 / HZ; 179 180 /* Lookup PCI host bridges */ 181 prpmc750_find_bridges(); 182 183#ifdef CONFIG_BLK_DEV_INITRD 184 if (initrd_start) 185 ROOT_DEV = Root_RAM0; 186 else 187#endif 188#ifdef CONFIG_ROOT_NFS 189 ROOT_DEV = Root_NFS; 190#else 191 ROOT_DEV = Root_SDA2; 192#endif 193 194 OpenPIC_InitSenses = prpmc750_openpic_initsenses; 195 OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses); 196 197 printk(KERN_INFO "Port by MontaVista Software, Inc. " 198 "(source@mvista.com)\n"); 199} 200 201/* 202 * Compute the PrPMC750's bus speed using the baud clock as a 203 * reference. 204 */ 205static unsigned long __init prpmc750_get_bus_speed(void) 206{ 207 unsigned long tbl_start, tbl_end; 208 unsigned long current_state, old_state, bus_speed; 209 unsigned char lcr, dll, dlm; 210 int baud_divisor, count; 211 212 /* Read the UART's baud clock divisor */ 213 lcr = readb(PRPMC750_SERIAL_0_LCR); 214 writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); 215 dll = readb(PRPMC750_SERIAL_0_DLL); 216 dlm = readb(PRPMC750_SERIAL_0_DLM); 217 writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); 218 baud_divisor = (dlm << 8) | dll; 219 220 /* 221 * Use the baud clock divisor and base baud clock 222 * to determine the baud rate and use that as 223 * the number of baud clock edges we use for 224 * the time base sample. Make it half the baud 225 * rate. 226 */ 227 count = PRPMC750_BASE_BAUD / (baud_divisor * 16); 228 229 /* Find the first edge of the baud clock */ 230 old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK; 231 do { 232 current_state = readb(PRPMC750_STATUS_REG) & 233 PRPMC750_BAUDOUT_MASK; 234 } while (old_state == current_state); 235 236 old_state = current_state; 237 238 /* Get the starting time base value */ 239 tbl_start = get_tbl(); 240 241 /* 242 * Loop until we have found a number of edges equal 243 * to half the count (half the baud rate) 244 */ 245 do { 246 do { 247 current_state = readb(PRPMC750_STATUS_REG) & 248 PRPMC750_BAUDOUT_MASK; 249 } while (old_state == current_state); 250 old_state = current_state; 251 } while (--count); 252 253 /* Get the ending time base value */ 254 tbl_end = get_tbl(); 255 256 /* Compute bus speed */ 257 bus_speed = (tbl_end - tbl_start) * 128; 258 259 return bus_speed; 260} 261 262static void __init prpmc750_calibrate_decr(void) 263{ 264 unsigned long freq; 265 int divisor = 4; 266 267 freq = prpmc750_get_bus_speed(); 268 269 tb_ticks_per_jiffy = freq / (HZ * divisor); 270 tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000); 271} 272 273static void prpmc750_restart(char *cmd) 274{ 275 local_irq_disable(); 276 writeb(PRPMC750_MODRST_MASK, PRPMC750_MODRST_REG); 277 while (1) ; 278} 279 280static void prpmc750_halt(void) 281{ 282 local_irq_disable(); 283 while (1) ; 284} 285 286static void prpmc750_power_off(void) 287{ 288 prpmc750_halt(); 289} 290 291static void __init prpmc750_init_IRQ(void) 292{ 293 openpic_init(0); 294} 295 296/* 297 * Set BAT 3 to map 0xf0000000 to end of physical memory space. 298 */ 299static __inline__ void prpmc750_set_bat(void) 300{ 301 mb(); 302 mtspr(SPRN_DBAT1U, 0xf0001ffe); 303 mtspr(SPRN_DBAT1L, 0xf000002a); 304 mb(); 305} 306 307/* 308 * We need to read the Falcon/Hawk memory controller 309 * to properly determine this value 310 */ 311static unsigned long __init prpmc750_find_end_of_memory(void) 312{ 313 /* Read the memory size from the Hawk SMC */ 314 return hawk_get_mem_size(PRPMC750_HAWK_SMC_BASE); 315} 316 317static void __init prpmc750_map_io(void) 318{ 319 io_block_mapping(PRPMC750_ISA_IO_BASE, PRPMC750_ISA_IO_BASE, 320 0x10000000, _PAGE_IO); 321#if 0 322 io_block_mapping(0xf0000000, 0xc0000000, 0x08000000, _PAGE_IO); 323#endif 324 io_block_mapping(0xf8000000, 0xf8000000, 0x08000000, _PAGE_IO); 325} 326 327void __init 328platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 329 unsigned long r6, unsigned long r7) 330{ 331 parse_bootinfo(find_bootinfo()); 332 333 /* Cover the Hawk registers with a BAT */ 334 prpmc750_set_bat(); 335 336 isa_io_base = PRPMC750_ISA_IO_BASE; 337 isa_mem_base = PRPMC750_ISA_MEM_BASE; 338 pci_dram_offset = PRPMC750_PCI_DRAM_OFFSET; 339 340 ppc_md.setup_arch = prpmc750_setup_arch; 341 ppc_md.show_cpuinfo = prpmc750_show_cpuinfo; 342 ppc_md.init_IRQ = prpmc750_init_IRQ; 343 ppc_md.get_irq = openpic_get_irq; 344 345 ppc_md.find_end_of_memory = prpmc750_find_end_of_memory; 346 ppc_md.setup_io_mappings = prpmc750_map_io; 347 348 ppc_md.restart = prpmc750_restart; 349 ppc_md.power_off = prpmc750_power_off; 350 ppc_md.halt = prpmc750_halt; 351 352 /* PrPMC750 has no timekeeper part */ 353 ppc_md.time_init = NULL; 354 ppc_md.get_rtc_time = NULL; 355 ppc_md.set_rtc_time = NULL; 356 ppc_md.calibrate_decr = prpmc750_calibrate_decr; 357 358#ifdef CONFIG_SERIAL_TEXT_DEBUG 359 ppc_md.progress = gen550_progress; 360#endif /* CONFIG_SERIAL_TEXT_DEBUG */ 361}