📄 mv64x60.c
字号:
case MV64x60_TYPE_MV64360: bh->ci = &mv64360_ci; break; case MV64x60_TYPE_MV64460: bh->ci = &mv64460_ci; break; case MV64x60_TYPE_INVALID: default: if (ppc_md.progress) ppc_md.progress("mv64x60: Unsupported bridge", 0x0); printk(KERN_ERR "mv64x60: Unsupported bridge\n"); rc = -1; } return rc;}/* * mv64x60_get_bridge_vbase() * * Return the virtual address of the bridge's registers. */void __iomem *mv64x60_get_bridge_vbase(void){ return mv64x60_bridge_vbase;}/* * mv64x60_get_bridge_type() * * Return the type of bridge on the platform. */u32mv64x60_get_bridge_type(void){ return mv64x60_bridge_type;}/* * mv64x60_get_bridge_rev() * * Return the revision of the bridge on the platform. */u32mv64x60_get_bridge_rev(void){ return mv64x60_bridge_rev;}/* ***************************************************************************** * * System Memory Window Related Routines * ***************************************************************************** *//* * mv64x60_get_mem_size() * * Calculate the amount of memory that the memory controller is set up for. * This should only be used by board-specific code if there is no other * way to determine the amount of memory in the system. */u32 __initmv64x60_get_mem_size(u32 bridge_base, u32 chip_type){ struct mv64x60_handle bh; u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]; u32 rc = 0; memset(&bh, 0, sizeof(bh)); bh.type = chip_type; bh.v_base = (void *)bridge_base; if (!mv64x60_setup_for_chip(&bh)) { mv64x60_get_mem_windows(&bh, mem_windows); rc = mv64x60_calc_mem_size(&bh, mem_windows); } return rc;}/* * mv64x60_get_mem_windows() * * Get the values in the memory controller & return in the 'mem_windows' array. */void __initmv64x60_get_mem_windows(struct mv64x60_handle *bh, u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]){ u32 i, win; for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++) if (bh->ci->is_enabled_32bit(bh, win)) mv64x60_get_32bit_window(bh, win, &mem_windows[i][0], &mem_windows[i][1]); else { mem_windows[i][0] = 0; mem_windows[i][1] = 0; }}/* * mv64x60_calc_mem_size() * * Using the memory controller register values in 'mem_windows', determine * how much memory it is set up for. */u32 __initmv64x60_calc_mem_size(struct mv64x60_handle *bh, u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]){ u32 i, total = 0; for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) total += mem_windows[i][1]; return total;}/* ***************************************************************************** * * CPU->System MEM, PCI Config Routines * ***************************************************************************** *//* * mv64x60_config_cpu2mem_windows() * * Configure CPU->Memory windows on the bridge. */static u32 prot_tab[] __initdata = { MV64x60_CPU_PROT_0_WIN, MV64x60_CPU_PROT_1_WIN, MV64x60_CPU_PROT_2_WIN, MV64x60_CPU_PROT_3_WIN};static u32 cpu_snoop_tab[] __initdata = { MV64x60_CPU_SNOOP_0_WIN, MV64x60_CPU_SNOOP_1_WIN, MV64x60_CPU_SNOOP_2_WIN, MV64x60_CPU_SNOOP_3_WIN};void __initmv64x60_config_cpu2mem_windows(struct mv64x60_handle *bh, struct mv64x60_setup_info *si, u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]){ u32 i, win; /* Set CPU protection & snoop windows */ for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++) if (bh->ci->is_enabled_32bit(bh, win)) { mv64x60_set_32bit_window(bh, prot_tab[i], mem_windows[i][0], mem_windows[i][1], si->cpu_prot_options[i]); bh->ci->enable_window_32bit(bh, prot_tab[i]); if (bh->ci->window_tab_32bit[cpu_snoop_tab[i]]. base_reg != 0) { mv64x60_set_32bit_window(bh, cpu_snoop_tab[i], mem_windows[i][0], mem_windows[i][1], si->cpu_snoop_options[i]); bh->ci->enable_window_32bit(bh, cpu_snoop_tab[i]); } }}/* * mv64x60_config_cpu2pci_windows() * * Configure the CPU->PCI windows for one of the PCI buses. */static u32 win_tab[2][4] __initdata = { { MV64x60_CPU2PCI0_IO_WIN, MV64x60_CPU2PCI0_MEM_0_WIN, MV64x60_CPU2PCI0_MEM_1_WIN, MV64x60_CPU2PCI0_MEM_2_WIN }, { MV64x60_CPU2PCI1_IO_WIN, MV64x60_CPU2PCI1_MEM_0_WIN, MV64x60_CPU2PCI1_MEM_1_WIN, MV64x60_CPU2PCI1_MEM_2_WIN },};static u32 remap_tab[2][4] __initdata = { { MV64x60_CPU2PCI0_IO_REMAP_WIN, MV64x60_CPU2PCI0_MEM_0_REMAP_WIN, MV64x60_CPU2PCI0_MEM_1_REMAP_WIN, MV64x60_CPU2PCI0_MEM_2_REMAP_WIN }, { MV64x60_CPU2PCI1_IO_REMAP_WIN, MV64x60_CPU2PCI1_MEM_0_REMAP_WIN, MV64x60_CPU2PCI1_MEM_1_REMAP_WIN, MV64x60_CPU2PCI1_MEM_2_REMAP_WIN }};void __initmv64x60_config_cpu2pci_windows(struct mv64x60_handle *bh, struct mv64x60_pci_info *pi, u32 bus){ int i; if (pi->pci_io.size > 0) { mv64x60_set_32bit_window(bh, win_tab[bus][0], pi->pci_io.cpu_base, pi->pci_io.size, pi->pci_io.swap); mv64x60_set_32bit_window(bh, remap_tab[bus][0], pi->pci_io.pci_base_lo, 0, 0); bh->ci->enable_window_32bit(bh, win_tab[bus][0]); } else /* Actually, the window should already be disabled */ bh->ci->disable_window_32bit(bh, win_tab[bus][0]); for (i=0; i<3; i++) if (pi->pci_mem[i].size > 0) { mv64x60_set_32bit_window(bh, win_tab[bus][i+1], pi->pci_mem[i].cpu_base, pi->pci_mem[i].size, pi->pci_mem[i].swap); mv64x60_set_64bit_window(bh, remap_tab[bus][i+1], pi->pci_mem[i].pci_base_hi, pi->pci_mem[i].pci_base_lo, 0, 0); bh->ci->enable_window_32bit(bh, win_tab[bus][i+1]); } else /* Actually, the window should already be disabled */ bh->ci->disable_window_32bit(bh, win_tab[bus][i+1]);}/* ***************************************************************************** * * PCI->System MEM Config Routines * ***************************************************************************** *//* * mv64x60_config_pci2mem_windows() * * Configure the PCI->Memory windows on the bridge. */static u32 pci_acc_tab[2][4] __initdata = { { MV64x60_PCI02MEM_ACC_CNTL_0_WIN, MV64x60_PCI02MEM_ACC_CNTL_1_WIN, MV64x60_PCI02MEM_ACC_CNTL_2_WIN, MV64x60_PCI02MEM_ACC_CNTL_3_WIN }, { MV64x60_PCI12MEM_ACC_CNTL_0_WIN, MV64x60_PCI12MEM_ACC_CNTL_1_WIN, MV64x60_PCI12MEM_ACC_CNTL_2_WIN, MV64x60_PCI12MEM_ACC_CNTL_3_WIN }};static u32 pci_snoop_tab[2][4] __initdata = { { MV64x60_PCI02MEM_SNOOP_0_WIN, MV64x60_PCI02MEM_SNOOP_1_WIN, MV64x60_PCI02MEM_SNOOP_2_WIN, MV64x60_PCI02MEM_SNOOP_3_WIN }, { MV64x60_PCI12MEM_SNOOP_0_WIN, MV64x60_PCI12MEM_SNOOP_1_WIN, MV64x60_PCI12MEM_SNOOP_2_WIN, MV64x60_PCI12MEM_SNOOP_3_WIN }};static u32 pci_size_tab[2][4] __initdata = { { MV64x60_PCI0_MEM_0_SIZE, MV64x60_PCI0_MEM_1_SIZE, MV64x60_PCI0_MEM_2_SIZE, MV64x60_PCI0_MEM_3_SIZE }, { MV64x60_PCI1_MEM_0_SIZE, MV64x60_PCI1_MEM_1_SIZE, MV64x60_PCI1_MEM_2_SIZE, MV64x60_PCI1_MEM_3_SIZE }};void __initmv64x60_config_pci2mem_windows(struct mv64x60_handle *bh, struct pci_controller *hose, struct mv64x60_pci_info *pi, u32 bus, u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]){ u32 i, win; /* * Set the access control, snoop, BAR size, and window base addresses. * PCI->MEM windows base addresses will match exactly what the * CPU->MEM windows are. */ for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++) if (bh->ci->is_enabled_32bit(bh, win)) { mv64x60_set_64bit_window(bh, pci_acc_tab[bus][i], 0, mem_windows[i][0], mem_windows[i][1], pi->acc_cntl_options[i]); bh->ci->enable_window_64bit(bh, pci_acc_tab[bus][i]); if (bh->ci->window_tab_64bit[ pci_snoop_tab[bus][i]].base_lo_reg != 0) { mv64x60_set_64bit_window(bh, pci_snoop_tab[bus][i], 0, mem_windows[i][0], mem_windows[i][1], pi->snoop_options[i]); bh->ci->enable_window_64bit(bh, pci_snoop_tab[bus][i]); } bh->ci->set_pci2mem_window(hose, bus, i, mem_windows[i][0]); mv64x60_write(bh, pci_size_tab[bus][i], mv64x60_mask(mem_windows[i][1] - 1, 20)); /* Enable the window */ mv64x60_clr_bits(bh, ((bus == 0) ? MV64x60_PCI0_BAR_ENABLE : MV64x60_PCI1_BAR_ENABLE), (1 << i)); }}/* ***************************************************************************** * * Hose & Resource Alloc/Init Routines * ***************************************************************************** *//* * mv64x60_alloc_hoses() * * Allocate the PCI hose structures for the bridge's PCI buses. */void __initmv64x60_alloc_hose(struct mv64x60_handle *bh, u32 cfg_addr, u32 cfg_data, struct pci_controller **hose){ *hose = pcibios_alloc_controller(); setup_indirect_pci_nomap(*hose, bh->v_base + cfg_addr, bh->v_base + cfg_data);}/* * mv64x60_config_resources() * * Calculate the offsets, etc. for the hose structures to reflect all of * the address remapping that happens as you go from CPU->PCI and PCI->MEM. */void __initmv64x60_config_resources(struct pci_controller *hose, struct mv64x60_pci_info *pi, u32 io_base){ int i; /* 2 hoses; 4 resources/hose; string <= 64 bytes */ static char s[2][4][64]; if (pi->pci_io.size != 0) { sprintf(s[hose->index][0], "PCI hose %d I/O Space", hose->index); pci_init_resource(&hose->io_resource, io_base - isa_io_base, io_base - isa_io_base + pi->pci_io.size - 1, IORESOURCE_IO, s[hose->index][0]); hose->io_space.start = pi->pci_io.pci_base_lo; hose->io_space.end = pi->pci_io.pci_base_lo + pi->pci_io.size-1; hose->io_base_phys = pi->pci_io.cpu_base; hose->io_base_virt = (void *)isa_io_base; } for (i=0; i<3; i++) if (pi->pci_mem[i].size != 0) { sprintf(s[hose->index][i+1], "PCI hose %d MEM Space %d", hose->index, i); pci_init_resource(&hose->mem_resources[i], pi->pci_mem[i].cpu_base, pi->pci_mem[i].cpu_base + pi->pci_mem[i].size-1, IORESOURCE_MEM, s[hose->index][i+1]); } hose->mem_space.end = pi->pci_mem[0].pci_base_lo + pi->pci_mem[0].size - 1; hose->pci_mem_offset = pi->pci_mem[0].cpu_base - pi->pci_mem[0].pci_base_lo;}/* * mv64x60_config_pci_params() * * Configure a hose's PCI config space parameters. */void __initmv64x60_config_pci_params(struct pci_controller *hose, struct mv64x60_pci_info *pi){ u32 devfn; u16 u16_val; u8 save_exclude; devfn = PCI_DEVFN(0,0); save_exclude = mv64x60_pci_exclude_bridge; mv64x60_pci_exclude_bridge = 0; /* Set class code to indicate host bridge */ u16_val = PCI_CLASS_BRIDGE_HOST; /* 0x0600 (host bridge) */ early_write_config_word(hose, 0, devfn, PCI_CLASS_DEVICE, u16_val); /* Enable bridge to be PCI master & respond to PCI MEM cycles */ early_read_config_word(hose, 0, devfn, PCI_COMMAND, &u16_val); u16_val &= ~(PCI_COMMAND_IO | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK); u16_val |= pi->pci_cmd_bits | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; early_write_config_word(hose, 0, devfn, PCI_COMMAND, u16_val); /* Set latency timer, cache line size, clear BIST */ u16_val = (pi->latency_timer << 8) | (L1_CACHE_BYTES >> 2); early_write_config_word(hose, 0, devfn, PCI_CACHE_LINE_SIZE, u16_val); mv64x60_pci_exclude_bridge = save_exclude;}/* ***************************************************************************** * * PCI Related Routine * ***************************************************************************** *//* * mv64x60_set_bus() * * Set the bus number for the hose directly under the bridge. */void __initmv64x60_set_bus(struct mv64x60_handle *bh, u32 bus, u32 child_bus){ struct pci_controller *hose; u32 pci_mode, p2p_cfg, pci_cfg_offset, val; u8 save_exclude; if (bus == 0) { pci_mode = bh->pci_mode_a; p2p_cfg = MV64x60_PCI0_P2P_CONFIG; pci_cfg_offset = 0x64; hose = bh->hose_a; } else { pci_mode = bh->pci_mode_b; p2p_cfg = MV64x60_PCI1_P2P_CONFIG; pci_cfg_offset = 0xe4; hose = bh->hose_b; } child_bus &= 0xff; val = mv64x60_read(bh, p2p_cfg); if (pci_mode == MV64x60_PCIMODE_CONVENTIONAL) { val &= 0xe0000000; /* Force dev num to 0, turn off P2P bridge */ val |= (child_bus << 16) | 0xff; mv64x60_write(bh, p2p_cfg, val); (void)mv64x60_read(bh, p2p_cfg); /* Flush FIFO */ } else { /* PCI-X */ /* * Need to use the current bus/dev number (that's in the * P2P CONFIG reg) to access the bridge's pci config space. */ save_exclude = mv64x60_pci_exclude_bridge; mv64x60_pci_exclude_bridge = 0; early_write_config_dword(hose, (val & 0x00ff0000) >> 16, PCI_DEVFN(((val & 0x1f000000) >> 24), 0), pci_cfg_offset, child_bus << 8); mv64x60_pci_exclude_bridge = save_exclude; }}/* * mv64x60_pci_exclude_device() * * This routine is used to make the bridge not appear when the * PCI subsystem is accessing PCI devices (in PCI config space). */intmv64x60_pci_exclude_device(u8 bus, u8 devfn)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -