The PHY isn't being found because the FEC_SEL signal is not asserted when the FEC reads the PHY serially to get its ID.
I've had lots of trouble with the ethernet setup trying to get a patched kernel to run on the ZoomLite with the i.MX27 SOM. I think I have it
straightened out now. Maybe some of this will be of value to others struggling to port to the ZoomLite.
First of all, the ethernet LEDs never come on the first time I power the board. When the two LEDs near the ethernet connector are off and I try to load an image via tftp I get the "No empty FEC TX DMA buffers" message. However, if I wait for the board GPIO0 and GPIO1 LEDs to start blinking and then quickly toggle the power off then on, the ethernet LEDs come on and I can communicate via tftp. It works consistently.
In examining the kernel boot messages I noticed the fec driver was just not happy with the ZoomLite PHY because it was getting the ID wrong, was not setting the ethernet address correctly, was not recognizing the SMSC PHY and was therefore not initializing it. When you use LOLO to configure sm0 before booting it happens to be in a reasonable state - but the same isn't true for booting without configuring via LOLO first.
When you use 'ifconfig sm0 /dev/config' via LOLO, the MAC address gets loaded into the FEC and the FEC_SEL signal is enabled so the FEC can communicate with the PHY. An unpatched MX27ADS 2.6.22 kernel FEC driver loads the MAC address from flash for some systems but when ARCH_MXC is defined, it tries to load the address from the i.MX 'IMM' area (which seems to be inaccessible on a ZoomLite via LOLO - and appears unprogrammed when read via the FEC driver). When the MAC address is all zeros or all FFs, the fec driver replaces it with a default address.
The patched 2.6.22 kernel FEC driver just reads the ethernet address from the FEC assuming the bootloader (in our case LOLO) has initialized it. The default MAC address can be specified on the kernel command line:
fec_mac=00:01:02:03:04:05
This is fine for development but on a Zoom Lite board, we should be getting the MAC address from the serial EEPROM.
Here are some things I experimented with to get things to work:
1. Make sure the FEC_SEL signal is asserted to allow the FEC to communicate with the PHY. You can do this in the 'gpio_fec_active' function in ads27_gpio.c in arch/arm/mach-mx27:
#define FEC_SEL_PIN MX27_PIN_SSI3_CLK
/* Configure the FEC PHY select output to enable it */
gpio_request_mux(FEC_SEL_PIN, GPIO_MUX_GPIO);
mxc_set_gpio_direction(FEC_SEL_PIN, 0);
mxc_set_gpio_dataout(FEC_SEL_PIN, 1);
2. Set the expio_intr_fec to zero in mx27ads.c and change the fec.c driver to not use request_irq, disable_irq, or enable_irq for the PHY whenever the value of expio_intr_fec is zero. You don't need the PHY to interrupt since all the driver ever does is acknowledge it. The FEC gets internal interrupts from the PHY by communicating with it serially. If you need the PHY to interrupt then configure the PCMCIA_READY input as the source.
3. Tweak the discovery function in the fec.c driver to ignore the first 2 to 4 bits of the first PHY ID word because the SMSC8700 sometimes returns 7fff and 3fff when you query it with an address other than its own. Because of this, the fec driver thinks the phy ID is 7fffffff or 3fffffff at address 0 when it should be discovering ID 0x007C0C3 at address 0x1f (the default for the SMSC8700).
TO DO THIS I REPLACED:
if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) {
WITH:
phytype = mii_reg & 0xffff;
if (((phytype & 0x0fff) != 0x0fff) && (phytype != 0)) {
4. Finally, add support for the SMSC8700 to the fec.c driver. You don't need to configure PHYLIB or load the SMSC driver - all ethernet and PHY support is handled internal to the fec driver. To add another PHY just add a PHY info structure for it. This one seems to work for me. Note, we don't even enable PHY interrupts so we don't need to provide anything for the 'ack_int' command sequence. Also, the 'shutdown' member is never used so it can be empty as well. Also note, IDs are shifted right 4 bits:
static phy_info_t phy_info_smsc8700= {
0x00007c0c,
"SMSC8700",
(const phy_cmd_t []) { /* config */
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* startup */
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* auto-negotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* ack_int - never happens, no interrupt */
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* shutdown */
{ mk_mii_end, }
},
};
Don't forget to add a pointer to the SMSC info in the info array:
static phy_info_t const * const phy_info[] = {
&phy_info_lxt970,
&phy_info_lxt971,
&phy_info_qs6612,
&phy_info_am79c874,
&phy_info_ks8721bl,
&phy_info_dp83848,
&phy_info_smsc8700, /* <------ added phy_info pointer */
NULL
With these mods, the fec driver recognizes and initializes the SMSC PHY properly on the ZoomLite. My output during boot looks like:
FEC ENET Version 0.2
fec: PHY @ 0x1f, ID 0x0007c0c3 -- SMSC8700
eth0: ethernet 00:08:ee:01:f6:c3
I haven't tried to read the MAC address out of the serial EEPROM so for now I just pass the ethernet address on the kernel command line.