|
@@ -107,6 +107,11 @@ struct macb_device {
|
|
};
|
|
};
|
|
#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
|
|
#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
|
|
|
|
|
|
|
|
+static int macb_is_gem(struct macb_device *macb)
|
|
|
|
+{
|
|
|
|
+ return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2;
|
|
|
|
+}
|
|
|
|
+
|
|
static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
|
|
static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
|
|
{
|
|
{
|
|
unsigned long netctl;
|
|
unsigned long netctl;
|
|
@@ -427,28 +432,64 @@ static int macb_phy_init(struct macb_device *macb)
|
|
printf("%s: link down (status: 0x%04x)\n",
|
|
printf("%s: link down (status: 0x%04x)\n",
|
|
netdev->name, status);
|
|
netdev->name, status);
|
|
return 0;
|
|
return 0;
|
|
- } else {
|
|
|
|
- adv = macb_mdio_read(macb, MII_ADVERTISE);
|
|
|
|
- lpa = macb_mdio_read(macb, MII_LPA);
|
|
|
|
- media = mii_nway_result(lpa & adv);
|
|
|
|
- speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
|
|
|
- ? 1 : 0);
|
|
|
|
- duplex = (media & ADVERTISE_FULL) ? 1 : 0;
|
|
|
|
- printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
|
|
|
|
- netdev->name,
|
|
|
|
- speed ? "100" : "10",
|
|
|
|
- duplex ? "full" : "half",
|
|
|
|
- lpa);
|
|
|
|
-
|
|
|
|
- ncfgr = macb_readl(macb, NCFGR);
|
|
|
|
- ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
|
|
|
- if (speed)
|
|
|
|
- ncfgr |= MACB_BIT(SPD);
|
|
|
|
- if (duplex)
|
|
|
|
- ncfgr |= MACB_BIT(FD);
|
|
|
|
- macb_writel(macb, NCFGR, ncfgr);
|
|
|
|
- return 1;
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* First check for GMAC */
|
|
|
|
+ if (macb_is_gem(macb)) {
|
|
|
|
+ lpa = macb_mdio_read(macb, MII_STAT1000);
|
|
|
|
+ if (lpa & (1 << 11)) {
|
|
|
|
+ speed = 1000;
|
|
|
|
+ duplex = 1;
|
|
|
|
+ } else {
|
|
|
|
+ if (lpa & (1 << 10)) {
|
|
|
|
+ speed = 1000;
|
|
|
|
+ duplex = 1;
|
|
|
|
+ } else {
|
|
|
|
+ speed = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (speed == 1000) {
|
|
|
|
+ printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n",
|
|
|
|
+ netdev->name,
|
|
|
|
+ speed,
|
|
|
|
+ duplex ? "full" : "half",
|
|
|
|
+ lpa);
|
|
|
|
+
|
|
|
|
+ ncfgr = macb_readl(macb, NCFGR);
|
|
|
|
+ ncfgr &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD));
|
|
|
|
+ if (speed)
|
|
|
|
+ ncfgr |= GEM_BIT(GBE);
|
|
|
|
+ if (duplex)
|
|
|
|
+ ncfgr |= MACB_BIT(FD);
|
|
|
|
+ macb_writel(macb, NCFGR, ncfgr);
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* fall back for EMAC checking */
|
|
|
|
+ adv = macb_mdio_read(macb, MII_ADVERTISE);
|
|
|
|
+ lpa = macb_mdio_read(macb, MII_LPA);
|
|
|
|
+ media = mii_nway_result(lpa & adv);
|
|
|
|
+ speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
|
|
|
+ ? 1 : 0);
|
|
|
|
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
|
|
|
|
+ printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
|
|
|
|
+ netdev->name,
|
|
|
|
+ speed ? "100" : "10",
|
|
|
|
+ duplex ? "full" : "half",
|
|
|
|
+ lpa);
|
|
|
|
+
|
|
|
|
+ ncfgr = macb_readl(macb, NCFGR);
|
|
|
|
+ ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
|
|
|
+ if (speed)
|
|
|
|
+ ncfgr |= MACB_BIT(SPD);
|
|
|
|
+ if (duplex)
|
|
|
|
+ ncfgr |= MACB_BIT(FD);
|
|
|
|
+ macb_writel(macb, NCFGR, ncfgr);
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
|
|
|
|
static int macb_init(struct eth_device *netdev, bd_t *bd)
|
|
static int macb_init(struct eth_device *netdev, bd_t *bd)
|
|
@@ -483,6 +524,13 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
|
|
macb_writel(macb, RBQP, macb->rx_ring_dma);
|
|
macb_writel(macb, RBQP, macb->rx_ring_dma);
|
|
macb_writel(macb, TBQP, macb->tx_ring_dma);
|
|
macb_writel(macb, TBQP, macb->tx_ring_dma);
|
|
|
|
|
|
|
|
+ if (macb_is_gem(macb)) {
|
|
|
|
+#ifdef CONFIG_RGMII
|
|
|
|
+ gem_writel(macb, UR, GEM_BIT(RGMII));
|
|
|
|
+#else
|
|
|
|
+ gem_writel(macb, UR, 0);
|
|
|
|
+#endif
|
|
|
|
+ } else {
|
|
/* choose RMII or MII mode. This depends on the board */
|
|
/* choose RMII or MII mode. This depends on the board */
|
|
#ifdef CONFIG_RMII
|
|
#ifdef CONFIG_RMII
|
|
#ifdef CONFIG_AT91FAMILY
|
|
#ifdef CONFIG_AT91FAMILY
|
|
@@ -497,6 +545,7 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
|
|
macb_writel(macb, USRIO, MACB_BIT(MII));
|
|
macb_writel(macb, USRIO, MACB_BIT(MII));
|
|
#endif
|
|
#endif
|
|
#endif /* CONFIG_RMII */
|
|
#endif /* CONFIG_RMII */
|
|
|
|
+ }
|
|
|
|
|
|
if (!macb_phy_init(macb))
|
|
if (!macb_phy_init(macb))
|
|
return -1;
|
|
return -1;
|
|
@@ -540,11 +589,48 @@ static int macb_write_hwaddr(struct eth_device *dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
|
|
|
|
+{
|
|
|
|
+ u32 config;
|
|
|
|
+ unsigned long macb_hz = get_macb_pclk_rate(id);
|
|
|
|
+
|
|
|
|
+ if (macb_hz < 20000000)
|
|
|
|
+ config = MACB_BF(CLK, MACB_CLK_DIV8);
|
|
|
|
+ else if (macb_hz < 40000000)
|
|
|
|
+ config = MACB_BF(CLK, MACB_CLK_DIV16);
|
|
|
|
+ else if (macb_hz < 80000000)
|
|
|
|
+ config = MACB_BF(CLK, MACB_CLK_DIV32);
|
|
|
|
+ else
|
|
|
|
+ config = MACB_BF(CLK, MACB_CLK_DIV64);
|
|
|
|
+
|
|
|
|
+ return config;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
|
|
|
|
+{
|
|
|
|
+ u32 config;
|
|
|
|
+ unsigned long macb_hz = get_macb_pclk_rate(id);
|
|
|
|
+
|
|
|
|
+ if (macb_hz < 20000000)
|
|
|
|
+ config = GEM_BF(CLK, GEM_CLK_DIV8);
|
|
|
|
+ else if (macb_hz < 40000000)
|
|
|
|
+ config = GEM_BF(CLK, GEM_CLK_DIV16);
|
|
|
|
+ else if (macb_hz < 80000000)
|
|
|
|
+ config = GEM_BF(CLK, GEM_CLK_DIV32);
|
|
|
|
+ else if (macb_hz < 120000000)
|
|
|
|
+ config = GEM_BF(CLK, GEM_CLK_DIV48);
|
|
|
|
+ else if (macb_hz < 160000000)
|
|
|
|
+ config = GEM_BF(CLK, GEM_CLK_DIV64);
|
|
|
|
+ else
|
|
|
|
+ config = GEM_BF(CLK, GEM_CLK_DIV96);
|
|
|
|
+
|
|
|
|
+ return config;
|
|
|
|
+}
|
|
|
|
+
|
|
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
|
|
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
|
|
{
|
|
{
|
|
struct macb_device *macb;
|
|
struct macb_device *macb;
|
|
struct eth_device *netdev;
|
|
struct eth_device *netdev;
|
|
- unsigned long macb_hz;
|
|
|
|
u32 ncfgr;
|
|
u32 ncfgr;
|
|
|
|
|
|
macb = malloc(sizeof(struct macb_device));
|
|
macb = malloc(sizeof(struct macb_device));
|
|
@@ -568,7 +654,11 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
|
|
macb->regs = regs;
|
|
macb->regs = regs;
|
|
macb->phy_addr = phy_addr;
|
|
macb->phy_addr = phy_addr;
|
|
|
|
|
|
- sprintf(netdev->name, "macb%d", id);
|
|
|
|
|
|
+ if (macb_is_gem(macb))
|
|
|
|
+ sprintf(netdev->name, "gmac%d", id);
|
|
|
|
+ else
|
|
|
|
+ sprintf(netdev->name, "macb%d", id);
|
|
|
|
+
|
|
netdev->init = macb_init;
|
|
netdev->init = macb_init;
|
|
netdev->halt = macb_halt;
|
|
netdev->halt = macb_halt;
|
|
netdev->send = macb_send;
|
|
netdev->send = macb_send;
|
|
@@ -579,15 +669,12 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
|
|
* Do some basic initialization so that we at least can talk
|
|
* Do some basic initialization so that we at least can talk
|
|
* to the PHY
|
|
* to the PHY
|
|
*/
|
|
*/
|
|
- macb_hz = get_macb_pclk_rate(id);
|
|
|
|
- if (macb_hz < 20000000)
|
|
|
|
- ncfgr = MACB_BF(CLK, MACB_CLK_DIV8);
|
|
|
|
- else if (macb_hz < 40000000)
|
|
|
|
- ncfgr = MACB_BF(CLK, MACB_CLK_DIV16);
|
|
|
|
- else if (macb_hz < 80000000)
|
|
|
|
- ncfgr = MACB_BF(CLK, MACB_CLK_DIV32);
|
|
|
|
- else
|
|
|
|
- ncfgr = MACB_BF(CLK, MACB_CLK_DIV64);
|
|
|
|
|
|
+ if (macb_is_gem(macb)) {
|
|
|
|
+ ncfgr = gem_mdc_clk_div(id, macb);
|
|
|
|
+ ncfgr |= GEM_BF(DBW, 1);
|
|
|
|
+ } else {
|
|
|
|
+ ncfgr = macb_mdc_clk_div(id, macb);
|
|
|
|
+ }
|
|
|
|
|
|
macb_writel(macb, NCFGR, ncfgr);
|
|
macb_writel(macb, NCFGR, ncfgr);
|
|
|
|
|