📄 hdpu.c
字号:
{ hdpu_halt(); /* NOTREACHED */}static int hdpu_show_cpuinfo(struct seq_file *m){ uint pvid; pvid = mfspr(SPRN_PVR); seq_printf(m, "vendor\t\t: Sky Computers\n"); seq_printf(m, "machine\t\t: HDPU Compute Blade\n"); seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n", pvid, (pvid & (1 << 15) ? "IBM" : "Motorola")); return 0;}static void __init hdpu_calibrate_decr(void){ ulong freq; if (ppcboot_bd_valid) freq = ppcboot_bd.bi_busfreq / 4; else freq = 133000000; printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", freq / 1000000, freq % 1000000); tb_ticks_per_jiffy = freq / HZ; tb_to_us = mulhwu_scale_factor(freq, 1000000); return;}static void parse_bootinfo(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7){ bd_t *bd = NULL; char *cmdline_start = NULL; int cmdline_len = 0; if (r3) { if ((r3 & 0xf0000000) == 0) r3 += KERNELBASE; if ((r3 & 0xf0000000) == KERNELBASE) { bd = (void *)r3; memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd)); ppcboot_bd_valid = 1; } }#ifdef CONFIG_BLK_DEV_INITRD if (r4 && r5 && r5 > r4) { if ((r4 & 0xf0000000) == 0) r4 += KERNELBASE; if ((r5 & 0xf0000000) == 0) r5 += KERNELBASE; if ((r4 & 0xf0000000) == KERNELBASE) { initrd_start = r4; initrd_end = r5; initrd_below_start_ok = 1; } }#endif /* CONFIG_BLK_DEV_INITRD */ if (r6 && r7 && r7 > r6) { if ((r6 & 0xf0000000) == 0) r6 += KERNELBASE; if ((r7 & 0xf0000000) == 0) r7 += KERNELBASE; if ((r6 & 0xf0000000) == KERNELBASE) { cmdline_start = (void *)r6; cmdline_len = (r7 - r6); strncpy(cmd_line, cmdline_start, cmdline_len); } }}#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)static voidhdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name){ request_region(from, extent, name); return;}static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent){ release_region(from, extent); return;}static void __inithdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq){ struct pci_dev *dev; pci_for_each_dev(dev) { if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) || ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) { hw->irq = dev->irq; if (irq != NULL) { *irq = dev->irq; } } } return;}#endifvoid hdpu_heartbeat(void){ if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5)) mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 5)); else mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, (1 << 5)); ppc_md.heartbeat_count = ppc_md.heartbeat_reset;}static void __init hdpu_map_io(void){ io_block_mapping(0xf1000000, 0xf1000000, 0x20000, _PAGE_IO);}#ifdef CONFIG_SMPchar hdpu_smp0[] = "SMP Cpu #0";char hdpu_smp1[] = "SMP Cpu #1";static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id, struct pt_regs *regs){ volatile unsigned int doorbell; doorbell = mv64x60_read(&bh, MV64360_CPU0_DOORBELL); /* Ack the doorbell interrupts */ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell); if (doorbell & 1) { smp_message_recv(0, regs); } if (doorbell & 2) { smp_message_recv(1, regs); } if (doorbell & 4) { smp_message_recv(2, regs); } if (doorbell & 8) { smp_message_recv(3, regs); } return IRQ_HANDLED;}static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id, struct pt_regs *regs){ volatile unsigned int doorbell; doorbell = mv64x60_read(&bh, MV64360_CPU1_DOORBELL); /* Ack the doorbell interrupts */ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell); if (doorbell & 1) { smp_message_recv(0, regs); } if (doorbell & 2) { smp_message_recv(1, regs); } if (doorbell & 4) { smp_message_recv(2, regs); } if (doorbell & 8) { smp_message_recv(3, regs); } return IRQ_HANDLED;}static void smp_hdpu_CPU_two(void){ __asm__ __volatile__ ("\n" "lis 3,0x0000\n" "ori 3,3,0x00c0\n" "mtspr 26, 3\n" "li 4,0\n" "mtspr 27,4\n" "rfi");}static int smp_hdpu_probe(void){ int *cpu_count_reg; int num_cpus = 0; cpu_count_reg = ioremap(HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE); if (cpu_count_reg) { num_cpus = (*cpu_count_reg >> 20) & 0x3; iounmap(cpu_count_reg); } /* Validate the bits in the CPLD. If we could not map the reg, return 2. * If the register reported 0 or 3, return 2. * Older CPLD revisions set these bits to all ones (val = 3). */ if ((num_cpus < 1) || (num_cpus > 2)) { printk ("Unable to determine the number of processors %d . deafulting to 2.\n", num_cpus); num_cpus = 2; } return num_cpus;}static voidsmp_hdpu_message_pass(int target, int msg){ if (msg > 0x3) { printk("SMP %d: smp_message_pass: unknown msg %d\n", smp_processor_id(), msg); return; } switch (target) { case MSG_ALL: mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); break; case MSG_ALL_BUT_SELF: if (smp_processor_id()) mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); else mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); break; default: if (target == 0) mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); else mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); break; }}static void smp_hdpu_kick_cpu(int nr){ volatile unsigned int *bootaddr; if (ppc_md.progress) ppc_md.progress("smp_hdpu_kick_cpu", 0); hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_KICK); /* Disable BootCS. Must also reduce the windows size to zero. */ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, 0, 0, 0); bootaddr = ioremap(HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE); if (!bootaddr) { if (ppc_md.progress) ppc_md.progress("smp_hdpu_kick_cpu: ioremap failed", 0); return; } memcpy((void *)(bootaddr + 0x40), (void *)&smp_hdpu_CPU_two, 0x20); /* map SRAM to 0xfff00000 */ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, 0xfff00000, HDPU_INTERNAL_SRAM_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); /* Enable CPU1 arbitration */ mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); /* * Wait 100mSecond until other CPU has reached __secondary_start. * When it reaches, it is permittable to rever the SRAM mapping etc... */ mdelay(100); *(unsigned long *)KERNELBASE = nr; asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory"); iounmap(bootaddr); /* Set up window for internal sram (256KByte insize) */ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); /* * Set up windows for embedded FLASH (using boot CS window). */ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);}static void smp_hdpu_setup_cpu(int cpu_nr){ if (cpu_nr == 0) { if (ppc_md.progress) ppc_md.progress("smp_hdpu_setup_cpu 0", 0); mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff); mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff); request_irq(60, hdpu_smp_cpu0_int_handler, SA_INTERRUPT, hdpu_smp0, 0); } if (cpu_nr == 1) { if (ppc_md.progress) ppc_md.progress("smp_hdpu_setup_cpu 1", 0); hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_OK); /* Enable L1 Parity Bits */ hdpu_set_l1pe(); /* Enable L2 cache */ _set_L2CR(0); _set_L2CR(0x80080000); mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0); mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff); request_irq(28, hdpu_smp_cpu1_int_handler, SA_INTERRUPT, hdpu_smp1, 0); }}void __devinit hdpu_tben_give(){ volatile unsigned long *val = 0; /* By writing 0 to the TBEN_BASE, the timebases is frozen */ val = ioremap(HDPU_TBEN_BASE, 4); *val = 0; mb(); spin_lock(&timebase_lock); timebase_upper = get_tbu(); timebase_lower = get_tbl(); spin_unlock(&timebase_lock); while (timebase_upper || timebase_lower) barrier(); /* By writing 1 to the TBEN_BASE, the timebases is thawed */ *val = 1; mb(); iounmap(val);}void __devinit hdpu_tben_take(){ while (!(timebase_upper || timebase_lower)) barrier(); spin_lock(&timebase_lock); set_tb(timebase_upper, timebase_lower); timebase_upper = 0; timebase_lower = 0; spin_unlock(&timebase_lock);}static struct smp_ops_t hdpu_smp_ops = { .message_pass = smp_hdpu_message_pass, .probe = smp_hdpu_probe, .kick_cpu = smp_hdpu_kick_cpu, .setup_cpu = smp_hdpu_setup_cpu, .give_timebase = hdpu_tben_give, .take_timebase = hdpu_tben_take,};#endif /* CONFIG_SMP */void __initplatform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7){ parse_bootinfo(r3, r4, r5, r6, r7); isa_mem_base = 0; ppc_md.setup_arch = hdpu_setup_arch; ppc_md.init = hdpu_init2; ppc_md.show_cpuinfo = hdpu_show_cpuinfo; ppc_md.init_IRQ = hdpu_init_irq; ppc_md.get_irq = mv64360_get_irq; ppc_md.restart = hdpu_restart; ppc_md.power_off = hdpu_power_off; ppc_md.halt = hdpu_halt; ppc_md.find_end_of_memory = hdpu_find_end_of_memory; ppc_md.calibrate_decr = hdpu_calibrate_decr; ppc_md.setup_io_mappings = hdpu_map_io; bh.p_base = CONFIG_MV64X60_NEW_BASE; bh.v_base = (unsigned long *)bh.p_base; hdpu_set_bat();#if defined(CONFIG_SERIAL_TEXT_DEBUG) ppc_md.progress = hdpu_mpsc_progress; /* embedded UART */ mv64x60_progress_init(bh.p_base);#endif /* CONFIG_SERIAL_TEXT_DEBUG */#ifdef CONFIG_SMP smp_ops = &hdpu_smp_ops;#endif /* CONFIG_SMP */#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) platform_notify = hdpu_platform_notify;#endif return;}#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)/* SMP safe version of the serial text debug routine. Uses Semaphore 0 */void hdpu_mpsc_progress(char *s, unsigned short hex){ while (mv64x60_read(&bh, MV64360_WHO_AM_I) != mv64x60_read(&bh, MV64360_SEMAPHORE_0)) { } mv64x60_mpsc_progress(s, hex); mv64x60_write(&bh, MV64360_SEMAPHORE_0, 0xff);}#endifstatic void hdpu_cpustate_set(unsigned char new_state){ unsigned int state = (new_state << 21); mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (0xff << 21)); mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, state);}#ifdef CONFIG_MTD_PHYSMAPstatic struct mtd_partition hdpu_partitions[] = { { .name = "Root FS", .size = 0x03400000, .offset = 0, .mask_flags = 0, },{ .name = "User FS", .size = 0x00800000, .offset = 0x03400000, .mask_flags = 0, },{ .name = "Kernel Image", .size = 0x002C0000, .offset = 0x03C00000, .mask_flags = 0, },{ .name = "bootEnv", .size = 0x00040000, .offset = 0x03EC0000, .mask_flags = 0, },{ .name = "bootROM", .size = 0x00100000, .offset = 0x03F00000, .mask_flags = 0, }};static int __init hdpu_setup_mtd(void){ physmap_set_partitions(hdpu_partitions, 5); return 0;}arch_initcall(hdpu_setup_mtd);#endif#ifdef CONFIG_HDPU_FEATURESstatic struct resource hdpu_cpustate_resources[] = { [0] = { .name = "addr base", .start = MV64x60_GPP_VALUE_SET, .end = MV64x60_GPP_VALUE_CLR + 1, .flags = IORESOURCE_MEM, },};static struct resource hdpu_nexus_resources[] = { [0] = { .name = "nexus register", .start = HDPU_NEXUS_ID_BASE, .end = HDPU_NEXUS_ID_BASE + HDPU_NEXUS_ID_SIZE, .flags = IORESOURCE_MEM, },};static struct platform_device hdpu_cpustate_device = { .name = HDPU_CPUSTATE_NAME, .id = 0, .num_resources = ARRAY_SIZE(hdpu_cpustate_resources), .resource = hdpu_cpustate_resources,};static struct platform_device hdpu_nexus_device = { .name = HDPU_NEXUS_NAME, .id = 0, .num_resources = ARRAY_SIZE(hdpu_nexus_resources), .resource = hdpu_nexus_resources,};static int __init hdpu_add_pds(void){ platform_device_register(&hdpu_cpustate_device); platform_device_register(&hdpu_nexus_device); return 0;}arch_initcall(hdpu_add_pds);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -