summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorLiu Gang <Gang.Liu@freescale.com>2012-08-09 05:10:02 +0000
committerAndy Fleming <afleming@freescale.com>2012-08-23 10:24:15 -0500
commitb5f7c8732ad99b0c1a7fa456f706de1ab7d74eef (patch)
tree4f9da9d46e6b662cd0572ddaa0fd6d592f275ec5 /drivers/pci
parentfc54c7fa0addfc0e33b703be0502395920d2926b (diff)
downloadu-boot-imx-b5f7c8732ad99b0c1a7fa456f706de1ab7d74eef.zip
u-boot-imx-b5f7c8732ad99b0c1a7fa456f706de1ab7d74eef.tar.gz
u-boot-imx-b5f7c8732ad99b0c1a7fa456f706de1ab7d74eef.tar.bz2
powerpc/corenet_ds: Master module for boot from PCIE
For the powerpc processors with PCIE interface, boot location can be configured from one PCIE interface by RCW. The processor booting from PCIE can do without flash for u-boot image. The image can be fetched from another processor's memory space by PCIE link connected between them. The processor booting from PCIE is slave, the processor booting from normal flash memory space is master, and it can help slave to boot from master's memory space. When boot from PCIE, slave's core should be in holdoff after powered on for some specific requirements. Master will release the slave's core at the right time by PCIE interface. Environment and requirement: master: 1. NOR flash for its own u-boot image, ucode and ENV space. 2. Slave's u-boot image is in master NOR flash. 3. Normally boot from local NOR flash. 4. Configure PCIE system if needed. slave: 1. Just has EEPROM for RCW. No flash for u-boot image, ucode and ENV. 2. Boot location should be set to one PCIE interface by RCW. 3. RCW should configure the SerDes, PCIE interfaces correctly. 4. Must set all the cores in holdoff by RCW. 5. Must be powered on before master's boot. For the master module, need to finish these processes: 1. Initialize the PCIE port and address space. 2. Set inbound PCIE windows covered slave's u-boot image stored in master's NOR flash. 3. Set outbound windows in order to configure slave's registers for the core's releasing. 4. Should set the environment variable "bootmaster" to "PCIE1", "PCIE2" or "PCIE3" using the following command: setenv bootmaster PCIE1 saveenv Signed-off-by: Liu Gang <Gang.Liu@freescale.com> Signed-off-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/fsl_pci_init.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 1d75a82..0d46c96 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -211,6 +211,95 @@ static int fsl_pci_setup_inbound_windows(struct pci_controller *hose,
return 1;
}
+#ifdef CONFIG_FSL_CORENET
+static void fsl_pcie_boot_master(pit_t *pi)
+{
+ /* configure inbound window for slave's u-boot image */
+ debug("PCIEBOOT - MASTER: Inbound window for slave's image; "
+ "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n",
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS,
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE);
+ struct pci_region r_inbound;
+ u32 sz_inbound = __ilog2_u64(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE)
+ - 1;
+ pci_set_region(&r_inbound,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS,
+ sz_inbound,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ set_inbound_window(pi--, &r_inbound,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE);
+
+ /* configure inbound window for slave's u-boot image */
+ debug("PCIEBOOT - MASTER: Inbound window for slave's image; "
+ "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n",
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS,
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE);
+ pci_set_region(&r_inbound,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS,
+ sz_inbound,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ set_inbound_window(pi--, &r_inbound,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE);
+
+ /* configure inbound window for slave's ucode and ENV */
+ debug("PCIEBOOT - MASTER: Inbound window for slave's "
+ "ucode and ENV; "
+ "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n",
+ (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS,
+ (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE);
+ sz_inbound = __ilog2_u64(CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE)
+ - 1;
+ pci_set_region(&r_inbound,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS,
+ sz_inbound,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ set_inbound_window(pi--, &r_inbound,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE);
+}
+
+static void fsl_pcie_boot_master_release_slave(int port)
+{
+ unsigned long release_addr;
+
+ /* now release slave's core 0 */
+ switch (port) {
+ case 1:
+ release_addr = CONFIG_SYS_PCIE1_MEM_VIRT
+ + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET;
+ break;
+ case 2:
+ release_addr = CONFIG_SYS_PCIE2_MEM_VIRT
+ + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET;
+ break;
+ case 3:
+ release_addr = CONFIG_SYS_PCIE3_MEM_VIRT
+ + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET;
+ break;
+ default:
+ release_addr = 0;
+ break;
+ }
+ if (release_addr != 0) {
+ out_be32((void *)release_addr,
+ CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK);
+ debug("PCIEBOOT - MASTER: "
+ "Release slave successfully! Now the slave should start up!\n");
+ } else {
+ debug("PCIEBOOT - MASTER: "
+ "Release slave failed!\n");
+ }
+}
+#endif
+
void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
{
u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr;
@@ -295,8 +384,25 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
/* see if we are a PCIe or PCI controller */
pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
+#ifdef CONFIG_FSL_CORENET
+ /* boot from PCIE --master */
+ char *s = getenv("bootmaster");
+ char pcie[6];
+ sprintf(pcie, "PCIE%d", pci_info->pci_num);
+
+ if (s && (strcmp(s, pcie) == 0)) {
+ debug("PCIEBOOT - MASTER: Master port [ %d ] for pcie boot.\n",
+ pci_info->pci_num);
+ fsl_pcie_boot_master((pit_t *)pi);
+ } else {
+ /* inbound */
+ inbound = fsl_pci_setup_inbound_windows(hose,
+ out_lo, pcie_cap, pi);
+ }
+#else
/* inbound */
inbound = fsl_pci_setup_inbound_windows(hose, out_lo, pcie_cap, pi);
+#endif
for (r = 0; r < hose->region_count; r++)
debug("PCI reg:%d %016llx:%016llx %016llx %08lx\n", r,
@@ -488,6 +594,16 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info,
if (fsl_is_pci_agent(hose)) {
fsl_pci_config_unlock(hose);
hose->last_busno = hose->first_busno;
+#ifdef CONFIG_FSL_CORENET
+ } else {
+ /* boot from PCIE --master releases slave's core 0 */
+ char *s = getenv("bootmaster");
+ char pcie[6];
+ sprintf(pcie, "PCIE%d", pci_info->pci_num);
+
+ if (s && (strcmp(s, pcie) == 0))
+ fsl_pcie_boot_master_release_slave(pci_info->pci_num);
+#endif
}
pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);