From a6da8b8195f47a70106f743948f2729d94157b32 Mon Sep 17 00:00:00 2001 From: Chenhui Zhao Date: Tue, 4 Jan 2011 17:23:05 +0800 Subject: fsl_esdhc: Fix esdhc disabled problem on some platforms Some new platform's esdhc pins don't share with other function. The eSDHC shouldn't be disabled, even if "esdhc" isn't defined in hwconfig env variable. Use CONFIG_FSL_ESDHC_PIN_MUX to fix this problem. Signed-off-by: Chenhui Zhao Signed-off-by: Li Yang Signed-off-by: Kumar Gala --- drivers/mmc/fsl_esdhc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 40b136c..cef2859 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -508,17 +508,19 @@ int fsl_esdhc_mmc_init(bd_t *bis) void fdt_fixup_esdhc(void *blob, bd_t *bd) { const char *compat = "fsl,esdhc"; - const char *status = "okay"; +#ifdef CONFIG_FSL_ESDHC_PIN_MUX if (!hwconfig("esdhc")) { - status = "disabled"; - goto out; + do_fixup_by_compat(blob, compat, "status", "disabled", + 8 + 1, 1); + return; } +#endif do_fixup_by_compat_u32(blob, compat, "clock-frequency", gd->sdhc_clk, 1); -out: - do_fixup_by_compat(blob, compat, "status", status, - strlen(status) + 1, 1); + + do_fixup_by_compat(blob, compat, "status", "okay", + 4 + 1, 1); } #endif -- cgit v1.1 From 3a0e3c27a50e395a59497e8bd60a00404e662eb1 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 17 Dec 2010 05:57:25 -0600 Subject: powerpc/fsl-pci: Determine pci_controller based on cfg addr for dts fixup Previously we passed in a specifically named struct pci_controller to determine if we had setup the particular PCI bus. Now we can search for the struct so we dont have to depend on the name or the struct being statically allocated. Introduced new find_hose_by_cfg_addr() to get back a pci_controller struct back by searching for it means we can do things like dynamically allocate them or not have to expose the static structures to all users. Signed-off-by: Kumar Gala Acked-by: Wolfgang Denk --- drivers/pci/fsl_pci_init.c | 5 ++++- drivers/pci/pci.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 5b34dcb..71ab02b 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -518,11 +518,14 @@ void fsl_pci_config_unlock(struct pci_controller *hose) #include void ft_fsl_pci_setup(void *blob, const char *pci_compat, - struct pci_controller *hose, unsigned long ctrl_addr) + unsigned long ctrl_addr) { int off; u32 bus_range[2]; phys_addr_t p_ctrl_addr = (phys_addr_t)ctrl_addr; + struct pci_controller *hose; + + hose = find_hose_by_cfg_addr((void *)(ctrl_addr)); /* convert ctrl_addr to true physical address */ p_ctrl_addr = (phys_addr_t)ctrl_addr - CONFIG_SYS_CCSRBAR; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 702ac67..cdfc4fb 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -165,6 +165,18 @@ struct pci_controller *pci_bus_to_hose (int bus) return NULL; } +struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr) +{ + struct pci_controller *hose; + + for (hose = hose_head; hose; hose = hose->next) { + if (hose->cfg_addr == cfg_addr) + return hose; + } + + return NULL; +} + int pci_last_busno(void) { struct pci_controller *hose = hose_head; -- cgit v1.1 From a4aafcc990c12816cfd4644e5c003d8556b6236b Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 15 Dec 2010 14:21:41 -0600 Subject: powerpc/fsl-pci: Add generic code to setup PCIe controllers Since all the PCIe controllers are connected over SERDES on the SoCs we can utilize is_serdes_configured() to determine if a controller is enabled. After which we can setup the ATMUs and LAWs for the controller in a common fashion and allow board code to specify what the controller is connected to for reporting reasons. We also provide a per controller (rather than all) for some systems that may have special requirements. Finally, we refactor the code used by the P1022DS to utilize the new generic code. Based on patch by: Li Yang Signed-off-by: Kumar Gala --- drivers/pci/fsl_pci_init.c | 148 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 71ab02b..d762336 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -18,6 +18,8 @@ */ #include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -513,6 +515,152 @@ void fsl_pci_config_unlock(struct pci_controller *hose) } } +#if defined(CONFIG_PCIE1) || defined(CONFIG_PCIE2) || \ + defined(CONFIG_PCIE3) || defined(CONFIG_PCIE4) +int fsl_configure_pcie(struct fsl_pci_info *info, + struct pci_controller *hose, + const char *connected, int busno) +{ + int is_endpoint; + + set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law); + set_next_law(info->io_phys, law_size_bits(info->io_size), info->law); + is_endpoint = fsl_setup_hose(hose, info->regs); + printf("PCIE%u: connected to %s as %s (base addr %lx)\n", + info->pci_num, connected, + is_endpoint ? "Endpoint" : "Root Complex", info->regs); + return fsl_pci_init_port(info, hose, busno); +} + +#if defined(CONFIG_FSL_CORENET) + #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1 + #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2 + #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3 + #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4 + #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR +#elif defined(CONFIG_MPC85xx) + #define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE + #define _DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2 + #define _DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3 + #define _DEVDISR_PCIE4 0 + #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR +#elif defined(CONFIG_MPC86xx) + #define _DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIE1 + #define _DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIE2 + #define _DEVDISR_PCIE3 0 + #define _DEVDISR_PCIE4 0 + #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \ + (&((immap_t *)CONFIG_SYS_IMMR)->im_gur) +#else +#error "No defines for DEVDISR_PCIE" +#endif + +/* Implement a dummy function for those platforms w/o SERDES */ +static const char *__board_serdes_name(enum srds_prtcl device) +{ + switch (device) { +#ifdef CONFIG_SYS_PCIE1_NAME + case PCIE1: + return CONFIG_SYS_PCIE1_NAME; +#endif +#ifdef CONFIG_SYS_PCIE2_NAME + case PCIE2: + return CONFIG_SYS_PCIE2_NAME; +#endif +#ifdef CONFIG_SYS_PCIE3_NAME + case PCIE3: + return CONFIG_SYS_PCIE3_NAME; +#endif +#ifdef CONFIG_SYS_PCIE4_NAME + case PCIE4: + return CONFIG_SYS_PCIE4_NAME; +#endif + default: + return NULL; + } + + return NULL; +} + +__attribute__((weak, alias("__board_serdes_name"))) const char * +board_serdes_name(enum srds_prtcl device); + +static u32 devdisr_mask[] = { + _DEVDISR_PCIE1, + _DEVDISR_PCIE2, + _DEVDISR_PCIE3, + _DEVDISR_PCIE4, +}; + +int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, + struct fsl_pci_info *pci_info) +{ + struct pci_controller *hose; + int num = dev - PCIE1; + + hose = calloc(1, sizeof(struct pci_controller)); + if (!hose) + return busno; + + if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) { + busno = fsl_configure_pcie(pci_info, hose, + board_serdes_name(dev), busno); + } else { + printf("PCIE%d: disabled\n", num + 1); + } + + return busno; +} + +int fsl_pcie_init_board(int busno) +{ + struct fsl_pci_info pci_info; + ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR; + u32 devdisr = in_be32(&gur->devdisr); + +#ifdef CONFIG_PCIE1 + SET_STD_PCIE_INFO(pci_info, 1); + busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info); +#else + setbits_be32(&gur->devdisr, _DEVDISR_PCIE1); /* disable */ +#endif + +#ifdef CONFIG_PCIE2 + SET_STD_PCIE_INFO(pci_info, 2); + busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info); +#else + setbits_be32(&gur->devdisr, _DEVDISR_PCIE2); /* disable */ +#endif + +#ifdef CONFIG_PCIE3 + SET_STD_PCIE_INFO(pci_info, 3); + busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info); +#else + setbits_be32(&gur->devdisr, _DEVDISR_PCIE3); /* disable */ +#endif + +#ifdef CONFIG_PCIE4 + SET_STD_PCIE_INFO(pci_info, 4); + busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info); +#else + setbits_be32(&gur->devdisr, _DEVDISR_PCIE4); /* disable */ +#endif + + return busno; +} +#else +int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, + struct fsl_pci_info *pci_info) +{ + return busno; +} + +int fsl_pcie_init_board(int busno) +{ + return busno; +} +#endif + #ifdef CONFIG_OF_BOARD_SETUP #include #include -- cgit v1.1 From 213ac73e2caff8b477c31f85d8132f8cc116f366 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Tue, 28 Dec 2010 17:47:25 -0600 Subject: fsl_pci: Update PCIe boot ouput This change does the following: - Adds printing of negotiated link width. This information can be useful when debugging PCIe issues. - Makes it optional for boards to implement board_serdes_name(). Previously boards that did not implement it would print unsightly output such as "PCIE1: Connected to ..." - Rewords the PCIe boot output to reduce line length and to make it clear that the "base address XYZ" value refers to the base address of the internal processor PCIe registers and not a standard PCI BAR value. - Changes "PCIE" output to the standard "PCIe" Before change: PCIE1: connected to as Root Complex (base addr ef008000) 01:00.0 - 10b5:8518 - Bridge device 02:01.0 - 10b5:8518 - Bridge device 02:02.0 - 10b5:8518 - Bridge device 02:03.0 - 10b5:8518 - Bridge device PCIE1: Bus 00 - 05 PCIE2: connected to as Endpoint (base addr ef009000) PCIE2: Bus 06 - 06 After change: PCIe1: Root Complex of PEX8518 Switch, x4, regs @ 0xef008000 01:00.0 - 10b5:8518 - Bridge device 02:01.0 - 10b5:8518 - Bridge device 02:02.0 - 10b5:8518 - Bridge device 02:03.0 - 10b5:8518 - Bridge device PCIe1: Bus 00 - 05 PCIe2: Endpoint of VPX Fabric A, x2, regs @ 0xef009000 PCIe2: Bus 06 - 06 Signed-off-by: Peter Tyser Signed-off-by: Kumar Gala --- drivers/pci/fsl_pci_init.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index d762336..6c168c1 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -217,8 +217,10 @@ static int fsl_pci_setup_inbound_windows(struct pci_controller *hose, return 1; } -void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) +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; + u32 cfg_data = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_data; u16 temp16; u32 temp32; int enabled, r, inbound = 0; @@ -235,10 +237,6 @@ void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) u64 out_hi = 0, out_lo = -1ULL; u32 pcicsrbar, pcicsrbar_sz; -#ifdef DEBUG - int neg_link_w; -#endif - pci_setup_indirect(hose, cfg_addr, cfg_data); /* Handle setup of outbound windows first */ @@ -354,20 +352,20 @@ void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) #endif if (!enabled) { - debug("....PCIE link error. Skipping scan." - "LTSSM=0x%02x\n", ltssm); + /* Let the user know there's no PCIe link */ + printf("no link, regs @ 0x%lx\n", pci_info->regs); hose->last_busno = hose->first_busno; return; } out_be32(&pci->pme_msg_det, 0xffffffff); out_be32(&pci->pme_msg_int_en, 0xffffffff); -#ifdef DEBUG + + /* Print the negotiated PCIe link width */ pci_hose_read_config_word(hose, dev, PCI_LSR, &temp16); - neg_link_w = (temp16 & 0x3f0 ) >> 4; - printf("...PCIE LTSSM=0x%x, Negotiated link width=%d\n", - ltssm, neg_link_w); -#endif + printf("x%d, regs @ 0x%lx\n", (temp16 & 0x3f0 ) >> 4, + pci_info->regs); + hose->current_busno++; /* Start scan with secondary */ pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); } @@ -476,7 +474,7 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info, hose->region_count = r - hose->regions; hose->first_busno = busno; - fsl_pci_init(hose, (u32)&pci->cfg_addr, (u32)&pci->cfg_data); + fsl_pci_init(hose, pci_info); if (fsl_is_pci_agent(hose)) { fsl_pci_config_unlock(hose); @@ -485,7 +483,7 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info, pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); printf("PCI%s%x: Bus %02x - %02x\n", pcie_cap == PCI_CAP_ID_EXP ? - "E" : "", pci_info->pci_num, + "e" : "", pci_info->pci_num, hose->first_busno, hose->last_busno); return(hose->last_busno + 1); @@ -525,10 +523,14 @@ int fsl_configure_pcie(struct fsl_pci_info *info, set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law); set_next_law(info->io_phys, law_size_bits(info->io_size), info->law); + is_endpoint = fsl_setup_hose(hose, info->regs); - printf("PCIE%u: connected to %s as %s (base addr %lx)\n", - info->pci_num, connected, - is_endpoint ? "Endpoint" : "Root Complex", info->regs); + printf("PCIe%u: %s", info->pci_num, + is_endpoint ? "Endpoint" : "Root Complex"); + if (connected) + printf(" of %s", connected); + puts(", "); + return fsl_pci_init_port(info, hose, busno); } @@ -606,7 +608,7 @@ int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, busno = fsl_configure_pcie(pci_info, hose, board_serdes_name(dev), busno); } else { - printf("PCIE%d: disabled\n", num + 1); + printf("PCIe%d: disabled\n", num + 1); } return busno; -- cgit v1.1 From d621da0066dff92a76ca3c6fb031a7f823a811f3 Mon Sep 17 00:00:00 2001 From: Jerry Huang Date: Thu, 6 Jan 2011 23:42:19 -0600 Subject: fsl_esdhc: Add the workaround for erratum ESDHC111 (enable on P4080) Do not issue a manual asynchronous CMD12. Instead, use a (software) synchronous CMD12 or AUTOCMD12 to abort data transfer. Signed-off-by: Jerry Huang Signed-off-by: Roy Zang Signed-off-by: Kumar Gala --- drivers/mmc/fsl_esdhc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index cef2859..fe94164 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -1,5 +1,5 @@ /* - * Copyright 2007,2010 Freescale Semiconductor, Inc + * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc * Andy Fleming * * Based vaguely on the pxa mmc code: @@ -79,6 +79,9 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) if (data->blocks > 1) { xfertyp |= XFERTYP_MSBSEL; xfertyp |= XFERTYP_BCEN; +#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 + xfertyp |= XFERTYP_AC12EN; +#endif } if (data->flags & MMC_DATA_READ) @@ -234,6 +237,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; +#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 + if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) + return 0; +#endif + esdhc_write32(®s->irqstat, -1); sync(); -- cgit v1.1 From 3b4456ec391877a950dd5e98ee20df6560f0e1af Mon Sep 17 00:00:00 2001 From: Roy Zang Date: Fri, 7 Jan 2011 00:06:47 -0600 Subject: fsl_esdhc: Add the workaround for erratum ESDHC135 (enable on P4080) The default value of the SRS, VS18 and VS30 and ADMAS fields in the host controller capabilities register (HOSTCAPBLT) are incorrect. The default of these bits should be zero instead of one. Clear these bits out when we read HOSTCAPBLT. Signed-off-by: Roy Zang Signed-off-by: Kumar Gala --- drivers/mmc/fsl_esdhc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index fe94164..d01c926 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -472,6 +472,11 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) voltage_caps = 0; caps = regs->hostcapblt; + +#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135 + caps = caps & ~(ESDHC_HOSTCAPBLT_SRS | + ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30); +#endif if (caps & ESDHC_HOSTCAPBLT_VS18) voltage_caps |= MMC_VDD_165_195; if (caps & ESDHC_HOSTCAPBLT_VS30) -- cgit v1.1