X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=drivers%2Fqe%2Fuec.c;h=0b4a6e7c47c849bed90662c6e59bdc1aa1103c5e;hb=8e55258f144764de8902e9f078a7ad4c6c022c2f;hp=dc2765bb09e6c6e981433f5fd0f6a5c43cc8e450;hpb=fc9970137c8f187b5938e4926224e0f3d46c3476;p=karo-tx-uboot.git diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index dc2765bb09..0b4a6e7c47 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Freescale Semiconductor, Inc. + * Copyright (C) 2006-2009 Freescale Semiconductor, Inc. * * Dave Liu * @@ -29,45 +29,41 @@ #include "uccf.h" #include "uec.h" #include "uec_phy.h" +#include "miiphy.h" -#if defined(CONFIG_QE) - +static uec_info_t uec_info[] = { #ifdef CONFIG_UEC_ETH1 -static uec_info_t eth1_uec_info = { - .uf_info = { - .ucc_num = CFG_UEC1_UCC_NUM, - .rx_clock = CFG_UEC1_RX_CLK, - .tx_clock = CFG_UEC1_TX_CLK, - .eth_type = CFG_UEC1_ETH_TYPE, - }, - .num_threads_tx = UEC_NUM_OF_THREADS_4, - .num_threads_rx = UEC_NUM_OF_THREADS_4, - .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, - .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, - .tx_bd_ring_len = 16, - .rx_bd_ring_len = 16, - .phy_address = CFG_UEC1_PHY_ADDR, - .enet_interface = CFG_UEC1_INTERFACE_MODE, -}; + STD_UEC_INFO(1), /* UEC1 */ #endif #ifdef CONFIG_UEC_ETH2 -static uec_info_t eth2_uec_info = { - .uf_info = { - .ucc_num = CFG_UEC2_UCC_NUM, - .rx_clock = CFG_UEC2_RX_CLK, - .tx_clock = CFG_UEC2_TX_CLK, - .eth_type = CFG_UEC2_ETH_TYPE, - }, - .num_threads_tx = UEC_NUM_OF_THREADS_4, - .num_threads_rx = UEC_NUM_OF_THREADS_4, - .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, - .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, - .tx_bd_ring_len = 16, - .rx_bd_ring_len = 16, - .phy_address = CFG_UEC2_PHY_ADDR, - .enet_interface = CFG_UEC2_INTERFACE_MODE, -}; + STD_UEC_INFO(2), /* UEC2 */ +#endif +#ifdef CONFIG_UEC_ETH3 + STD_UEC_INFO(3), /* UEC3 */ +#endif +#ifdef CONFIG_UEC_ETH4 + STD_UEC_INFO(4), /* UEC4 */ +#endif +#ifdef CONFIG_UEC_ETH5 + STD_UEC_INFO(5), /* UEC5 */ #endif +#ifdef CONFIG_UEC_ETH6 + STD_UEC_INFO(6), /* UEC6 */ +#endif +#ifdef CONFIG_UEC_ETH7 + STD_UEC_INFO(7), /* UEC7 */ +#endif +#ifdef CONFIG_UEC_ETH8 + STD_UEC_INFO(8), /* UEC8 */ +#endif +}; + +#define MAXCONTROLLERS (8) + +static struct eth_device *devlist[MAXCONTROLLERS]; + +u16 phy_read (struct uec_mii_info *mii_info, u16 regnum); +void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val); static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode) { @@ -325,7 +321,7 @@ static int uec_set_mac_duplex(uec_private_t *uec, int duplex) static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode) { enet_interface_e enet_if_mode; - uec_info_t *uec_info; + uec_info_t *uec_info; uec_t *uec_regs; u32 upsmr; u32 maccfg2; @@ -361,6 +357,8 @@ static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode) maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; upsmr |= (UPSMR_RPM | UPSMR_TBIM); break; + case ENET_1000_RGMII_RXID: + case ENET_1000_RGMII_ID: case ENET_1000_RGMII: maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; upsmr |= UPSMR_RPM; @@ -456,6 +454,8 @@ static int init_phy(struct eth_device *dev) uec->mii_info = mii_info; + qe_set_mii_clk_src(uec->uec_info->uf_info.ucc_num); + if (init_mii_management_configuration(umii_regs)) { printf("%s: The MII Bus is stuck!", dev->name); err = -1; @@ -562,22 +562,86 @@ static void adjust_link(struct eth_device *dev) static void phy_change(struct eth_device *dev) { uec_private_t *uec = (uec_private_t *)dev->priv; - uec_t *uec_regs; - int result = 0; - - uec_regs = uec->uec_regs; - - /* Delay 5s to give the PHY a chance to change the register state */ - udelay(5000000); /* Update the link, speed, duplex */ - result = uec->mii_info->phyinfo->read_status(uec->mii_info); + uec->mii_info->phyinfo->read_status(uec->mii_info); /* Adjust the interface according to speed */ - if ((0 == result) || (uec->mii_info->link == 0)) { - adjust_link(dev); + adjust_link(dev); +} + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ + && !defined(BITBANGMII) + +/* + * Find a device index from the devlist by name + * + * Returns: + * The index where the device is located, -1 on error + */ +static int uec_miiphy_find_dev_by_name(char *devname) +{ + int i; + + for (i = 0; i < MAXCONTROLLERS; i++) { + if (strncmp(devname, devlist[i]->name, strlen(devname)) == 0) { + break; + } + } + + /* If device cannot be found, returns -1 */ + if (i == MAXCONTROLLERS) { + debug ("%s: device %s not found in devlist\n", __FUNCTION__, devname); + i = -1; + } + + return i; +} + +/* + * Read a MII PHY register. + * + * Returns: + * 0 on success + */ +static int uec_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + int devindex = 0; + + if (devname == NULL || value == NULL) { + debug("%s: NULL pointer given\n", __FUNCTION__); + } else { + devindex = uec_miiphy_find_dev_by_name(devname); + if (devindex >= 0) { + *value = uec_read_phy_reg(devlist[devindex], addr, reg); + } + } + return 0; +} + +/* + * Write a MII PHY register. + * + * Returns: + * 0 on success + */ +static int uec_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + int devindex = 0; + + if (devname == NULL) { + debug("%s: NULL pointer given\n", __FUNCTION__); + } else { + devindex = uec_miiphy_find_dev_by_name(devname); + if (devindex >= 0) { + uec_write_phy_reg(devlist[devindex], addr, reg, value); + } } + return 0; } +#endif static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr) { @@ -844,7 +908,7 @@ static int uec_issue_init_enet_rxtx_cmd(uec_private_t *uec, /* Init Rx global parameter pointer */ p_init_enet_param->rgftgfrxglobal |= uec->rx_glbl_pram_offset | - (u32)uec_info->riscRx; + (u32)uec_info->risc_rx; /* Init Rx threads */ for (i = 0; i < (thread_rx + 1); i++) { @@ -862,13 +926,13 @@ static int uec_issue_init_enet_rxtx_cmd(uec_private_t *uec, } entry_val = ((u32)snum << ENET_INIT_PARAM_SNUM_SHIFT) | - init_enet_offset | (u32)uec_info->riscRx; + init_enet_offset | (u32)uec_info->risc_rx; p_init_enet_param->rxthread[i] = entry_val; } /* Init Tx global parameter pointer */ p_init_enet_param->txglobal = uec->tx_glbl_pram_offset | - (u32)uec_info->riscTx; + (u32)uec_info->risc_tx; /* Init Tx threads */ for (i = 0; i < thread_tx; i++) { @@ -881,7 +945,7 @@ static int uec_issue_init_enet_rxtx_cmd(uec_private_t *uec, UEC_THREAD_TX_PRAM_ALIGNMENT); entry_val = ((u32)snum << ENET_INIT_PARAM_SNUM_SHIFT) | - init_enet_offset | (u32)uec_info->riscTx; + init_enet_offset | (u32)uec_info->risc_tx; p_init_enet_param->txthread[i] = entry_val; } @@ -1101,28 +1165,60 @@ static int uec_startup(uec_private_t *uec) static int uec_init(struct eth_device* dev, bd_t *bd) { uec_private_t *uec; - int err; + int err, i; + struct phy_info *curphy; uec = (uec_private_t *)dev->priv; if (uec->the_first_run == 0) { - /* Set up the MAC address */ - if (dev->enetaddr[0] & 0x01) { - printf("%s: MacAddress is multcast address\n", - __FUNCTION__); - return 0; + err = init_phy(dev); + if (err) { + printf("%s: Cannot initialize PHY, aborting.\n", + dev->name); + return err; + } + + curphy = uec->mii_info->phyinfo; + + if (curphy->config_aneg) { + err = curphy->config_aneg(uec->mii_info); + if (err) { + printf("%s: Can't negotiate PHY\n", dev->name); + return err; + } } - uec_set_mac_address(uec, dev->enetaddr); + + /* Give PHYs up to 5 sec to report a link */ + i = 50; + do { + err = curphy->read_status(uec->mii_info); + udelay(100000); + } while (((i-- > 0) && !uec->mii_info->link) || err); + + if (err || i <= 0) + printf("warning: %s: timeout on PHY link\n", dev->name); + uec->the_first_run = 1; } + /* Set up the MAC address */ + if (dev->enetaddr[0] & 0x01) { + printf("%s: MacAddress is multcast address\n", + __FUNCTION__); + return -1; + } + uec_set_mac_address(uec, dev->enetaddr); + + err = uec_open(uec, COMM_DIR_RX_AND_TX); if (err) { printf("%s: cannot enable UEC device\n", dev->name); - return 0; + return -1; } - return uec->mii_info->link; + phy_change(dev); + + return (uec->mii_info->link ? 0 : -1); } static void uec_halt(struct eth_device* dev) @@ -1209,12 +1305,11 @@ static int uec_recv(struct eth_device* dev) return 1; } -int uec_initialize(int index) +int uec_initialize(bd_t *bis, uec_info_t *uec_info) { struct eth_device *dev; int i; uec_private_t *uec; - uec_info_t *uec_info; int err; dev = (struct eth_device *)malloc(sizeof(struct eth_device)); @@ -1229,23 +1324,17 @@ int uec_initialize(int index) } memset(uec, 0, sizeof(uec_private_t)); - /* Init UEC private struct, they come from board.h */ - if (index == 0) { -#ifdef CONFIG_UEC_ETH1 - uec_info = ð1_uec_info; -#endif - } else if (index == 1) { -#ifdef CONFIG_UEC_ETH2 - uec_info = ð2_uec_info; + /* Adjust uec_info */ +#if (MAX_QE_RISC == 4) + uec_info->risc_tx = QE_RISC_ALLOCATION_FOUR_RISCS; + uec_info->risc_rx = QE_RISC_ALLOCATION_FOUR_RISCS; #endif - } else { - printf("%s: index is illegal.\n", __FUNCTION__); - return -EINVAL; - } + + devlist[uec_info->uf_info.ucc_num] = dev; uec->uec_info = uec_info; - sprintf(dev->name, "FSL UEC%d", index); + sprintf(dev->name, "FSL UEC%d", uec_info->uf_info.ucc_num); dev->iobase = 0; dev->priv = (void *)uec; dev->init = uec_init; @@ -1265,14 +1354,27 @@ int uec_initialize(int index) return err; } - err = init_phy(dev); - if (err) { - printf("%s: Cannot initialize PHY, aborting.\n", dev->name); - return err; - } - - phy_change(dev); +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ + && !defined(BITBANGMII) + miiphy_register(dev->name, uec_miiphy_read, uec_miiphy_write); +#endif return 1; } -#endif /* CONFIG_QE */ + +int uec_eth_init(bd_t *bis, uec_info_t *uecs, int num) +{ + int i; + + for (i = 0; i < num; i++) + uec_initialize(bis, &uecs[i]); + + return 0; +} + +int uec_standard_init(bd_t *bis) +{ + return uec_eth_init(bis, uec_info, ARRAY_SIZE(uec_info)); +} + +