Newer
Older
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
/* Check if the PHY device address was found */
if (phyaddr > 31)
{
/* Failed to find PHY at any location */
return -ENODEV;
}
/* Save the discovered PHY device address */
priv->lp_phyaddr = phyaddr;
/* Reset the PHY */
ret = lpc17_phyreset(phyaddr);
if (ret < 0)
{
return ret;
}
lpc17_showmii(phyaddr, "After reset");
/* Check for preamble suppression support */
phyreg = lpc17_phyread(phyaddr, MII_MSR);
if ((phyreg & MII_MSR_MFRAMESUPPRESS) != 0)
{
/* The PHY supports preamble suppression */
regval = lpc17_getreg(LPC17_ETH_MCFG);
regval |= ETH_MCFG_SUPPRE;
lpc17_putreg(regval, LPC17_ETH_MCFG);
}
/* Are we configured to do auto-negotiation? */
#ifdef CONFIG_PHY_AUTONEG
/* Setup the Auto-negotiation advertisement: 100 or 10, and HD or FD */
lpc17_phywrite(phyaddr, MII_ADVERTISE,
(MII_ADVERTISE_100BASETXFULL | MII_ADVERTISE_100BASETXHALF |
MII_ADVERTISE_10BASETXFULL | MII_ADVERTISE_10BASETXHALF |
MII_ADVERTISE_CSMA));
ret = lpc17_phyautoneg(phyaddr);
if (ret < 0)
{
return ret;
}
#else
/* Set up the fixed PHY configuration */
ret = lpc17_phymode(phyaddr, LPC17_MODE_DEFLT);
if (ret < 0)
{
return ret;
}
#endif
/* The link is established */
lpc17_showmii(phyaddr, "After link established");
/* Check configuration */
#ifdef CONFIG_PHY_KS8721
phyreg = lpc17_phyread(phyaddr, MII_KS8721_10BTCR);
switch (phyreg & KS8721_10BTCR_MODE_MASK)
{
case KS8721_10BTCR_MODE_10BTHD: /* 10BASE-T half duplex */
lpc17_putreg(0, LPC17_ETH_SUPP);
break;
case KS8721_10BTCR_MODE_100BTHD: /* 100BASE-T half duplex */
break;
case KS8721_10BTCR_MODE_10BTFD: /* 10BASE-T full duplex */
lpc17_putreg(0, LPC17_ETH_SUPP);
break;
case KS8721_10BTCR_MODE_100BTFD: /* 100BASE-T full duplex */
#else
# warning "PHY Unknown: speed and duplex are bogus"
(priv->lp_mode & LPC17_SPEED_MASK) == LPC17_SPEED_100 ? 100 : 10,
(priv->lp_mode & LPC17_DUPLEX_MASK) == LPC17_DUPLEX_FULL ?"full" : "half");
/* Disable auto-configuration. Set the fixed speed/duplex mode.
* (probably more than little redundant).
*/
ret = lpc17_phymode(phyaddr, LPC17_MODE_DEFLT);
lpc17_showmii(phyaddr, "After final configuration");
return ret;
}
#else
static inline int lpc17_phyinit(struct lpc17_driver_s *priv)
{
priv->lp_mode = LPC17_MODE_DEFLT;
return OK;
}
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
/****************************************************************************
* Function: lpc17_txdescinit
*
* Description:
* Initialize the EMAC Tx descriptor table
*
* Parameters:
* priv - Pointer to EMAC device driver structure
*
* Returned Value:
* None directory.
* As a side-effect, it will initialize priv->lp_phyaddr and
* priv->lp_phymode.
*
* Assumptions:
*
****************************************************************************/
static inline void lpc17_txdescinit(struct lpc17_driver_s *priv)
{
uint32_t *txdesc;
uint32_t *txstat;
uint32_t pktaddr;
int i;
/* Configure Tx descriptor and status tables */
lpc17_putreg(LPC17_TXDESC_BASE, LPC17_ETH_TXDESC);
lpc17_putreg(LPC17_TXSTAT_BASE, LPC17_ETH_TXSTAT);
lpc17_putreg(CONFIG_NET_NTXDESC-1, LPC17_ETH_TXDESCRNO);
/* Initialize Tx descriptors and link to packet buffers */
txdesc = (uint32_t*)LPC17_TXDESC_BASE;
pktaddr = LPC17_TXBUFFER_BASE;
for (i = 0; i < CONFIG_NET_NTXDESC; i++)
{
*txdesc++ = pktaddr;
*txdesc++ = (TXDESC_CONTROL_INT | (LPC17_MAXPACKET_SIZE - 1));
}
/* Initialize Tx status */
txstat = (uint32_t*)LPC17_TXSTAT_BASE;
for (i = 0; i < CONFIG_NET_NTXDESC; i++)
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
{
*txstat++ = 0;
}
/* Point to first Tx descriptor */
lpc17_putreg(0, LPC17_ETH_TXPRODIDX);
}
/****************************************************************************
* Function: lpc17_rxdescinit
*
* Description:
* Initialize the EMAC Rx descriptor table
*
* Parameters:
* priv - Pointer to EMAC device driver structure
*
* Returned Value:
* None directory.
* As a side-effect, it will initialize priv->lp_phyaddr and
* priv->lp_phymode.
*
* Assumptions:
*
****************************************************************************/
static inline void lpc17_rxdescinit(struct lpc17_driver_s *priv)
{
uint32_t *rxdesc;
uint32_t *rxstat;
uint32_t pktaddr;
int i;
/* Configure Rx descriptor and status tables */
lpc17_putreg(LPC17_RXDESC_BASE, LPC17_ETH_RXDESC);
lpc17_putreg(LPC17_RXSTAT_BASE, LPC17_ETH_RXSTAT);
lpc17_putreg(CONFIG_NET_NRXDESC-1, LPC17_ETH_RXDESCNO);
/* Initialize Rx descriptors and link to packet buffers */
rxdesc = (uint32_t*)LPC17_RXDESC_BASE;
pktaddr = LPC17_RXBUFFER_BASE;
for (i = 0; i < CONFIG_NET_NRXDESC; i++)
{
*rxdesc++ = pktaddr;
*rxdesc++ = (RXDESC_CONTROL_INT | (LPC17_MAXPACKET_SIZE - 1));
pktaddr += LPC17_MAXPACKET_SIZE;
}
/* Initialize Rx status */
for (i = 0; i < CONFIG_NET_NRXDESC; i++)
{
*rxstat++ = 0;
*rxstat++ = 0;
}
/* Point to first Rx descriptor */
lpc17_putreg(0, LPC17_ETH_RXCONSIDX);
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
/****************************************************************************
* Function: lpc17_macmode
*
* Description:
* Set the MAC to operate at a selected speed/duplex mode.
*
* Parameters:
* mode - speed/duplex mode
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
#ifdef LPC17_HAVE_PHY
static void lpc17_macmode(uint8_t mode)
{
uint32_t regval;
/* Set up for full or half duplex operation */
if ((mode & LPC17_DUPLEX_MASK) == LPC17_DUPLEX_FULL)
{
/* Set the back-to-back inter-packet gap */
lpc17_putreg(21, LPC17_ETH_IPGT);
/* Set MAC to operate in full duplex mode with CRC and Pad enabled */
regval = lpc17_getreg(LPC17_ETH_MAC2);
regval |= (ETH_MAC2_FD | ETH_MAC2_CRCEN | ETH_MAC2_PADCRCEN);
lpc17_putreg(regval, LPC17_ETH_MAC2);
/* Select full duplex operation for ethernet controller */
regval = lpc17_getreg(LPC17_ETH_CMD);
regval |= (ETH_CMD_FD | ETH_CMD_RMII | ETH_CMD_PRFRAME);
lpc17_putreg(regval, LPC17_ETH_CMD);
}
else
{
/* Set the back-to-back inter-packet gap */
lpc17_putreg(18, LPC17_ETH_IPGT);
/* Set MAC to operate in half duplex mode with CRC and Pad enabled */
regval = lpc17_getreg(LPC17_ETH_MAC2);
regval &= ~ETH_MAC2_FD;
regval |= (ETH_MAC2_CRCEN | ETH_MAC2_PADCRCEN);
lpc17_putreg(regval, LPC17_ETH_MAC2);
/* Select half duplex operation for ethernet controller */
regval = lpc17_getreg(LPC17_ETH_CMD);
regval &= ~ETH_CMD_FD;
regval |= (ETH_CMD_RMII | ETH_CMD_PRFRAME);
lpc17_putreg(regval, LPC17_ETH_CMD);
}
/* This is currently done in lpc17_phyinit(). That doesn't
* seem like the right place. It should be done here.
*/
#if 0
regval = lpc17_getreg(LPC17_ETH_SUPP);
if ((mode & LPC17_SPEED_MASK) == LPC17_SPEED_100)
{
regval |= ETH_SUPP_SPEED;
}
else
{
regval &= ~ETH_SUPP_SPEED;
}
lpc17_putreg(regval, LPC17_ETH_SUPP);
#endif
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
}
#endif
/****************************************************************************
* Function: lpc17_ethreset
*
* Description:
* Configure and reset the Ethernet module, leaving it in a disabled state.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* OK on success; a negated errno on failure
*
* Assumptions:
*
****************************************************************************/
static void lpc17_ethreset(struct lpc17_driver_s *priv)
{
irqstate_t flags;
lpc17_putreg((ETH_MAC1_TXRST | ETH_MAC1_MCSTXRST | ETH_MAC1_RXRST |
ETH_MAC1_MCSRXRST | ETH_MAC1_SIMRST | ETH_MAC1_SOFTRST),
LPC17_ETH_MAC1);
/* Disable RX/RX, clear modes, reset all control registers */
lpc17_putreg((ETH_CMD_REGRST | ETH_CMD_TXRST | ETH_CMD_RXRST),
LPC17_ETH_CMD);
/* Take the MAC out of the reset state */
up_udelay(50);
lpc17_putreg(0, LPC17_ETH_MAC1);
/* The RMII bit must be set on initialization (I'm not sure this needs
* to be done here but... oh well).
*/
lpc17_putreg(ETH_CMD_RMII, LPC17_ETH_CMD);
/* Set other misc configuration-related registers to default values */
lpc17_putreg(0, LPC17_ETH_MAC2);
lpc17_putreg(0, LPC17_ETH_SUPP);
lpc17_putreg(0, LPC17_ETH_TEST);
lpc17_putreg(18, LPC17_ETH_IPGR);
lpc17_putreg(((15 << ETH_CLRT_RMAX_SHIFT) | (55 << ETH_CLRT_COLWIN_SHIFT)),
LPC17_ETH_CLRT);
lpc17_putreg(0x0600, LPC17_ETH_MAXF);
/* Disable all Ethernet controller interrupts */
/* Clear any pending interrupts (shouldn't be any) */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: lpc17_ethinitialize
* Initialize one Ethernet controller and driver structure.
* intf - Selects the interface to be initialized.
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/
int lpc17_ethinitialize(int intf)
#else
static inline int lpc17_ethinitialize(int intf)
#endif
/* Turn on the ethernet MAC clock */
regval = lpc17_getreg(LPC17_SYSCON_PCONP);
regval |= SYSCON_PCONP_PCENET;
lpc17_putreg(regval, LPC17_SYSCON_PCONP);
/* Configure all GPIO pins needed by ENET */
for (i = 0; i < GPIO_NENET_PINS; i++)
{
(void)lpc17_configgpio(g_enetpins[i]);
}
lpc17_showpins();
/* Initialize the driver structure */
priv->lp_dev.d_ifup = lpc17_ifup; /* I/F down callback */
priv->lp_dev.d_ifdown = lpc17_ifdown; /* I/F up (new IP address) callback */
priv->lp_dev.d_txavail = lpc17_txavail; /* New TX data callback */
priv->lp_dev.d_addmac = lpc17_addmac; /* Add multicast MAC address */
priv->lp_dev.d_rmmac = lpc17_rmmac; /* Remove multicast MAC address */
#endif
priv->lp_dev.d_private = (void*)priv; /* Used to recover private state from dev */
# error "A mechanism to associate base address an IRQ with an interface is needed"
priv->lp_base = ??; /* Ethernet controller base address */
priv->lp_irq = ??; /* Ethernet controller IRQ number */
#endif
/* Create a watchdog for timing polling for and timing of transmisstions */
priv->lp_txpoll = wd_create(); /* Create periodic poll timer */
priv->lp_txtimeout = wd_create(); /* Create TX timeout timer */
/* Reset the Ethernet controller and leave in the ifdown statue. The
* Ethernet controller will be properly re-initialized each time
* lpc17_ifup() is called.
*/
lpc17_ifdown(&priv->lp_dev);
/* Attach the IRQ to the driver */
ret = irq_attach(priv->irq, lpc17_interrupt);
#else
ret = irq_attach(LPC17_IRQ_ETH, lpc17_interrupt);
#endif
if (ret != 0)
{
/* We could not attach the ISR to the the interrupt */
/* Register the device with the OS so that socket IOCTLs can be performed */
(void)netdev_register(&priv->lp_dev);
/****************************************************************************
* Name: up_netinitialize
*
* Description:
* Initialize the first network interface. If there are more than one
* interface in the chip, then board-specific logic will have to provide
* this function to determine which, if any, Ethernet controllers should
* be initialized.
*
****************************************************************************/
void up_netinitialize(void)
{
(void)lpc17_ethinitialize(0);
}
#endif
#endif /* LPC17_NETHCONTROLLERS > 0 */
#endif /* CONFIG_NET && CONFIG_LPC17_ETHERNET */