コード例 #1
0
static int __init mpc836x_usb_cfg(void)
{
	u8 __iomem *bcsr;
	struct device_node *np;
	const char *mode;
	int ret = 0;

	np = of_find_compatible_node(NULL, NULL, "fsl,mpc8360mds-bcsr");
	if (!np)
		return -ENODEV;

	bcsr = of_iomap(np, 0);
	of_node_put(np);
	if (!bcsr)
		return -ENOMEM;

	np = of_find_compatible_node(NULL, NULL, "fsl,mpc8323-qe-usb");
	if (!np) {
		ret = -ENODEV;
		goto err;
	}

#define BCSR8_TSEC1M_MASK	(0x3 << 6)
#define BCSR8_TSEC1M_RGMII	(0x0 << 6)
#define BCSR8_TSEC2M_MASK	(0x3 << 4)
#define BCSR8_TSEC2M_RGMII	(0x0 << 4)
	/*
                                                                    
                                          
  */
	clrsetbits_8(&bcsr[8], BCSR8_TSEC1M_MASK | BCSR8_TSEC2M_MASK,
			       BCSR8_TSEC1M_RGMII | BCSR8_TSEC2M_RGMII);

#define BCSR13_USBMASK	0x0f
#define BCSR13_nUSBEN	0x08 /*                           */
#define BCSR13_USBSPEED	0x04 /*                     */
#define BCSR13_USBMODE	0x02 /*                          */
#define BCSR13_nUSBVCC	0x01 /*                                   */

	clrsetbits_8(&bcsr[13], BCSR13_USBMASK, BCSR13_USBSPEED);

	mode = of_get_property(np, "mode", NULL);
	if (mode && !strcmp(mode, "peripheral")) {
		setbits8(&bcsr[13], BCSR13_nUSBVCC);
		qe_usb_clock_set(QE_CLK21, 48000000);
	} else {
		setbits8(&bcsr[13], BCSR13_USBMODE);
		/*
                                                 
                                                     
                       
   */
		simple_gpiochip_init("fsl,mpc8360mds-bcsr-gpio");
	}

	of_node_put(np);
err:
	iounmap(bcsr);
	return ret;
}
コード例 #2
0
static int __init mpc836x_usb_cfg(void)
{
	u8 __iomem *bcsr;
	struct device_node *np;
	const char *mode;
	int ret = 0;

	np = of_find_compatible_node(NULL, NULL, "fsl,mpc8360mds-bcsr");
	if (!np)
		return -ENODEV;

	bcsr = of_iomap(np, 0);
	of_node_put(np);
	if (!bcsr)
		return -ENOMEM;

	np = of_find_compatible_node(NULL, NULL, "fsl,mpc8323-qe-usb");
	if (!np) {
		ret = -ENODEV;
		goto err;
	}

#define BCSR8_TSEC1M_MASK	(0x3 << 6)
#define BCSR8_TSEC1M_RGMII	(0x0 << 6)
#define BCSR8_TSEC2M_MASK	(0x3 << 4)
#define BCSR8_TSEC2M_RGMII	(0x0 << 4)
	/*
	 * Default is GMII (2), but we should set it to RGMII (0) if we use
	 * USB (Eth PHY is in RGMII mode anyway).
	 */
	clrsetbits_8(&bcsr[8], BCSR8_TSEC1M_MASK | BCSR8_TSEC2M_MASK,
			       BCSR8_TSEC1M_RGMII | BCSR8_TSEC2M_RGMII);

#define BCSR13_USBMASK	0x0f
#define BCSR13_nUSBEN	0x08 /* 1 - Disable, 0 - Enable			*/
#define BCSR13_USBSPEED	0x04 /* 1 - Full, 0 - Low			*/
#define BCSR13_USBMODE	0x02 /* 1 - Host, 0 - Function			*/
#define BCSR13_nUSBVCC	0x01 /* 1 - gets VBUS, 0 - supplies VBUS 	*/

	clrsetbits_8(&bcsr[13], BCSR13_USBMASK, BCSR13_USBSPEED);

	mode = of_get_property(np, "mode", NULL);
	if (mode && !strcmp(mode, "peripheral")) {
		setbits8(&bcsr[13], BCSR13_nUSBVCC);
		qe_usb_clock_set(QE_CLK21, 48000000);
	} else {
		setbits8(&bcsr[13], BCSR13_USBMODE);
		/*
		 * The BCSR GPIOs are used to control power and
		 * speed of the USB transceiver. This is needed for
		 * the USB Host only.
		 */
		simple_gpiochip_init("fsl,mpc8360mds-bcsr-gpio");
	}

	of_node_put(np);
err:
	iounmap(bcsr);
	return ret;
}
コード例 #3
0
ファイル: cpu_init.c プロジェクト: Jheengut/u-boot
int fecpin_setclear(struct eth_device *dev, int setclear)
{
    gpio_t *gpio = (gpio_t *) MMAP_GPIO;
    struct fec_info_s *info = (struct fec_info_s *)dev->priv;

#ifdef CONFIG_MCF5445x
    if (setclear) {
#ifdef CONFIG_SYS_FEC_NO_SHARED_PHY
        if (info->iobase == CONFIG_SYS_FEC0_IOBASE)
            setbits_be16(&gpio->par_feci2c,
                         GPIO_PAR_FECI2C_MDC0_MDC0 |
                         GPIO_PAR_FECI2C_MDIO0_MDIO0);
        else
            setbits_be16(&gpio->par_feci2c,
                         GPIO_PAR_FECI2C_MDC1_MDC1 |
                         GPIO_PAR_FECI2C_MDIO1_MDIO1);
#else
        setbits_be16(&gpio->par_feci2c,
                     GPIO_PAR_FECI2C_MDC0_MDC0 | GPIO_PAR_FECI2C_MDIO0_MDIO0);
#endif

        if (info->iobase == CONFIG_SYS_FEC0_IOBASE)
            setbits_8(&gpio->par_fec, GPIO_PAR_FEC_FEC0_RMII_GPIO);
        else
            setbits_8(&gpio->par_fec, GPIO_PAR_FEC_FEC1_RMII_ATA);
    } else {
        clrbits_be16(&gpio->par_feci2c,
                     GPIO_PAR_FECI2C_MDC0_MDC0 | GPIO_PAR_FECI2C_MDIO0_MDIO0);

        if (info->iobase == CONFIG_SYS_FEC0_IOBASE) {
#ifdef CONFIG_SYS_FEC_FULL_MII
            setbits_8(&gpio->par_fec, GPIO_PAR_FEC_FEC0_MII);
#else
            clrbits_8(&gpio->par_fec, ~GPIO_PAR_FEC_FEC0_UNMASK);
#endif
        } else {
#ifdef CONFIG_SYS_FEC_FULL_MII
            setbits_8(&gpio->par_fec, GPIO_PAR_FEC_FEC1_MII);
#else
            clrbits_8(&gpio->par_fec, ~GPIO_PAR_FEC_FEC1_UNMASK);
#endif
        }
    }
#endif	/* CONFIG_MCF5445x */

#ifdef CONFIG_MCF5441x
    if (setclear) {
        out_8(&gpio->par_fec, 0x03);
        out_8(&gpio->srcr_fec, 0x0F);
        clrsetbits_8(&gpio->par_simp0h, ~GPIO_PAR_SIMP0H_DAT_MASK,
                     GPIO_PAR_SIMP0H_DAT_GPIO);
        clrsetbits_8(&gpio->pddr_g, ~GPIO_PDDR_G4_MASK,
                     GPIO_PDDR_G4_OUTPUT);
        clrbits_8(&gpio->podr_g, ~GPIO_PODR_G4_MASK);

    } else
        clrbits_8(&gpio->par_fec, ~GPIO_PAR_FEC_FEC_MASK);
#endif
    return 0;
}
コード例 #4
0
ファイル: max77686.c プロジェクト: AdriDlu/coreboot
/*
 * Enable the max77686 register
 *
 * @param reg		register number of buck/ldo to be enabled
 * @param enable	enable or disable bit
 *
 *			REG_DISABLE = 0,
			needed to set the buck/ldo enable bit OFF
 * @return		Return 0 if ok, else -1
 */
static int max77686_enablereg(unsigned int bus, enum max77686_regnum reg, int enable)
{
	struct max77686_para *pmic;
	unsigned char read_data;
	int ret;

	pmic = &max77686_param[reg];

	ret = max77686_i2c_read(bus, MAX77686_I2C_ADDR, pmic->reg_enaddr,
				&read_data);
	if (ret != 0) {
		printk(BIOS_DEBUG, "max77686 i2c read failed.\n");
		return -1;
	}

	if (enable == REG_DISABLE) {
		clrbits_8(&read_data,
				pmic->reg_enbitmask << pmic->reg_enbitpos);
	} else {
		clrsetbits_8(&read_data,
				pmic->reg_enbitmask << pmic->reg_enbitpos,
				pmic->reg_enbiton << pmic->reg_enbitpos);
	}

	ret = max77686_i2c_write(bus, MAX77686_I2C_ADDR,
				 pmic->reg_enaddr, read_data);
	if (ret != 0) {
		printk(BIOS_DEBUG, "max77686 i2c write failed.\n");
		return -1;
	}

	return 0;
}
コード例 #5
0
static int set_px_corepll(unsigned long corepll)
{
	u8 val;

	switch (corepll) {
	case 20:
		val = 0x08;
		break;
	case 25:
		val = 0x0C;
		break;
	case 30:
		val = 0x10;
		break;
	case 35:
		val = 0x1C;
		break;
	case 40:
		val = 0x14;
		break;
	case 45:
		val = 0x0E;
		break;
	default:
		printf("Unsupported COREPLL ratio.\n");
		return 0;
	}

	clrsetbits_8(pixis_base + PIXIS_VSPEED0, 0x1F, val);
	return 1;
}
コード例 #6
0
ファイル: s5m8767.c プロジェクト: yytang2012/u-boot-arm
/*
 * Enable the s5m8767 register
 *
 * @param reg		register number of buck/ldo to be enabled
 * @param enable	enable or disable bit
 *
 *			S5M8767_REG_DISABLE = 0,
			needed to set the buck/ldo enable bit OFF
 * @return		Return 0 if ok, else -1
 */
