?? pmc440.c
字號:
/* * pci_pre_init * * This routine is called just prior to registering the hose and gives * the board the opportunity to check things. Returning a value of zero * indicates that things are bad & PCI initialization should be aborted. * * Different boards may wish to customize the pci controller structure * (add regions, override default access routines, etc) or perform * certain pre-initialization actions. */#if defined(CONFIG_PCI)int pci_pre_init(struct pci_controller *hose){ unsigned long addr; /* * Set priority for all PLB3 devices to 0. * Set PLB3 arbiter to fair mode. */ mfsdr(sdr_amp1, addr); mtsdr(sdr_amp1, (addr & 0x000000FF) | 0x0000FF00); addr = mfdcr(plb3_acr); mtdcr(plb3_acr, addr | 0x80000000); /* * Set priority for all PLB4 devices to 0. */ mfsdr(sdr_amp0, addr); mtsdr(sdr_amp0, (addr & 0x000000FF) | 0x0000FF00); addr = mfdcr(plb4_acr) | 0xa0000000; /* Was 0x8---- */ mtdcr(plb4_acr, addr); /* * Set Nebula PLB4 arbiter to fair mode. */ /* Segment0 */ addr = (mfdcr(plb0_acr) & ~plb0_acr_ppm_mask) | plb0_acr_ppm_fair; addr = (addr & ~plb0_acr_hbu_mask) | plb0_acr_hbu_enabled; addr = (addr & ~plb0_acr_rdp_mask) | plb0_acr_rdp_4deep; addr = (addr & ~plb0_acr_wrp_mask) | plb0_acr_wrp_2deep; mtdcr(plb0_acr, addr); /* Segment1 */ addr = (mfdcr(plb1_acr) & ~plb1_acr_ppm_mask) | plb1_acr_ppm_fair; addr = (addr & ~plb1_acr_hbu_mask) | plb1_acr_hbu_enabled; addr = (addr & ~plb1_acr_rdp_mask) | plb1_acr_rdp_4deep; addr = (addr & ~plb1_acr_wrp_mask) | plb1_acr_wrp_2deep; mtdcr(plb1_acr, addr);#ifdef CONFIG_PCI_PNP hose->fixup_irq = pmc440_pci_fixup_irq;#endif return 1;}#endif /* defined(CONFIG_PCI) *//* * pci_target_init * * The bootstrap configuration provides default settings for the pci * inbound map (PIM). But the bootstrap config choices are limited and * may not be sufficient for a given board. */#if defined(CONFIG_PCI) && defined(CONFIG_SYS_PCI_TARGET_INIT)void pci_target_init(struct pci_controller *hose){ char *ptmla_str, *ptmms_str; /* * Set up Direct MMIO registers */ /* * PowerPC440EPX PCI Master configuration. * Map one 1Gig range of PLB/processor addresses to PCI memory space. * PLB address 0x80000000-0xBFFFFFFF * ==> PCI address 0x80000000-0xBFFFFFFF * Use byte reversed out routines to handle endianess. * Make this region non-prefetchable. */ out32r(PCIX0_PMM0MA, 0x00000000); /* PMM0 Mask/Attribute */ /* - disabled b4 setting */ out32r(PCIX0_PMM0LA, CONFIG_SYS_PCI_MEMBASE); /* PMM0 Local Address */ out32r(PCIX0_PMM0PCILA, CONFIG_SYS_PCI_MEMBASE); /* PMM0 PCI Low Address */ out32r(PCIX0_PMM0PCIHA, 0x00000000); /* PMM0 PCI High Address */ out32r(PCIX0_PMM0MA, 0xc0000001); /* 1G + No prefetching, */ /* and enable region */ if (!is_monarch()) { ptmla_str = getenv("ptm1la"); ptmms_str = getenv("ptm1ms"); if(NULL != ptmla_str && NULL != ptmms_str ) { out32r(PCIX0_PTM1MS, simple_strtoul(ptmms_str, NULL, 16)); out32r(PCIX0_PTM1LA, simple_strtoul(ptmla_str, NULL, 16)); } else { /* BAR1: default top 64MB of RAM */ out32r(PCIX0_PTM1MS, 0xfc000001); out32r(PCIX0_PTM1LA, 0x0c000000); } } else { /* BAR1: default: complete 256MB RAM */ out32r(PCIX0_PTM1MS, 0xf0000001); out32r(PCIX0_PTM1LA, 0x00000000); } ptmla_str = getenv("ptm2la"); /* Local Addr. Reg */ ptmms_str = getenv("ptm2ms"); /* Memory Size/Attribute */ if(NULL != ptmla_str && NULL != ptmms_str ) { out32r(PCIX0_PTM2MS, simple_strtoul(ptmms_str, NULL, 16)); out32r(PCIX0_PTM2LA, simple_strtoul(ptmla_str, NULL, 16)); } else { /* BAR2: default: 4MB FPGA */ out32r(PCIX0_PTM2MS, 0xffc00001); /* Memory Size/Attribute */ out32r(PCIX0_PTM2LA, 0xef000000); /* Local Addr. Reg */ } if (is_monarch()) { /* BAR2: map FPGA registers behind system memory at 1GB */ pci_hose_write_config_dword(hose, 0, PCI_BASE_ADDRESS_2, 0x40000008); } /* * Set up Configuration registers */ /* Program the board's vendor id */ pci_hose_write_config_word(hose, 0, PCI_SUBSYSTEM_VENDOR_ID, CONFIG_SYS_PCI_SUBSYS_VENDORID); /* disabled for PMC405 backward compatibility */ /* Configure command register as bus master */ /* pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER); */ /* 240nS PCI clock */ pci_hose_write_config_word(hose, 0, PCI_LATENCY_TIMER, 1); /* No error reporting */ pci_hose_write_config_word(hose, 0, PCI_ERREN, 0); pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101); if (!is_monarch()) { /* Program the board's subsystem id/classcode */ pci_hose_write_config_word(hose, 0, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_ID_NONMONARCH); pci_hose_write_config_word(hose, 0, PCI_CLASS_SUB_CODE, CONFIG_SYS_PCI_CLASSCODE_NONMONARCH); /* PCI configuration done: release ERREADY */ out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_PPC_EREADY); out_be32((void*)GPIO1_TCR, in_be32((void*)GPIO1_TCR) | GPIO1_PPC_EREADY); } else { /* Program the board's subsystem id/classcode */ pci_hose_write_config_word(hose, 0, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_ID_MONARCH); pci_hose_write_config_word(hose, 0, PCI_CLASS_SUB_CODE, CONFIG_SYS_PCI_CLASSCODE_MONARCH); } /* enable host configuration */ pci_hose_write_config_dword(hose, 0, PCI_BRDGOPT2, 0x00000101);}#endif /* defined(CONFIG_PCI) && defined(CONFIG_SYS_PCI_TARGET_INIT) *//* * pci_master_init */#if defined(CONFIG_PCI) && defined(CONFIG_SYS_PCI_MASTER_INIT)void pci_master_init(struct pci_controller *hose){ unsigned short temp_short; /* * Write the PowerPC440 EP PCI Configuration regs. * Enable PowerPC440 EP to be a master on the PCI bus (PMM). * Enable PowerPC440 EP to act as a PCI memory target (PTM). */ if (is_monarch()) { pci_read_config_word(0, PCI_COMMAND, &temp_short); pci_write_config_word(0, PCI_COMMAND, temp_short | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); }}#endif /* defined(CONFIG_PCI) && defined(CONFIG_SYS_PCI_MASTER_INIT) */static void wait_for_pci_ready(void){ int i; char *s = getenv("pcidelay"); /* * We have our own handling of the pcidelay variable. * Using CONFIG_PCI_BOOTDELAY enables pausing for host * and adapter devices. For adapter devices we do not * want this. */ if (s) { int ms = simple_strtoul(s, NULL, 10); printf("PCI: Waiting for %d ms\n", ms); for (i=0; i<ms; i++) udelay(1000); } if (!(in_be32((void*)GPIO1_IR) & GPIO1_PPC_EREADY)) { printf("PCI: Waiting for EREADY (CTRL-C to skip) ... "); while (1) { if (ctrlc()) { puts("abort\n"); break; } if (in_be32((void*)GPIO1_IR) & GPIO1_PPC_EREADY) { printf("done\n"); break; } } }}/* * is_pci_host * * This routine is called to determine if a pci scan should be * performed. With various hardware environments (especially cPCI and * PPMC) it's insufficient to depend on the state of the arbiter enable * bit in the strap register, or generic host/adapter assumptions. * * Rather than hard-code a bad assumption in the general 440 code, the * 440 pci code requires the board to decide at runtime. * * Return 0 for adapter mode, non-zero for host (monarch) mode. */#if defined(CONFIG_PCI)int is_pci_host(struct pci_controller *hose){ char *s = getenv("pciscan"); if (s == NULL) if (is_monarch()) { wait_for_pci_ready(); return 1; } else return 0; else if (!strcmp(s, "yes")) return 1; return 0;}#endif /* defined(CONFIG_PCI) */#if defined(CONFIG_POST)/* * Returns 1 if keys pressed to start the power-on long-running tests * Called from board_init_f(). */int post_hotkeys_pressed(void){ return 0; /* No hotkeys supported */}#endif /* CONFIG_POST */#ifdef CONFIG_RESET_PHY_Rvoid reset_phy(void){ char *s; unsigned short val_method, val_behavior; /* special LED setup for NGCC/CANDES */ if ((s = getenv("bd_type")) && ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes")))) { val_method = 0x0e0a; val_behavior = 0x0cf2; } else { /* PMC440 standard type */ val_method = 0x0e10; val_behavior = 0x0cf0; } if (miiphy_write("ppc_4xx_eth0", CONFIG_PHY_ADDR, 0x1f, 0x0001) == 0) { miiphy_write("ppc_4xx_eth0", CONFIG_PHY_ADDR, 0x11, 0x0010); miiphy_write("ppc_4xx_eth0", CONFIG_PHY_ADDR, 0x11, val_behavior); miiphy_write("ppc_4xx_eth0", CONFIG_PHY_ADDR, 0x10, val_method); miiphy_write("ppc_4xx_eth0", CONFIG_PHY_ADDR, 0x1f, 0x0000); } if (miiphy_write("ppc_4xx_eth1", CONFIG_PHY1_ADDR, 0x1f, 0x0001) == 0) { miiphy_write("ppc_4xx_eth1", CONFIG_PHY1_ADDR, 0x11, 0x0010); miiphy_write("ppc_4xx_eth1", CONFIG_PHY1_ADDR, 0x11, val_behavior); miiphy_write("ppc_4xx_eth1", CONFIG_PHY1_ADDR, 0x10, val_method); miiphy_write("ppc_4xx_eth1", CONFIG_PHY1_ADDR, 0x1f, 0x0000); }}#endif#if defined(CONFIG_SYS_EEPROM_WREN)/* * Input: <dev_addr> I2C address of EEPROM device to enable. * <state> -1: deliver current state * 0: disable write * 1: enable write * Returns: -1: wrong device address * 0: dis-/en- able done * 0/1: current state if <state> was -1. */int eeprom_write_enable(unsigned dev_addr, int state){ if ((CONFIG_SYS_I2C_EEPROM_ADDR != dev_addr) && (CONFIG_SYS_I2C_BOOT_EEPROM_ADDR != dev_addr)) { return -1; } else { switch (state) { case 1: /* Enable write access, clear bit GPIO_SINT2. */ out32(GPIO0_OR, in32(GPIO0_OR) & ~GPIO0_EP_EEP); state = 0; break; case 0: /* Disable write access, set bit GPIO_SINT2. */ out32(GPIO0_OR, in32(GPIO0_OR) | GPIO0_EP_EEP); state = 0; break; default: /* Read current status back. */ state = (0 == (in32(GPIO0_OR) & GPIO0_EP_EEP)); break; } } return state;}#endif /* #if defined(CONFIG_SYS_EEPROM_WREN) */#define CONFIG_SYS_BOOT_EEPROM_PAGE_WRITE_BITS 3int bootstrap_eeprom_write(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt){ unsigned end = offset + cnt; unsigned blk_off; int rcode = 0;#if defined(CONFIG_SYS_EEPROM_WREN) eeprom_write_enable(dev_addr, 1);#endif /* * Write data until done or would cross a write page boundary. * We must write the address again when changing pages * because the address counter only increments within a page. */ while (offset < end) { unsigned alen, len; unsigned maxlen; uchar addr[2]; blk_off = offset & 0xFF; /* block offset */ addr[0] = offset >> 8; /* block number */ addr[1] = blk_off; /* block offset */ alen = 2; addr[0] |= dev_addr; /* insert device address */ len = end - offset;#define BOOT_EEPROM_PAGE_SIZE (1 << CONFIG_SYS_BOOT_EEPROM_PAGE_WRITE_BITS)#define BOOT_EEPROM_PAGE_OFFSET(x) ((x) & (BOOT_EEPROM_PAGE_SIZE - 1)) maxlen = BOOT_EEPROM_PAGE_SIZE - BOOT_EEPROM_PAGE_OFFSET(blk_off); if (maxlen > I2C_RXTX_LEN) maxlen = I2C_RXTX_LEN; if (len > maxlen) len = maxlen; if (i2c_write (addr[0], offset, alen-1, buffer, len) != 0) rcode = 1; buffer += len; offset += len;#if defined(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS) udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);#endif }#if defined(CONFIG_SYS_EEPROM_WREN) eeprom_write_enable(dev_addr, 0);#endif return rcode;}int bootstrap_eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt){ unsigned end = offset + cnt; unsigned blk_off; int rcode = 0; /* * Read data until done or would cross a page boundary. * We must write the address again when changing pages * because the next page may be in a different device. */ while (offset < end) { unsigned alen, len; unsigned maxlen; uchar addr[2]; blk_off = offset & 0xFF; /* block offset */ addr[0] = offset >> 8; /* block number */ addr[1] = blk_off; /* block offset */ alen = 2; addr[0] |= dev_addr; /* insert device address */ len = end - offset; maxlen = 0x100 - blk_off; if (maxlen > I2C_RXTX_LEN) maxlen = I2C_RXTX_LEN; if (len > maxlen) len = maxlen; if (i2c_read (addr[0], offset, alen-1, buffer, len) != 0) rcode = 1; buffer += len; offset += len; } return rcode;}#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_BOARD_INIT)int usb_board_init(void){ char *act = getenv("usbact"); int i; if ((act == NULL || strcmp(act, "host") == 0) && !(in_be32((void*)GPIO0_IR) & GPIO0_USB_PRSNT)) /* enable power on USB socket */ out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_USB_PWR_N); for (i=0; i<1000; i++) udelay(1000); return 0;}int usb_board_stop(void){ /* disable power on USB socket */ out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_USB_PWR_N); return 0;}int usb_board_init_fail(void){ usb_board_stop(); return 0;}#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_BOARD_INIT) */#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)void ft_board_setup(void *blob, bd_t *bd){ int rc; __ft_board_setup(blob, bd); /* * Disable PCI in non-monarch mode. */ if (!is_monarch()) { rc = fdt_find_and_setprop(blob, "/plb/pci@1ec000000", "status", "disabled", sizeof("disabled"), 1); if (rc) { printf("Unable to update property status in PCI node, err=%s\n", fdt_strerror(rc)); } }}#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -