+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;
+}
+
+/*
+ * Get the DMA bus width field of the network configuration register that we
+ * should program. We find the width from decoding the design configuration
+ * register to find the maximum supported data bus width.
+ */
+static u32 macb_dbw(struct macb_device *macb)
+{
+ switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) {
+ case 4:
+ return GEM_BF(DBW, GEM_DBW128);
+ case 2:
+ return GEM_BF(DBW, GEM_DBW64);
+ case 1:
+ default:
+ return GEM_BF(DBW, GEM_DBW32);
+ }
+}
+
+static void _macb_eth_initialize(struct macb_device *macb)
+{
+ int id = 0; /* This is not used by functions we call */
+ u32 ncfgr;
+
+ /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */
+ macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE,
+ &macb->rx_buffer_dma);
+ macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE,
+ &macb->rx_ring_dma);
+ macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE,
+ &macb->tx_ring_dma);
+ macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE,
+ &macb->dummy_desc_dma);
+
+ /*
+ * Do some basic initialization so that we at least can talk
+ * to the PHY
+ */
+ if (macb_is_gem(macb)) {
+ ncfgr = gem_mdc_clk_div(id, macb);
+ ncfgr |= macb_dbw(macb);
+ } else {
+ ncfgr = macb_mdc_clk_div(id, macb);
+ }
+
+ macb_writel(macb, NCFGR, ncfgr);
+}
+
+#ifndef CONFIG_DM_ETH
+static int macb_send(struct eth_device *netdev, void *packet, int length)
+{
+ struct macb_device *macb = to_macb(netdev);
+
+ return _macb_send(macb, netdev->name, packet, length);
+}
+
+static int macb_recv(struct eth_device *netdev)
+{
+ struct macb_device *macb = to_macb(netdev);
+ uchar *packet;
+ int length;
+
+ macb->wrapped = false;
+ for (;;) {
+ macb->next_rx_tail = macb->rx_tail;
+ length = _macb_recv(macb, &packet);
+ if (length >= 0) {
+ net_process_received_packet(packet, length);
+ reclaim_rx_buffers(macb, macb->next_rx_tail);
+ } else if (length < 0) {
+ return length;
+ }
+ }
+}
+
+static int macb_init(struct eth_device *netdev, bd_t *bd)
+{
+ struct macb_device *macb = to_macb(netdev);
+
+ return _macb_init(macb, netdev->name);
+}
+
+static void macb_halt(struct eth_device *netdev)
+{
+ struct macb_device *macb = to_macb(netdev);
+
+ return _macb_halt(macb);
+}
+
+static int macb_write_hwaddr(struct eth_device *netdev)
+{
+ struct macb_device *macb = to_macb(netdev);
+
+ return _macb_write_hwaddr(macb, netdev->enetaddr);
+}
+