📄 mv64x60.c
字号:
#ifdef CONFIG_MV643XX_ETH &mv64x60_eth_shared_device,#endif#ifdef CONFIG_MV643XX_ETH_0 ð0_device,#endif#ifdef CONFIG_MV643XX_ETH_1 ð1_device,#endif#ifdef CONFIG_MV643XX_ETH_2 ð2_device,#endif#ifdef CONFIG_I2C_MV64XXX &i2c_device,#endif#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260) &mv64xxx_device,#endif};/* ***************************************************************************** * * Bridge Initialization Routines * ***************************************************************************** *//* * mv64x60_init() * * Initialze the bridge based on setting passed in via 'si'. The bridge * handle, 'bh', will be set so that it can be used to make subsequent * calls to routines in this file. */int __initmv64x60_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si){ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]; if (ppc_md.progress) ppc_md.progress("mv64x60 initialization", 0x0); spin_lock_init(&mv64x60_lock); mv64x60_early_init(bh, si); if (mv64x60_get_type(bh) || mv64x60_setup_for_chip(bh)) { iounmap(bh->v_base); bh->v_base = 0; if (ppc_md.progress) ppc_md.progress("mv64x60_init: Can't determine chip",0); return -1; } bh->ci->disable_all_windows(bh, si); mv64x60_get_mem_windows(bh, mem_windows); mv64x60_config_cpu2mem_windows(bh, si, mem_windows); if (bh->ci->config_io2mem_windows) bh->ci->config_io2mem_windows(bh, si, mem_windows); if (bh->ci->set_mpsc2regs_window) bh->ci->set_mpsc2regs_window(bh, si->phys_reg_base); if (si->pci_1.enable_bus) { bh->io_base_b = (u32)ioremap(si->pci_1.pci_io.cpu_base, si->pci_1.pci_io.size); isa_io_base = bh->io_base_b; } if (si->pci_0.enable_bus) { bh->io_base_a = (u32)ioremap(si->pci_0.pci_io.cpu_base, si->pci_0.pci_io.size); isa_io_base = bh->io_base_a; mv64x60_alloc_hose(bh, MV64x60_PCI0_CONFIG_ADDR, MV64x60_PCI0_CONFIG_DATA, &bh->hose_a); mv64x60_config_resources(bh->hose_a, &si->pci_0, bh->io_base_a); mv64x60_config_pci_params(bh->hose_a, &si->pci_0); mv64x60_config_cpu2pci_windows(bh, &si->pci_0, 0); mv64x60_config_pci2mem_windows(bh, bh->hose_a, &si->pci_0, 0, mem_windows); bh->ci->set_pci2regs_window(bh, bh->hose_a, 0, si->phys_reg_base); } if (si->pci_1.enable_bus) { mv64x60_alloc_hose(bh, MV64x60_PCI1_CONFIG_ADDR, MV64x60_PCI1_CONFIG_DATA, &bh->hose_b); mv64x60_config_resources(bh->hose_b, &si->pci_1, bh->io_base_b); mv64x60_config_pci_params(bh->hose_b, &si->pci_1); mv64x60_config_cpu2pci_windows(bh, &si->pci_1, 1); mv64x60_config_pci2mem_windows(bh, bh->hose_b, &si->pci_1, 1, mem_windows); bh->ci->set_pci2regs_window(bh, bh->hose_b, 1, si->phys_reg_base); } bh->ci->chip_specific_init(bh, si); mv64x60_pd_fixup(bh, mv64x60_pd_devs, ARRAY_SIZE(mv64x60_pd_devs)); return 0;}/* * mv64x60_early_init() * * Do some bridge work that must take place before we start messing with * the bridge for real. */void __initmv64x60_early_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si){ struct pci_controller hose_a, hose_b; memset(bh, 0, sizeof(*bh)); bh->p_base = si->phys_reg_base; bh->v_base = ioremap(bh->p_base, MV64x60_INTERNAL_SPACE_SIZE); mv64x60_bridge_pbase = bh->p_base; mv64x60_bridge_vbase = bh->v_base; /* Assuming pci mode [reserved] bits 4:5 on 64260 are 0 */ bh->pci_mode_a = mv64x60_read(bh, MV64x60_PCI0_MODE) & MV64x60_PCIMODE_MASK; bh->pci_mode_b = mv64x60_read(bh, MV64x60_PCI1_MODE) & MV64x60_PCIMODE_MASK; /* Need temporary hose structs to call mv64x60_set_bus() */ memset(&hose_a, 0, sizeof(hose_a)); memset(&hose_b, 0, sizeof(hose_b)); setup_indirect_pci_nomap(&hose_a, bh->v_base + MV64x60_PCI0_CONFIG_ADDR, bh->v_base + MV64x60_PCI0_CONFIG_DATA); setup_indirect_pci_nomap(&hose_b, bh->v_base + MV64x60_PCI1_CONFIG_ADDR, bh->v_base + MV64x60_PCI1_CONFIG_DATA); bh->hose_a = &hose_a; bh->hose_b = &hose_b;#if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260) /* Save a copy of hose_a for sysfs functions -- hack */ memcpy(&sysfs_hose_a, &hose_a, sizeof(hose_a));#endif mv64x60_set_bus(bh, 0, 0); mv64x60_set_bus(bh, 1, 0); bh->hose_a = NULL; bh->hose_b = NULL; /* Clear bit 0 of PCI addr decode control so PCI->CPU remap 1:1 */ mv64x60_clr_bits(bh, MV64x60_PCI0_PCI_DECODE_CNTL, 0x00000001); mv64x60_clr_bits(bh, MV64x60_PCI1_PCI_DECODE_CNTL, 0x00000001); /* Bit 12 MUST be 0; set bit 27--don't auto-update cpu remap regs */ mv64x60_clr_bits(bh, MV64x60_CPU_CONFIG, (1<<12)); mv64x60_set_bits(bh, MV64x60_CPU_CONFIG, (1<<27)); mv64x60_set_bits(bh, MV64x60_PCI0_TO_RETRY, 0xffff); mv64x60_set_bits(bh, MV64x60_PCI1_TO_RETRY, 0xffff);}/* ***************************************************************************** * * Window Config Routines * ***************************************************************************** *//* * mv64x60_get_32bit_window() * * Determine the base address and size of a 32-bit window on the bridge. */void __initmv64x60_get_32bit_window(struct mv64x60_handle *bh, u32 window, u32 *base, u32 *size){ u32 val, base_reg, size_reg, base_bits, size_bits; u32 (*get_from_field)(u32 val, u32 num_bits); base_reg = bh->ci->window_tab_32bit[window].base_reg; if (base_reg != 0) { size_reg = bh->ci->window_tab_32bit[window].size_reg; base_bits = bh->ci->window_tab_32bit[window].base_bits; size_bits = bh->ci->window_tab_32bit[window].size_bits; get_from_field= bh->ci->window_tab_32bit[window].get_from_field; val = mv64x60_read(bh, base_reg); *base = get_from_field(val, base_bits); if (size_reg != 0) { val = mv64x60_read(bh, size_reg); val = get_from_field(val, size_bits); *size = bh->ci->untranslate_size(*base, val, size_bits); } else *size = 0; } else { *base = 0; *size = 0; } pr_debug("get 32bit window: %d, base: 0x%x, size: 0x%x\n", window, *base, *size);}/* * mv64x60_set_32bit_window() * * Set the base address and size of a 32-bit window on the bridge. */void __initmv64x60_set_32bit_window(struct mv64x60_handle *bh, u32 window, u32 base, u32 size, u32 other_bits){ u32 val, base_reg, size_reg, base_bits, size_bits; u32 (*map_to_field)(u32 val, u32 num_bits); pr_debug("set 32bit window: %d, base: 0x%x, size: 0x%x, other: 0x%x\n", window, base, size, other_bits); base_reg = bh->ci->window_tab_32bit[window].base_reg; if (base_reg != 0) { size_reg = bh->ci->window_tab_32bit[window].size_reg; base_bits = bh->ci->window_tab_32bit[window].base_bits; size_bits = bh->ci->window_tab_32bit[window].size_bits; map_to_field = bh->ci->window_tab_32bit[window].map_to_field; val = map_to_field(base, base_bits) | other_bits; mv64x60_write(bh, base_reg, val); if (size_reg != 0) { val = bh->ci->translate_size(base, size, size_bits); val = map_to_field(val, size_bits); mv64x60_write(bh, size_reg, val); } (void)mv64x60_read(bh, base_reg); /* Flush FIFO */ }}/* * mv64x60_get_64bit_window() * * Determine the base address and size of a 64-bit window on the bridge. */void __initmv64x60_get_64bit_window(struct mv64x60_handle *bh, u32 window, u32 *base_hi, u32 *base_lo, u32 *size){ u32 val, base_lo_reg, size_reg, base_lo_bits, size_bits; u32 (*get_from_field)(u32 val, u32 num_bits); base_lo_reg = bh->ci->window_tab_64bit[window].base_lo_reg; if (base_lo_reg != 0) { size_reg = bh->ci->window_tab_64bit[window].size_reg; base_lo_bits = bh->ci->window_tab_64bit[window].base_lo_bits; size_bits = bh->ci->window_tab_64bit[window].size_bits; get_from_field= bh->ci->window_tab_64bit[window].get_from_field; *base_hi = mv64x60_read(bh, bh->ci->window_tab_64bit[window].base_hi_reg); val = mv64x60_read(bh, base_lo_reg); *base_lo = get_from_field(val, base_lo_bits); if (size_reg != 0) { val = mv64x60_read(bh, size_reg); val = get_from_field(val, size_bits); *size = bh->ci->untranslate_size(*base_lo, val, size_bits); } else *size = 0; } else { *base_hi = 0; *base_lo = 0; *size = 0; } pr_debug("get 64bit window: %d, base hi: 0x%x, base lo: 0x%x, " "size: 0x%x\n", window, *base_hi, *base_lo, *size);}/* * mv64x60_set_64bit_window() * * Set the base address and size of a 64-bit window on the bridge. */void __initmv64x60_set_64bit_window(struct mv64x60_handle *bh, u32 window, u32 base_hi, u32 base_lo, u32 size, u32 other_bits){ u32 val, base_lo_reg, size_reg, base_lo_bits, size_bits; u32 (*map_to_field)(u32 val, u32 num_bits); pr_debug("set 64bit window: %d, base hi: 0x%x, base lo: 0x%x, " "size: 0x%x, other: 0x%x\n", window, base_hi, base_lo, size, other_bits); base_lo_reg = bh->ci->window_tab_64bit[window].base_lo_reg; if (base_lo_reg != 0) { size_reg = bh->ci->window_tab_64bit[window].size_reg; base_lo_bits = bh->ci->window_tab_64bit[window].base_lo_bits; size_bits = bh->ci->window_tab_64bit[window].size_bits; map_to_field = bh->ci->window_tab_64bit[window].map_to_field; mv64x60_write(bh, bh->ci->window_tab_64bit[window].base_hi_reg, base_hi); val = map_to_field(base_lo, base_lo_bits) | other_bits; mv64x60_write(bh, base_lo_reg, val); if (size_reg != 0) { val = bh->ci->translate_size(base_lo, size, size_bits); val = map_to_field(val, size_bits); mv64x60_write(bh, size_reg, val); } (void)mv64x60_read(bh, base_lo_reg); /* Flush FIFO */ }}/* * mv64x60_mask() * * Take the high-order 'num_bits' of 'val' & mask off low bits. */u32 __initmv64x60_mask(u32 val, u32 num_bits){ return val & (0xffffffff << (32 - num_bits));}/* * mv64x60_shift_left() * * Take the low-order 'num_bits' of 'val', shift left to align at bit 31 (MSB). */u32 __initmv64x60_shift_left(u32 val, u32 num_bits){ return val << (32 - num_bits);}/* * mv64x60_shift_right() * * Take the high-order 'num_bits' of 'val', shift right to align at bit 0 (LSB). */u32 __initmv64x60_shift_right(u32 val, u32 num_bits){ return val >> (32 - num_bits);}/* ***************************************************************************** * * Chip Identification Routines * ***************************************************************************** *//* * mv64x60_get_type() * * Determine the type of bridge chip we have. */int __initmv64x60_get_type(struct mv64x60_handle *bh){ struct pci_controller hose; u16 val; u8 save_exclude; memset(&hose, 0, sizeof(hose)); setup_indirect_pci_nomap(&hose, bh->v_base + MV64x60_PCI0_CONFIG_ADDR, bh->v_base + MV64x60_PCI0_CONFIG_DATA); save_exclude = mv64x60_pci_exclude_bridge; mv64x60_pci_exclude_bridge = 0; /* Sanity check of bridge's Vendor ID */ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val); if (val != PCI_VENDOR_ID_MARVELL) { mv64x60_pci_exclude_bridge = save_exclude; return -1; } /* Get the revision of the chip */ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_CLASS_REVISION, &val); bh->rev = (u32)(val & 0xff); /* Figure out the type of Marvell bridge it is */ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_DEVICE_ID, &val); mv64x60_pci_exclude_bridge = save_exclude; switch (val) { case PCI_DEVICE_ID_MARVELL_GT64260: switch (bh->rev) { case GT64260_REV_A: bh->type = MV64x60_TYPE_GT64260A; break; default: printk(KERN_WARNING "Unsupported GT64260 rev %04x\n", bh->rev); /* Assume its similar to a 'B' rev and fallthru */ case GT64260_REV_B: bh->type = MV64x60_TYPE_GT64260B; break; } break; case PCI_DEVICE_ID_MARVELL_MV64360: /* Marvell won't tell me how to distinguish a 64361 & 64362 */ bh->type = MV64x60_TYPE_MV64360; break; case PCI_DEVICE_ID_MARVELL_MV64460: bh->type = MV64x60_TYPE_MV64460; break; default: printk(KERN_ERR "Unknown Marvell bridge type %04x\n", val); return -1; } /* Hang onto bridge type & rev for PIC code */ mv64x60_bridge_type = bh->type; mv64x60_bridge_rev = bh->rev; return 0;}/* * mv64x60_setup_for_chip() * * Set 'bh' to use the proper set of routine for the bridge chip that we have. */int __initmv64x60_setup_for_chip(struct mv64x60_handle *bh){ int rc = 0; /* Set up chip-specific info based on the chip/bridge type */ switch(bh->type) { case MV64x60_TYPE_GT64260A: bh->ci = >64260a_ci; break; case MV64x60_TYPE_GT64260B: bh->ci = >64260b_ci; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -