* Authors: Tony Li <tony.li@freescale.com>
* Anton Vorontsov <avorontsov@ru.mvista.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#define PCIE_MAX_BUSES 2
+static struct {
+ u32 base;
+ u32 size;
+} mpc83xx_pcie_cfg_space[] = {
+ {
+ .base = CONFIG_SYS_PCIE1_CFG_BASE,
+ .size = CONFIG_SYS_PCIE1_CFG_SIZE,
+ },
+#if defined(CONFIG_SYS_PCIE2_CFG_BASE) && defined(CONFIG_SYS_PCIE2_CFG_SIZE)
+ {
+ .base = CONFIG_SYS_PCIE2_CFG_BASE,
+ .size = CONFIG_SYS_PCIE2_CFG_SIZE,
+ },
+#endif
+};
+
#ifdef CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES
+/* private structure for mpc83xx pcie hose */
+static struct mpc83xx_pcie_priv {
+ u8 index;
+} pcie_priv[PCIE_MAX_BUSES] = {
+ {
+ /* pcie controller 1 */
+ .index = 0,
+ },
+ {
+ /* pcie controller 2 */
+ .index = 1,
+ },
+};
+
static int mpc83xx_pcie_remap_cfg(struct pci_controller *hose, pci_dev_t dev)
{
int bus = PCI_BUS(dev) - hose->first_busno;
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
- pex83xx_t *pex = &immr->pciexp[bus];
+ struct mpc83xx_pcie_priv *pcie_priv = hose->priv_data;
+ pex83xx_t *pex = &immr->pciexp[pcie_priv->index];
struct pex_outbound_window *out_win = &pex->bridge.pex_outbound_win[0];
u8 devfn = PCI_DEV(dev) << 3 | PCI_FUNC(dev);
u32 dev_base = bus << 24 | devfn << 16;
hose->first_busno = pci_last_busno() + 1;
hose->last_busno = 0xff;
- if (bus == 0)
- hose->cfg_addr = (unsigned int *)CONFIG_SYS_PCIE1_CFG_BASE;
- else
- hose->cfg_addr = (unsigned int *)CONFIG_SYS_PCIE2_CFG_BASE;
+ hose->cfg_addr = (unsigned int *)mpc83xx_pcie_cfg_space[bus].base;
+
+ hose->priv_data = &pcie_priv[bus];
pci_set_ops(hose,
pcie_read_config_byte,
PEX_CSB_OBCTRL_CFGWE);
out_win = &pex->bridge.pex_outbound_win[0];
- if (bus) {
- out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
- CONFIG_SYS_PCIE2_CFG_SIZE);
- out_le32(&out_win->bar, CONFIG_SYS_PCIE2_CFG_BASE);
- } else {
- out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
- CONFIG_SYS_PCIE1_CFG_SIZE);
- out_le32(&out_win->bar, CONFIG_SYS_PCIE1_CFG_BASE);
- }
+ out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
+ mpc83xx_pcie_cfg_space[bus].size);
+ out_le32(&out_win->bar, mpc83xx_pcie_cfg_space[bus].base);
out_le32(&out_win->tarl, 0);
out_le32(&out_win->tarh, 0);
- for (i = 0; i < 2; i++, reg++) {
+ for (i = 0; i < 2; i++) {
u32 ar;
- if (reg->size == 0)
+ if (reg[i].size == 0)
break;
out_win = &pex->bridge.pex_outbound_win[i + 1];
- out_le32(&out_win->bar, reg->phys_start);
- out_le32(&out_win->tarl, reg->bus_start);
+ out_le32(&out_win->bar, reg[i].phys_start);
+ out_le32(&out_win->tarl, reg[i].bus_start);
out_le32(&out_win->tarh, 0);
- ar = PEX_OWAR_EN | (reg->size & PEX_OWAR_SIZE);
- if (reg->flags & PCI_REGION_IO)
+ ar = PEX_OWAR_EN | (reg[i].size & PEX_OWAR_SIZE);
+ if (reg[i].flags & PCI_REGION_IO)
ar |= PEX_OWAR_TYPE_IO;
else
ar |= PEX_OWAR_TYPE_MEM;
get_clocks();
/* Configure the PCIE controller core clock ratio */
out_le32(hose_cfg_base + PEX_GCLK_RATIO,
- (((bus ? gd->pciexp2_clk : gd->pciexp1_clk) / 1000000) * 16)
- / 333);
+ (((bus ? gd->arch.pciexp2_clk : gd->arch.pciexp1_clk)
+ / 1000000) * 16) / 333);
udelay(1000000);
/* Do Type 1 bridge configuration */
printf("PCIE%d: ", bus);
+#define PCI_LTSSM 0x404 /* PCIe Link Training, Status State Machine */
+#define PCI_LTSSM_L0 0x16 /* L0 state */
reg16 = in_le16(hose_cfg_base + PCI_LTSSM);
if (reg16 >= PCI_LTSSM_L0)
printf("link\n");
* The caller must have already set SCCR, SERDES and the PCIE_LAW BARs
* must have been set to cover all of the requested regions.
*/
-void mpc83xx_pcie_init(int num_buses, struct pci_region **reg, int warmboot)
+void mpc83xx_pcie_init(int num_buses, struct pci_region **reg)
{
int i;
/*
* Release PCI RST Output signal.
* Power on to RST high must be at least 100 ms as per PCI spec.
- * On warm boots only 1 ms is required.
+ * On warm boots only 1 ms is required, but we play it safe.
*/
- udelay(warmboot ? 1000 : 100000);
+ udelay(100000);
+
+ if (num_buses > ARRAY_SIZE(mpc83xx_pcie_cfg_space)) {
+ printf("Second PCIE host contoller not configured!\n");
+ num_buses = ARRAY_SIZE(mpc83xx_pcie_cfg_space);
+ }
for (i = 0; i < num_buses; i++)
mpc83xx_pcie_init_bus(i, reg[i]);