static int s5m8767_enablereg(enum s5m8767_regnum reg, int enable)
{
	struct s5m8767_para *pmic;
	unsigned char read_data;
	int ret;

	pmic = &s5m8767_param[reg];

	ret = s5m8767_i2c_read(S5M8767_I2C_ADDR, pmic->reg_enaddr,
				&read_data);
	if (ret != 0) {
		debug("s5m8767 i2c read failed.\n");
		return -1;
	}

	if (enable == S5M8767_REG_DISABLE) {
		clrbits_8(&read_data,
				pmic->reg_enbitmask << pmic->reg_enbitpos);
	} else {
		clrsetbits_8(&read_data,
				pmic->reg_enbitmask << pmic->reg_enbitpos,
				pmic->reg_enbiton << pmic->reg_enbitpos);
	}

	ret = s5m8767_i2c_write(S5M8767_I2C_ADDR,
				 pmic->reg_enaddr, read_data);
	if (ret != 0) {
		debug("s5m8767 i2c write failed.\n");
		return -1;
	}

	return 0;
}
コード例 #7
0
ファイル: ucc.c プロジェクト: Blackburn29/PsycoKernel
int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
{
	u8 __iomem *guemr;

	switch (ucc_num) {
	case 0: guemr = &qe_immr->ucc1.slow.guemr;
		break;
	case 1: guemr = &qe_immr->ucc2.slow.guemr;
		break;
	case 2: guemr = &qe_immr->ucc3.slow.guemr;
		break;
	case 3: guemr = &qe_immr->ucc4.slow.guemr;
		break;
	case 4: guemr = &qe_immr->ucc5.slow.guemr;
		break;
	case 5: guemr = &qe_immr->ucc6.slow.guemr;
		break;
	case 6: guemr = &qe_immr->ucc7.slow.guemr;
		break;
	case 7: guemr = &qe_immr->ucc8.slow.guemr;
		break;
	default:
		return -EINVAL;
	}

	clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
		UCC_GUEMR_SET_RESERVED3 | speed);

	return 0;
}
コード例 #8
0
ファイル: ucc.c プロジェクト: E-LLP/n900
/* Configure the UCC to either Slow or Fast.
 *
 * A given UCC can be figured to support either "slow" devices (e.g. UART)
 * or "fast" devices (e.g. Ethernet).
 *
 * 'ucc_num' is the UCC number, from 0 - 7.
 *
 * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
 * must always be set to 1.
 */
int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
{
	u8 __iomem *guemr;

	/* The GUEMR register is at the same location for both slow and fast
	   devices, so we just use uccX.slow.guemr. */
	switch (ucc_num) {
	case 0: guemr = &qe_immr->ucc1.slow.guemr;
		break;
	case 1: guemr = &qe_immr->ucc2.slow.guemr;
		break;
	case 2: guemr = &qe_immr->ucc3.slow.guemr;
		break;
	case 3: guemr = &qe_immr->ucc4.slow.guemr;
		break;
	case 4: guemr = &qe_immr->ucc5.slow.guemr;
		break;
	case 5: guemr = &qe_immr->ucc6.slow.guemr;
		break;
	case 6: guemr = &qe_immr->ucc7.slow.guemr;
		break;
	case 7: guemr = &qe_immr->ucc8.slow.guemr;
		break;
	default:
		return -EINVAL;
	}

	clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
		UCC_GUEMR_SET_RESERVED3 | speed);

	return 0;
}
コード例 #9
0
static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt,
				  int enable, int volt_units)
{
	struct max77686_para *pmic;
	unsigned char read_data;
	int vol_level = 0;
	int ret;

	pmic = &max77686_param[reg];

	if (pmic->vol_addr == 0) {
		debug("not a voltage register.\n");
		return -1;
	}

	ret = max77686_i2c_read(MAX77686_I2C_ADDR, pmic->vol_addr, &read_data);
	if (ret != 0) {
		debug("max77686 i2c read failed.\n");
		return -1;
	}

	if (volt_units == MAX77686_UV)
		vol_level = volt - pmic->vol_min * 1000;
	else
		vol_level = (volt - pmic->vol_min) * 1000;

	if (vol_level < 0) {
		debug("Not a valid voltage level to set\n");
		return -1;
	}
	vol_level /= pmic->vol_div;

	clrsetbits_8(&read_data, pmic->vol_bitmask << pmic->vol_bitpos,
			vol_level << pmic->vol_bitpos);

	ret = max77686_i2c_write(MAX77686_I2C_ADDR, pmic->vol_addr, read_data);
	if (ret != 0) {
		debug("max77686 i2c write failed.\n");
		return -1;
	}

	ret = max77686_enablereg(reg, enable);
	if (ret != 0) {
		debug("Failed to enable buck/ldo.\n");
		return -1;
	}

	return 0;
}
コード例 #10
0
ファイル: lpc.c プロジェクト: 96boards-bubblegum/u-boot
static void set_spi_speed(void)
{
	u32 fdod;

	/* Observe SPI Descriptor Component Section 0 */
	writel(0x1000, RCB_REG(SPI_DESC_COMP0));

	/* Extract the1 Write/Erase SPI Frequency from descriptor */
	fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
	fdod >>= 24;
	fdod &= 7;

	/* Set Software Sequence frequency to match */
	clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
}
コード例 #11
0
static void northbridge_init(struct udevice *dev, int rev)
{
	u32 bridge_type;

	add_fixed_resources(dev, 6);
	northbridge_dmi_init(dev, rev);

	bridge_type = readl(MCHBAR_REG(0x5f10));
	bridge_type &= ~0xff;

	if ((rev & BASE_REV_MASK) == BASE_REV_IVB) {
		/* Enable Power Aware Interrupt Routing - fixed priority */
		clrsetbits_8(MCHBAR_REG(0x5418), 0xf, 0x4);

		/* 30h for IvyBridge */
		bridge_type |= 0x30;
	} else {
		/* 20h for Sandybridge */
		bridge_type |= 0x20;
	}
	writel(bridge_type, MCHBAR_REG(0x5f10));

	/*
	 * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU
	 * that BIOS has initialized memory and power management
	 */
	setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 1);
	debug("Set BIOS_RESET_CPL\n");

	/* Configure turbo power limits 1ms after reset complete bit */
	mdelay(1);
	set_power_limits(28);

	/*
	 * CPUs with configurable TDP also need power limits set
	 * in MCHBAR.  Use same values from MSR_PKG_POWER_LIMIT.
	 */
	if (cpu_config_tdp_levels()) {
		msr_t msr = msr_read(MSR_PKG_POWER_LIMIT);

		writel(msr.lo, MCHBAR_REG(0x59A0));
		writel(msr.hi, MCHBAR_REG(0x59A4));
	}

	/* Set here before graphics PM init */
	writel(0x00100001, MCHBAR_REG(0x5500));
}
コード例 #12
0
/* Set the CFG_SYSPLL bits
 *
 * This only has effect if PX_VCFGEN0[SYSPLL]=1, which is true if
 * read_from_px_regs() is called.
 */
static int set_px_mpxpll(unsigned long mpxpll)
{
	switch (mpxpll) {
	case 2:
	case 4:
	case 6:
	case 8:
	case 10:
	case 12:
	case 14:
	case 16:
		clrsetbits_8(pixis_base + PIXIS_VSPEED1, 0x1F, mpxpll);
		return 1;
	}

	printf("Unsupported MPXPLL ratio.\n");
	return 0;
}
コード例 #13
0
ファイル: uuid.c プロジェクト: Noltari/u-boot
void gen_rand_uuid(unsigned char *uuid_bin)
{
	struct uuid uuid;
	unsigned int *ptr = (unsigned int *)&uuid;
	int i;

	/* Set all fields randomly */
	for (i = 0; i < sizeof(struct uuid) / sizeof(*ptr); i++)
		*(ptr + i) = cpu_to_be32(rand());

	clrsetbits_be16(&uuid.time_hi_and_version,
			UUID_VERSION_MASK,
			UUID_VERSION << UUID_VERSION_SHIFT);

	clrsetbits_8(&uuid.clock_seq_hi_and_reserved,
		     UUID_VARIANT_MASK,
		     UUID_VARIANT << UUID_VARIANT_SHIFT);

	memcpy(uuid_bin, &uuid, sizeof(struct uuid));
}
コード例 #14
0
ファイル: spl.c プロジェクト: 0s4l/u-boot-xlnx
void board_init_f(ulong bootflag)
{
	int px_spd;
	u32 plat_ratio, sys_clk, bus_clk;
	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;

	console_init_f();

	/* Set pmuxcr to allow both i2c1 and i2c2 */
	setbits_be32(&gur->pmuxcr, in_be32(&gur->pmuxcr) | 0x1000);
	setbits_be32(&gur->pmuxcr,
		     in_be32(&gur->pmuxcr) | MPC85xx_PMUXCR_SD_DATA);

#ifdef CONFIG_SPL_SPI_BOOT
	/* Enable the SPI */
	clrsetbits_8(&pixis->brdcfg0, PIXIS_ELBC_SPI_MASK, PIXIS_SPI);
#endif

	/* Read back the register to synchronize the write. */
	in_be32(&gur->pmuxcr);

	/* initialize selected port with appropriate baud rate */
	px_spd = in_8((unsigned char *)(PIXIS_BASE + PIXIS_SPD));
	sys_clk = sysclk_tbl[px_spd & PIXIS_SPD_SYSCLK_MASK];
	plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
	bus_clk = sys_clk * plat_ratio / 2;

	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
		     bus_clk / 16 / CONFIG_BAUDRATE);
#ifdef CONFIG_SPL_MMC_BOOT
	puts("\nSD boot...\n");
#elif defined(CONFIG_SPL_SPI_BOOT)
	puts("\nSPI Flash boot...\n");
#endif

	/* copy code to RAM and jump to it - this should not return */
	/* NOTE - code has to be copied out of NAND buffer before
	 * other blocks can be read.
	 */
	relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
}
コード例 #15
0
ファイル: eth_superhydra.c プロジェクト: 01hyang/u-boot
/*
 * Set the board muxing for a given MAC
 *
 * The MDIO layer calls this function every time it wants to talk to a PHY.
 */
void super_hydra_mux_mdio(u8 mask, u8 val)
{
	clrsetbits_8(&pixis->brdcfg1, mask, val);
}
コード例 #16
0
static void __init mpc85xx_mds_reset_ucc_phys(void)
{
	struct device_node *np;
	static u8 __iomem *bcsr_regs;

	/* Map BCSR area */
	np = of_find_node_by_name(NULL, "bcsr");
	if (!np)
		return;

	bcsr_regs = of_iomap(np, 0);
	of_node_put(np);
	if (!bcsr_regs)
		return;

	if (machine_is(mpc8568_mds)) {
#define BCSR_UCC1_GETH_EN	(0x1 << 7)
#define BCSR_UCC2_GETH_EN	(0x1 << 7)
#define BCSR_UCC1_MODE_MSK	(0x3 << 4)
#define BCSR_UCC2_MODE_MSK	(0x3 << 0)

		/* Turn off UCC1 & UCC2 */
		clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
		clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);

		/* Mode is RGMII, all bits clear */
		clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
					 BCSR_UCC2_MODE_MSK);

		/* Turn UCC1 & UCC2 on */
		setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
		setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
	} else if (machine_is(mpc8569_mds)) {
#define BCSR7_UCC12_GETHnRST	(0x1 << 2)
#define BCSR8_UEM_MARVELL_RST	(0x1 << 1)
#define BCSR_UCC_RGMII		(0x1 << 6)
#define BCSR_UCC_RTBI		(0x1 << 5)
		/*
		 * U-Boot mangles interrupt polarity for Marvell PHYs,
		 * so reset built-in and UEM Marvell PHYs, this puts
		 * the PHYs into their normal state.
		 */
		clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
		setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);

		setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
		clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);

		for (np = NULL; (np = of_find_compatible_node(np,
						"network",
						"ucc_geth")) != NULL;) {
			const unsigned int *prop;
			int ucc_num;

			prop = of_get_property(np, "cell-index", NULL);
			if (prop == NULL)
				continue;

			ucc_num = *prop - 1;

			prop = of_get_property(np, "phy-connection-type", NULL);
			if (prop == NULL)
				continue;

			if (strcmp("rtbi", (const char *)prop) == 0)
				clrsetbits_8(&bcsr_regs[7 + ucc_num],
					BCSR_UCC_RGMII, BCSR_UCC_RTBI);
		}
	} else if (machine_is(p1021_mds)) {
#define BCSR11_ENET_MICRST     (0x1 << 5)
		/* Reset Micrel PHY */
		clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
		setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
	}

	iounmap(bcsr_regs);
}
コード例 #17
0
int board_eth_init(bd_t *bis)
{
#ifdef CONFIG_FMAN_ENET
	struct fsl_pq_mdio_info dtsec_mdio_info;
	struct tgec_mdio_info tgec_mdio_info;
	unsigned int i, slot;
	int lane;
	struct mii_dev *bus;

	printf("Initializing Fman\n");

	initialize_lane_to_slot();

	/* We want to use the PIXIS to configure MUX routing, not GPIOs. */
	setbits_8(&pixis->brdcfg2, BRDCFG2_REG_GPIO_SEL);

	memset(mdio_mux, 0, sizeof(mdio_mux));

	dtsec_mdio_info.regs =
		(struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
	dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;

	/* Register the real 1G MDIO bus */
	fsl_pq_mdio_init(bis, &dtsec_mdio_info);

	tgec_mdio_info.regs =
		(struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
	tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;

	/* Register the real 10G MDIO bus */
	fm_tgec_mdio_init(bis, &tgec_mdio_info);

	/* Register the three virtual MDIO front-ends */
	hydra_mdio_init(DEFAULT_FM_MDIO_NAME, "HYDRA_RGMII_MDIO");
	hydra_mdio_init(DEFAULT_FM_MDIO_NAME, "HYDRA_SGMII_MDIO");

	/*
	 * Program the DTSEC PHY addresses assuming that they are all SGMII.
	 * For any DTSEC that's RGMII, we'll override its PHY address later.
	 * We assume that DTSEC5 is only used for RGMII.
	 */
	fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
	fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
	fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR);
	fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);

	for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
		int idx = i - FM1_DTSEC1;

		switch (fm_info_get_enet_if(i)) {
		case PHY_INTERFACE_MODE_SGMII:
			lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
			if (lane < 0)
				break;
			slot = lane_to_slot[lane];
			mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
			switch (slot) {
			case 1:
				/* Always DTSEC5 on Bank 3 */
				mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT1 |
						  BRDCFG1_EMI1_EN;
				break;
			case 2:
				mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT2 |
						  BRDCFG1_EMI1_EN;
				break;
			case 5:
				mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT5 |
						  BRDCFG1_EMI1_EN;
				break;
			case 6:
				mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT6 |
						  BRDCFG1_EMI1_EN;
				break;
			case 7:
				mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT7 |
						  BRDCFG1_EMI1_EN;
				break;
			};

			hydra_mdio_set_mux("HYDRA_SGMII_MDIO",
					mdio_mux[i].mask, mdio_mux[i].val);
			fm_info_set_mdio(i,
				miiphy_get_dev_by_name("HYDRA_SGMII_MDIO"));
			break;
		case PHY_INTERFACE_MODE_RGMII:
			/*
			 * If DTSEC4 is RGMII, then it's routed via via EC1 to
			 * the first on-board RGMII port.  If DTSEC5 is RGMII,
			 * then it's routed via via EC2 to the second on-board
			 * RGMII port. The other DTSECs cannot be routed to
			 * RGMII.
			 */
			fm_info_set_phy_address(i, i == FM1_DTSEC4 ? 0 : 1);
			mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
			mdio_mux[i].val  = BRDCFG1_EMI1_SEL_RGMII |
					   BRDCFG1_EMI1_EN;
			hydra_mdio_set_mux("HYDRA_RGMII_MDIO",
					mdio_mux[i].mask, mdio_mux[i].val);
			fm_info_set_mdio(i,
				miiphy_get_dev_by_name("HYDRA_RGMII_MDIO"));
			break;
		case PHY_INTERFACE_MODE_NONE:
			fm_info_set_phy_address(i, 0);
			break;
		default:
			printf("Fman1: DTSEC%u set to unknown interface %i\n",
			       idx + 1, fm_info_get_enet_if(i));
			fm_info_set_phy_address(i, 0);
			break;
		}
	}

	bus = miiphy_get_dev_by_name("HYDRA_SGMII_MDIO");
	set_sgmii_phy(bus, FM1_DTSEC1, CONFIG_SYS_NUM_FM1_DTSEC, PHY_BASE_ADDR);

	/*
	 * For 10G, we only support one XAUI card per Fman.  If present, then we
	 * force its routing and never touch those bits again, which removes the
	 * need for Linux to do any muxing.  This works because of the way
	 * BRDCFG1 is defined, but it's a bit hackish.
	 *
	 * The PHY address for the XAUI card depends on which slot it's in. The
	 * macros we use imply that the PHY address is based on which FM, but
	 * that's not true.  On the P4080DS, FM1 could only use XAUI in slot 5,
	 * and FM2 could only use a XAUI in slot 4.  On the Hydra board, we
	 * check the actual slot and just use the macros as-is, even though
	 * the P3041 and P5020 only have one Fman.
	 */
	lane = serdes_get_first_lane(XAUI_FM1);
	if (lane >= 0) {
		slot = lane_to_slot[lane];
		if (slot == 1) {
			/* XAUI card is in slot 1 */
			clrsetbits_8(&pixis->brdcfg1, BRDCFG1_EMI2_SEL_MASK,
				     BRDCFG1_EMI2_SEL_SLOT1);
			fm_info_set_phy_address(FM1_10GEC1,
						CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
		} else {
			/* XAUI card is in slot 2 */
			clrsetbits_8(&pixis->brdcfg1, BRDCFG1_EMI2_SEL_MASK,
				     BRDCFG1_EMI2_SEL_SLOT2);
			fm_info_set_phy_address(FM1_10GEC1,
						CONFIG_SYS_FM2_10GEC1_PHY_ADDR);
		}
	}

	fm_info_set_mdio(FM1_10GEC1,
			miiphy_get_dev_by_name(DEFAULT_FM_TGEC_MDIO_NAME));

	cpu_eth_init(bis);
#endif

	return pci_eth_init(bis);
}