@@ -11,6 +11,7 @@ obj-y += psc.o
obj-y += clock.o
obj-y += cmd_clock.o
obj-y += cmd_mon.o
+obj-y += keystone_nav.o
obj-y += msmc.o
obj-y += lowlevel_init.o
obj-$(CONFIG_SPL_BUILD) += spl.o
new file mode 100644
@@ -0,0 +1,377 @@
+/*
+ * Multicore Navigator driver for TI Keystone 2 devices.
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/keystone_nav.h>
+
+static int soc_type =
+#ifdef CONFIG_SOC_K2HK
+ k2hk;
+#endif
+
+struct qm_config k2hk_qm_memmap = {
+ .stat_cfg = 0x02a40000,
+ .queue = (struct qm_reg_queue *)0x02a80000,
+ .mngr_vbusm = 0x23a80000,
+ .i_lram = 0x00100000,
+ .proxy = (struct qm_reg_queue *)0x02ac0000,
+ .status_ram = 0x02a06000,
+ .mngr_cfg = (struct qm_cfg_reg *)0x02a02000,
+ .intd_cfg = 0x02a0c000,
+ .desc_mem = (struct descr_mem_setup_reg *)0x02a03000,
+ .region_num = 64,
+ .pdsp_cmd = 0x02a20000,
+ .pdsp_ctl = 0x02a0f000,
+ .pdsp_iram = 0x02a10000,
+ .qpool_num = 4000,
+};
+
+/*
+ * We are going to use only one type of descriptors - host packet
+ * descriptors. We staticaly allocate memory for them here
+ */
+struct qm_host_desc desc_pool[HDESC_NUM] __aligned(sizeof(struct qm_host_desc));
+
+static struct qm_config *qm_cfg;
+
+inline int num_of_desc_to_reg(int num_descr)
+{
+ int j, num;
+
+ for (j = 0, num = 32; j < 15; j++, num *= 2) {
+ if (num_descr <= num)
+ return j;
+ }
+
+ return 15;
+}
+
+static int _qm_init(struct qm_config *cfg)
+{
+ u32 j;
+
+ if (cfg == NULL)
+ return QM_ERR;
+
+ qm_cfg = cfg;
+
+ qm_cfg->mngr_cfg->link_ram_base0 = qm_cfg->i_lram;
+ qm_cfg->mngr_cfg->link_ram_size0 = HDESC_NUM * 8;
+ qm_cfg->mngr_cfg->link_ram_base1 = 0;
+ qm_cfg->mngr_cfg->link_ram_size1 = 0;
+ qm_cfg->mngr_cfg->link_ram_base2 = 0;
+
+ qm_cfg->desc_mem[0].base_addr = (u32)desc_pool;
+ qm_cfg->desc_mem[0].start_idx = 0;
+ qm_cfg->desc_mem[0].desc_reg_size =
+ (((sizeof(struct qm_host_desc) >> 4) - 1) << 16) |
+ num_of_desc_to_reg(HDESC_NUM);
+
+ memset(desc_pool, 0, sizeof(desc_pool));
+ for (j = 0; j < HDESC_NUM; j++)
+ qm_push(&desc_pool[j], qm_cfg->qpool_num);
+
+ return QM_OK;
+}
+
+int qm_init(void)
+{
+ switch (soc_type) {
+ case k2hk:
+ return _qm_init(&k2hk_qm_memmap);
+ }
+
+ return QM_ERR;
+}
+
+void qm_close(void)
+{
+ u32 j;
+
+ if (qm_cfg == NULL)
+ return;
+
+ queue_close(qm_cfg->qpool_num);
+
+ qm_cfg->mngr_cfg->link_ram_base0 = 0;
+ qm_cfg->mngr_cfg->link_ram_size0 = 0;
+ qm_cfg->mngr_cfg->link_ram_base1 = 0;
+ qm_cfg->mngr_cfg->link_ram_size1 = 0;
+ qm_cfg->mngr_cfg->link_ram_base2 = 0;
+
+ for (j = 0; j < qm_cfg->region_num; j++) {
+ qm_cfg->desc_mem[j].base_addr = 0;
+ qm_cfg->desc_mem[j].start_idx = 0;
+ qm_cfg->desc_mem[j].desc_reg_size = 0;
+ }
+
+ qm_cfg = NULL;
+}
+
+void qm_push(struct qm_host_desc *hd, u32 qnum)
+{
+ u32 regd;
+
+ if (!qm_cfg)
+ return;
+
+ cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4);
+ regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1);
+ writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh);
+}
+
+void qm_buff_push(struct qm_host_desc *hd, u32 qnum,
+ void *buff_ptr, u32 buff_len)
+{
+ hd->orig_buff_len = buff_len;
+ hd->buff_len = buff_len;
+ hd->orig_buff_ptr = (u32)buff_ptr;
+ hd->buff_ptr = (u32)buff_ptr;
+ qm_push(hd, qnum);
+}
+
+struct qm_host_desc *qm_pop(u32 qnum)
+{
+ u32 uhd;
+
+ if (!qm_cfg)
+ return NULL;
+
+ uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf;
+ if (uhd)
+ cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4);
+
+ return (struct qm_host_desc *)uhd;
+}
+
+struct qm_host_desc *qm_pop_from_free_pool(void)
+{
+ if (!qm_cfg)
+ return NULL;
+
+ return qm_pop(qm_cfg->qpool_num);
+}
+
+void queue_close(u32 qnum)
+{
+ struct qm_host_desc *hd;
+
+ while ((hd = qm_pop(qnum)))
+ ;
+}
+
+/************************************************
+ * DMA API
+ ***********************************************/
+
+struct pktdma_cfg k2hk_netcp_pktdma = {
+ .global = (struct global_ctl_regs *)0x02004000,
+ .tx_ch = (struct tx_chan_regs *)0x02004400,
+ .tx_ch_num = 9,
+ .rx_ch = (struct rx_chan_regs *)0x02004800,
+ .rx_ch_num = 26,
+ .tx_sched = (u32 *)0x02004c00,
+ .rx_flows = (struct rx_flow_regs *)0x02005000,
+ .rx_flow_num = 32,
+
+ .rx_free_q = 4001,
+ .rx_rcv_q = 4002,
+ .tx_snd_q = 648,
+};
+
+struct pktdma_cfg *netcp;
+
+static int netcp_rx_disable(void)
+{
+ u32 j, v, k;
+
+ for (j = 0; j < netcp->rx_ch_num; j++) {
+ v = readl(&netcp->rx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+
+ writel(v | CPDMA_CHAN_A_TDOWN, &netcp->rx_ch[j].cfg_a);
+ for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) {
+ udelay(100);
+ v = readl(&netcp->rx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+ }
+ /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */
+ }
+
+ /* Clear all of the flow registers */
+ for (j = 0; j < netcp->rx_flow_num; j++) {
+ writel(0, &netcp->rx_flows[j].control);
+ writel(0, &netcp->rx_flows[j].tags);
+ writel(0, &netcp->rx_flows[j].tag_sel);
+ writel(0, &netcp->rx_flows[j].fdq_sel[0]);
+ writel(0, &netcp->rx_flows[j].fdq_sel[1]);
+ writel(0, &netcp->rx_flows[j].thresh[0]);
+ writel(0, &netcp->rx_flows[j].thresh[1]);
+ writel(0, &netcp->rx_flows[j].thresh[2]);
+ }
+
+ return QM_OK;
+}
+
+static int netcp_tx_disable(void)
+{
+ u32 j, v, k;
+
+ for (j = 0; j < netcp->tx_ch_num; j++) {
+ v = readl(&netcp->tx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+
+ writel(v | CPDMA_CHAN_A_TDOWN, &netcp->tx_ch[j].cfg_a);
+ for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) {
+ udelay(100);
+ v = readl(&netcp->tx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+ }
+ /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */
+ }
+
+ return QM_OK;
+}
+
+static int _netcp_init(struct pktdma_cfg *netcp_cfg,
+ struct rx_buff_desc *rx_buffers)
+{
+ u32 j, v;
+ struct qm_host_desc *hd;
+ u8 *rx_ptr;
+
+ if (netcp_cfg == NULL || rx_buffers == NULL ||
+ rx_buffers->buff_ptr == NULL || qm_cfg == NULL)
+ return QM_ERR;
+
+ netcp = netcp_cfg;
+ netcp->rx_flow = rx_buffers->rx_flow;
+
+ /* init rx queue */
+ rx_ptr = rx_buffers->buff_ptr;
+
+ for (j = 0; j < rx_buffers->num_buffs; j++) {
+ hd = qm_pop(qm_cfg->qpool_num);
+ if (hd == NULL)
+ return QM_ERR;
+
+ qm_buff_push(hd, netcp->rx_free_q,
+ rx_ptr, rx_buffers->buff_len);
+
+ rx_ptr += rx_buffers->buff_len;
+ }
+
+ netcp_rx_disable();
+
+ /* configure rx channels */
+ v = CPDMA_REG_VAL_MAKE_RX_FLOW_A(1, 1, 0, 0, 0, 0, 0, netcp->rx_rcv_q);
+ writel(v, &netcp->rx_flows[netcp->rx_flow].control);
+ writel(0, &netcp->rx_flows[netcp->rx_flow].tags);
+ writel(0, &netcp->rx_flows[netcp->rx_flow].tag_sel);
+
+ v = CPDMA_REG_VAL_MAKE_RX_FLOW_D(0, netcp->rx_free_q, 0,
+ netcp->rx_free_q);
+
+ writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[0]);
+ writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[1]);
+ writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[0]);
+ writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[1]);
+ writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[2]);
+
+ for (j = 0; j < netcp->rx_ch_num; j++)
+ writel(CPDMA_CHAN_A_ENABLE, &netcp->rx_ch[j].cfg_a);
+
+ /* configure tx channels */
+ /* Disable loopback in the tx direction */
+ writel(0, &netcp->global->emulation_control);
+
+/* TODO: make it dependend on a soc type variable */
+#ifdef CONFIG_SOC_K2HK
+ /* Set QM base address, only for K2x devices */
+ writel(0x23a80000, &netcp->global->qm_base_addr[0]);
+#endif
+
+ /* Enable all channels. The current state isn't important */
+ for (j = 0; j < netcp->tx_ch_num; j++) {
+ writel(0, &netcp->tx_ch[j].cfg_b);
+ writel(CPDMA_CHAN_A_ENABLE, &netcp->tx_ch[j].cfg_a);
+ }
+
+ return QM_OK;
+}
+
+int netcp_init(struct rx_buff_desc *rx_buffers)
+{
+ switch (soc_type) {
+ case k2hk:
+ _netcp_init(&k2hk_netcp_pktdma, rx_buffers);
+ return QM_OK;
+ }
+ return QM_ERR;
+}
+
+int netcp_close(void)
+{
+ if (!netcp)
+ return QM_ERR;
+
+ netcp_tx_disable();
+ netcp_rx_disable();
+
+ queue_close(netcp->rx_free_q);
+ queue_close(netcp->rx_rcv_q);
+ queue_close(netcp->tx_snd_q);
+
+ return QM_OK;
+}
+
+int netcp_send(u32 *pkt, int num_bytes, u32 swinfo2)
+{
+ struct qm_host_desc *hd;
+
+ hd = qm_pop(qm_cfg->qpool_num);
+ if (hd == NULL)
+ return QM_ERR;
+
+ hd->desc_info = num_bytes;
+ hd->swinfo[2] = swinfo2;
+ hd->packet_info = qm_cfg->qpool_num;
+
+ qm_buff_push(hd, netcp->tx_snd_q, pkt, num_bytes);
+
+ return QM_OK;
+}
+
+void *netcp_recv(u32 **pkt, int *num_bytes)
+{
+ struct qm_host_desc *hd;
+
+ hd = qm_pop(netcp->rx_rcv_q);
+ if (!hd)
+ return NULL;
+
+ *pkt = (u32 *)hd->buff_ptr;
+ *num_bytes = hd->desc_info & 0x3fffff;
+
+ return hd;
+}
+
+void netcp_release_rxhd(void *hd)
+{
+ struct qm_host_desc *_hd = (struct qm_host_desc *)hd;
+
+ _hd->buff_len = _hd->orig_buff_len;
+ _hd->buff_ptr = _hd->orig_buff_ptr;
+
+ qm_push(_hd, netcp->rx_free_q);
+}
new file mode 100644
@@ -0,0 +1,255 @@
+/*
+ * emac definitions for keystone2 devices
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _EMAC_DEFS_H_
+#define _EMAC_DEFS_H_
+
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+#define DEVICE_REG32_R(a) readl(a)
+#define DEVICE_REG32_W(a, v) writel(v, a)
+
+/*#define chipLmbd(x,y) _lmbd(x,y) */
+
+#define EMAC_EMACSL_BASE_ADDR (KS2_PASS_BASE + 0x00090900)
+#define EMAC_MDIO_BASE_ADDR (KS2_PASS_BASE + 0x00090300)
+#define EMAC_SGMII_BASE_ADDR (KS2_PASS_BASE + 0x00090100)
+
+#define KEYSTONE2_EMAC_GIG_ENABLE
+
+#define MAC_ID_BASE_ADDR (KS2_DEVICE_STATE_CTRL_BASE + 0x110)
+
+#ifdef CONFIG_SOC_K2HK
+/* MDIO module input frequency */
+#define EMAC_MDIO_BUS_FREQ (clk_get_rate(pass_pll_clk))
+/* MDIO clock output frequency */
+#define EMAC_MDIO_CLOCK_FREQ 1000000 /* 1.0 MHz */
+#endif
+
+/* MII Status Register */
+#define MII_STATUS_REG 1
+#define MII_STATUS_LINK_MASK (0x4)
+
+/* Marvell 88E1111 PHY ID */
+#define PHY_MARVELL_88E1111 (0x01410cc0)
+
+
+
+#define MDIO_CONTROL_IDLE (0x80000000)
+#define MDIO_CONTROL_ENABLE (0x40000000)
+#define MDIO_CONTROL_FAULT_ENABLE (0x40000)
+#define MDIO_CONTROL_FAULT (0x80000)
+#define MDIO_USERACCESS0_GO (0x80000000)
+#define MDIO_USERACCESS0_WRITE_READ (0x0)
+#define MDIO_USERACCESS0_WRITE_WRITE (0x40000000)
+#define MDIO_USERACCESS0_ACK (0x20000000)
+
+#define EMAC_MACCONTROL_MIIEN_ENABLE (0x20)
+#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE (0x1)
+#define EMAC_MACCONTROL_GIGABIT_ENABLE (1 << 7)
+#define EMAC_MACCONTROL_GIGFORCE (1 << 17)
+#define EMAC_MACCONTROL_RMIISPEED_100 (1 << 15)
+
+#define EMAC_MIN_ETHERNET_PKT_SIZE 60
+
+struct mac_sl_cfg {
+ u_int32_t max_rx_len; /* Maximum receive packet length. */
+ u_int32_t ctl; /* Control bitfield */
+};
+
+/***************************************************************************
+ * Definition: Control bitfields used in the ctl field of hwGmacSlCfg_t
+ **************************************************************************/
+#define GMACSL_RX_ENABLE_RCV_CONTROL_FRAMES (1 << 24)
+#define GMACSL_RX_ENABLE_RCV_SHORT_FRAMES (1 << 23)
+#define GMACSL_RX_ENABLE_RCV_ERROR_FRAMES (1 << 22)
+#define GMACSL_RX_ENABLE_EXT_CTL (1 << 18)
+#define GMACSL_RX_ENABLE_GIG_FORCE (1 << 17)
+#define GMACSL_RX_ENABLE_IFCTL_B (1 << 16)
+#define GMACSL_RX_ENABLE_IFCTL_A (1 << 15)
+#define GMACSL_RX_ENABLE_CMD_IDLE (1 << 11)
+#define GMACSL_TX_ENABLE_SHORT_GAP (1 << 10)
+#define GMACSL_ENABLE_GIG_MODE (1 << 7)
+#define GMACSL_TX_ENABLE_PACE (1 << 6)
+#define GMACSL_ENABLE (1 << 5)
+#define GMACSL_TX_ENABLE_FLOW_CTL (1 << 4)
+#define GMACSL_RX_ENABLE_FLOW_CTL (1 << 3)
+#define GMACSL_ENABLE_LOOPBACK (1 << 1)
+#define GMACSL_ENABLE_FULL_DUPLEX (1 << 0)
+
+
+/***************************************************************************
+ * DEFINTITION: function return values
+ **************************************************************************/
+#define GMACSL_RET_OK 0
+#define GMACSL_RET_INVALID_PORT -1
+#define GMACSL_RET_WARN_RESET_INCOMPLETE -2
+#define GMACSL_RET_WARN_MAXLEN_TOO_BIG -3
+#define GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE -4
+
+
+/* Register offsets */
+#define CPGMACSL_REG_ID 0x00
+#define CPGMACSL_REG_CTL 0x04
+#define CPGMACSL_REG_STATUS 0x08
+#define CPGMACSL_REG_RESET 0x0c
+#define CPGMACSL_REG_MAXLEN 0x10
+#define CPGMACSL_REG_BOFF 0x14
+#define CPGMACSL_REG_RX_PAUSE 0x18
+#define CPGMACSL_REG_TX_PAURSE 0x1c
+#define CPGMACSL_REG_EM_CTL 0x20
+#define CPGMACSL_REG_PRI 0x24
+
+/* Soft reset register values */
+#define CPGMAC_REG_RESET_VAL_RESET_MASK (1 << 0)
+#define CPGMAC_REG_RESET_VAL_RESET (1 << 0)
+
+/* Maxlen register values */
+#define CPGMAC_REG_MAXLEN_LEN 0x3fff
+
+ /* Control bitfields */
+#define CPSW_CTL_P2_PASS_PRI_TAGGED (1 << 5)
+#define CPSW_CTL_P1_PASS_PRI_TAGGED (1 << 4)
+#define CPSW_CTL_P0_PASS_PRI_TAGGED (1 << 3)
+#define CPSW_CTL_P0_ENABLE (1 << 2)
+#define CPSW_CTL_VLAN_AWARE (1 << 1)
+#define CPSW_CTL_FIFO_LOOPBACK (1 << 0)
+
+#define DEVICE_CPSW_NUM_PORTS 5 /* 5 switch ports */
+#define DEVICE_CPSW_BASE (0x02090800)
+#define target_get_switch_ctl() CPSW_CTL_P0_ENABLE /* Enable port 0 */
+#define SWITCH_MAX_PKT_SIZE 9000
+
+/* Register offsets */
+#define CPSW_REG_CTL 0x004
+#define CPSW_REG_STAT_PORT_EN 0x00c
+#define CPSW_REG_MAXLEN 0x040
+#define CPSW_REG_ALE_CONTROL 0x608
+#define CPSW_REG_ALE_PORTCTL(x) (0x640 + (x)*4)
+
+
+/* Register values */
+#define CPSW_REG_VAL_STAT_ENABLE_ALL 0xf
+#define CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE ((u_int32_t)0xc0000000)
+#define CPSW_REG_VAL_ALE_CTL_BYPASS ((u_int32_t)0x00000010)
+#define CPSW_REG_VAL_PORTCTL_FORWARD_MODE 0x3
+
+#define SGMII_REG_STATUS_LOCK BIT(4)
+#define SGMII_REG_STATUS_LINK BIT(0)
+#define SGMII_REG_STATUS_AUTONEG BIT(2)
+#define SGMII_REG_CONTROL_AUTONEG BIT(0)
+#define SGMII_REG_CONTROL_MASTER BIT(5)
+#define SGMII_REG_MR_ADV_ENABLE BIT(0)
+#define SGMII_REG_MR_ADV_LINK BIT(15)
+#define SGMII_REG_MR_ADV_FULL_DUPLEX BIT(12)
+#define SGMII_REG_MR_ADV_GIG_MODE BIT(11)
+
+#define SGMII_LINK_MAC_MAC_AUTONEG 0
+#define SGMII_LINK_MAC_PHY 1
+#define SGMII_LINK_MAC_MAC_FORCED 2
+#define SGMII_LINK_MAC_FIBER 3
+#define SGMII_LINK_MAC_PHY_FORCED 4
+
+#define TARGET_SGMII_BASE KS2_PASS_BASE + 0x00090100
+#define TARGET_SGMII_BASE_ADDRESSES {KS2_PASS_BASE+0x00090100, \
+ KS2_PASS_BASE+0x00090200, \
+ KS2_PASS_BASE+0x00090400, \
+ KS2_PASS_BASE+0x00090500 }
+
+#define SGMII_OFFSET(x) ((x <= 1) ? (x * 0x100) : ((x * 0x100) + 0x100))
+
+/*
+ * SGMII registers
+ */
+#define SGMII_IDVER_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x000)
+#define SGMII_SRESET_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x004)
+#define SGMII_CTL_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x010)
+#define SGMII_STATUS_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x014)
+#define SGMII_MRADV_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x018)
+#define SGMII_LPADV_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x020)
+#define SGMII_TXCFG_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x030)
+#define SGMII_RXCFG_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x034)
+#define SGMII_AUXCFG_REG(x) (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x038)
+
+#define DEVICE_EMACSL_BASE(x) (KS2_PASS_BASE + 0x00090900 + (x)*0x040)
+#define DEVICE_N_GMACSL_PORTS 4
+#define DEVICE_EMACSL_RESET_POLL_COUNT 100
+
+#define DEVICE_PSTREAM_CFG_REG_ADDR (KS2_PASS_BASE + 0x604)
+
+#ifdef CONFIG_SOC_K2HK
+#define DEVICE_PSTREAM_CFG_REG_VAL_ROUTE_CPPI 0x06060606
+#endif
+
+#define hw_config_streaming_switch() \
+ DEVICE_REG32_W(DEVICE_PSTREAM_CFG_REG_ADDR, \
+ DEVICE_PSTREAM_CFG_REG_VAL_ROUTE_CPPI);
+
+/* EMAC MDIO Registers Structure */
+struct mdio_regs {
+ dv_reg VERSION;
+ dv_reg CONTROL;
+ dv_reg ALIVE;
+ dv_reg LINK;
+ dv_reg LINKINTRAW;
+ dv_reg LINKINTMASKED;
+ u_int8_t RSVD0[8];
+ dv_reg USERINTRAW;
+ dv_reg USERINTMASKED;
+ dv_reg USERINTMASKSET;
+ dv_reg USERINTMASKCLEAR;
+ u_int8_t RSVD1[80];
+ dv_reg USERACCESS0;
+ dv_reg USERPHYSEL0;
+ dv_reg USERACCESS1;
+ dv_reg USERPHYSEL1;
+};
+
+/* Ethernet MAC Registers Structure */
+struct emac_regs {
+ dv_reg IDVER;
+ dv_reg MACCONTROL;
+ dv_reg MACSTATUS;
+ dv_reg SOFT_RESET;
+ dv_reg RX_MAXLEN;
+ u32 RSVD0;
+ dv_reg RX_PAUSE;
+ dv_reg TX_PAUSE;
+ dv_reg EMCONTROL;
+ dv_reg PRI_MAP;
+ u32 RSVD1[6];
+};
+
+struct phy_t {
+ char name[64];
+ int (*init)(int phy_addr);
+ int (*is_phy_connected)(int phy_addr);
+ int (*get_link_speed)(int phy_addr);
+ int (*auto_negotiate)(int phy_addr);
+};
+
+#define SGMII_ACCESS(port, reg) \
+ *((volatile unsigned int *)(sgmiis[port] + reg))
+
+struct eth_priv_t {
+ char int_name[32];
+ int rx_flow;
+ int phy_addr;
+ int slave_port;
+ int sgmii_link_type;
+};
+
+extern struct eth_priv_t eth_priv_cfg[];
+
+int keystone2_emac_initialize(struct eth_priv_t *eth_priv);
+void sgmii_serdes_setup_156p25mhz(void);
+void sgmii_serdes_shutdown(void);
+
+#endif /* _EMAC_DEFS_H_ */
new file mode 100644
@@ -0,0 +1,194 @@
+/*
+ * Multicore Navigator definitions
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _KEYSTONE_NAV_H_
+#define _KEYSTONE_NAV_H_
+
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+enum soc_type_t {
+ k2hk
+};
+
+
+#define QM_OK 0
+#define QM_ERR -1
+#define QM_DESC_TYPE_HOST 0
+#define QM_DESC_PSINFO_IN_DESCR 0
+#define QM_DESC_DEFAULT_DESCINFO (QM_DESC_TYPE_HOST << 30) | \
+ (QM_DESC_PSINFO_IN_DESCR << 22)
+
+/* Packet Info */
+#define QM_DESC_PINFO_EPIB 1
+#define QM_DESC_PINFO_RETURN_OWN 1
+#define QM_DESC_DEFAULT_PINFO (QM_DESC_PINFO_EPIB << 31) | \
+ (QM_DESC_PINFO_RETURN_OWN << 15)
+
+struct qm_cfg_reg {
+ u32 revision;
+ u32 __pad1;
+ u32 divert;
+ u32 link_ram_base0;
+ u32 link_ram_size0;
+ u32 link_ram_base1;
+ u32 link_ram_size1;
+ u32 link_ram_base2;
+ u32 starvation[0];
+};
+
+struct descr_mem_setup_reg {
+ u32 base_addr;
+ u32 start_idx;
+ u32 desc_reg_size;
+ u32 _res0;
+};
+
+struct qm_reg_queue {
+ u32 entry_count;
+ u32 byte_count;
+ u32 packet_size;
+ u32 ptr_size_thresh;
+};
+
+struct qm_config {
+ /* QM module addresses */
+ u32 stat_cfg; /* status and config */
+ struct qm_reg_queue *queue; /* management region */
+ u32 mngr_vbusm; /* management region (VBUSM) */
+ u32 i_lram; /* internal linking RAM */
+ struct qm_reg_queue *proxy;
+ u32 status_ram;
+ struct qm_cfg_reg *mngr_cfg;
+ /* Queue manager config region */
+ u32 intd_cfg; /* QMSS INTD config region */
+ struct descr_mem_setup_reg *desc_mem;
+ /* descritor memory setup region*/
+ u32 region_num;
+ u32 pdsp_cmd; /* PDSP1 command interface */
+ u32 pdsp_ctl; /* PDSP1 control registers */
+ u32 pdsp_iram;
+ /* QM configuration parameters */
+
+ u32 qpool_num; /* */
+};
+
+struct qm_host_desc {
+ u32 desc_info;
+ u32 tag_info;
+ u32 packet_info;
+ u32 buff_len;
+ u32 buff_ptr;
+ u32 next_bdptr;
+ u32 orig_buff_len;
+ u32 orig_buff_ptr;
+ u32 timestamp;
+ u32 swinfo[3];
+ u32 ps_data[20];
+};
+
+#define HDESC_NUM 256
+
+int qm_init(void);
+void qm_close(void);
+void qm_push(struct qm_host_desc *hd, u32 qnum);
+struct qm_host_desc *qm_pop(u32 qnum);
+
+void qm_buff_push(struct qm_host_desc *hd, u32 qnum,
+ void *buff_ptr, u32 buff_len);
+
+struct qm_host_desc *qm_pop_from_free_pool(void);
+void queue_close(u32 qnum);
+
+/**********************************************
+ * DMA API
+ *********************************************/
+#define CPDMA_REG_VAL_MAKE_RX_FLOW_A(einfo, psinfo, rxerr, desc, \
+ psloc, sopoff, qmgr, qnum) \
+ (((einfo & 1) << 30) | \
+ ((psinfo & 1) << 29) | \
+ ((rxerr & 1) << 28) | \
+ ((desc & 3) << 26) | \
+ ((psloc & 1) << 25) | \
+ ((sopoff & 0x1ff) << 16) | \
+ ((qmgr & 3) << 12) | \
+ ((qnum & 0xfff) << 0))
+
+#define CPDMA_REG_VAL_MAKE_RX_FLOW_D(fd0qm, fd0qnum, fd1qm, fd1qnum) \
+ (((fd0qm & 3) << 28) | \
+ ((fd0qnum & 0xfff) << 16) | \
+ ((fd1qm & 3) << 12) | \
+ ((fd1qnum & 0xfff) << 0))
+
+#define CPDMA_CHAN_A_ENABLE ((u32)1 << 31)
+#define CPDMA_CHAN_A_TDOWN (1 << 30)
+#define TDOWN_TIMEOUT_COUNT 100
+
+struct global_ctl_regs {
+ u32 revision;
+ u32 perf_control;
+ u32 emulation_control;
+ u32 priority_control;
+ u32 qm_base_addr[4];
+};
+
+struct tx_chan_regs {
+ u32 cfg_a;
+ u32 cfg_b;
+ u32 res[6];
+};
+
+struct rx_chan_regs {
+ u32 cfg_a;
+ u32 res[7];
+};
+
+struct rx_flow_regs {
+ u32 control;
+ u32 tags;
+ u32 tag_sel;
+ u32 fdq_sel[2];
+ u32 thresh[3];
+};
+
+struct pktdma_cfg {
+ struct global_ctl_regs *global;
+ struct tx_chan_regs *tx_ch;
+ u32 tx_ch_num;
+ struct rx_chan_regs *rx_ch;
+ u32 rx_ch_num;
+ u32 *tx_sched;
+ struct rx_flow_regs *rx_flows;
+ u32 rx_flow_num;
+
+ u32 rx_free_q;
+ u32 rx_rcv_q;
+ u32 tx_snd_q;
+
+ u32 rx_flow; /* flow that is used for RX */
+};
+
+/*
+ * packet dma user allocates memory for rx buffers
+ * and describe it in the following structure
+ */
+struct rx_buff_desc {
+ u8 *buff_ptr;
+ u32 num_buffs;
+ u32 buff_len;
+ u32 rx_flow;
+};
+
+int netcp_close(void);
+int netcp_init(struct rx_buff_desc *rx_buffers);
+int netcp_send(u32 *pkt, int num_bytes, u32 swinfo2);
+void *netcp_recv(u32 **pkt, int *num_bytes);
+void netcp_release_rxhd(void *hd);
+
+#endif /* _KEYSTONE_NAV_H_ */
@@ -17,6 +17,7 @@
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/arch/nand_defs.h>
+#include <asm/arch/emac_defs.h>
#include <asm/arch/psc_defs.h>
@@ -71,6 +72,70 @@ int dram_init(void)
return 0;
}
+#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
+struct eth_priv_t eth_priv_cfg[] = {
+ {
+ .int_name = "K2HK_EMAC",
+ .rx_flow = 22,
+ .phy_addr = 0,
+ .slave_port = 1,
+ .sgmii_link_type = SGMII_LINK_MAC_PHY,
+ },
+ {
+ .int_name = "K2HK_EMAC1",
+ .rx_flow = 23,
+ .phy_addr = 1,
+ .slave_port = 2,
+ .sgmii_link_type = SGMII_LINK_MAC_PHY,
+ },
+ {
+ .int_name = "K2HK_EMAC2",
+ .rx_flow = 24,
+ .phy_addr = 2,
+ .slave_port = 3,
+ .sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
+ },
+ {
+ .int_name = "K2HK_EMAC3",
+ .rx_flow = 25,
+ .phy_addr = 3,
+ .slave_port = 4,
+ .sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
+ },
+};
+
+int get_eth_env_param(char *env_name)
+{
+ char *env;
+ int res = -1;
+
+ env = getenv(env_name);
+ if (env)
+ res = simple_strtol(env, NULL, 0);
+
+ return res;
+}
+
+int board_eth_init(bd_t *bis)
+{
+ int j;
+ int res;
+ char link_type_name[32];
+
+ for (j = 0; j < (sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t));
+ j++) {
+ sprintf(link_type_name, "sgmii%d_link_type", j);
+ res = get_eth_env_param(link_type_name);
+ if (res >= 0)
+ eth_priv_cfg[j].sgmii_link_type = res;
+
+ keystone2_emac_initialize(ð_priv_cfg[j]);
+ }
+
+ return 0;
+}
+#endif
+
/* Byte swap the 32-bit data if the device is BE */
int cpu_to_bus(u32 *ptr, u32 length)
{
@@ -30,6 +30,7 @@ obj-$(CONFIG_FTMAC110) += ftmac110.o
obj-$(CONFIG_FTMAC100) += ftmac100.o
obj-$(CONFIG_GRETH) += greth.o
obj-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
+obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o
obj-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
obj-$(CONFIG_LAN91C96) += lan91c96.o
new file mode 100644
@@ -0,0 +1,857 @@
+/*
+ * Ethernet driver for TI K2HK EVM.
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <command.h>
+
+#include <net.h>
+#include <miiphy.h>
+#include <malloc.h>
+#include <asm/arch/emac_defs.h>
+#include <asm/arch/psc_defs.h>
+#include <asm/arch/keystone_nav.h>
+
+unsigned int emac_dbg;
+#define debug_emac(fmt, args...) if (emac_dbg) printf(fmt, ##args)
+
+unsigned int emac_open;
+static unsigned int sys_has_mdio = 1;
+
+#ifdef KEYSTONE2_EMAC_GIG_ENABLE
+#define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x)
+#else
+#define emac_gigabit_enable(x) /* no gigabit to enable */
+#endif
+
+#define RX_BUFF_NUMS 24
+#define RX_BUFF_LEN 1520
+#define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
+
+static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
+
+struct rx_buff_desc net_rx_buffs = {
+ .buff_ptr = rx_buffs,
+ .num_buffs = RX_BUFF_NUMS,
+ .buff_len = RX_BUFF_LEN,
+ .rx_flow = 22,
+};
+
+static void keystone2_eth_mdio_enable(void);
+
+static int gen_init_phy(int phy_addr);
+static int gen_is_phy_connected(int phy_addr);
+static int gen_get_link_speed(int phy_addr);
+static int gen_auto_negotiate(int phy_addr);
+
+static int marvell_88e1111_init_phy(int phy_addr);
+static int marvell_88e1111_is_phy_connected(int phy_addr);
+static int marvell_88e1111_get_link_speed(int phy_addr);
+static int marvell_88e1111_auto_negotiate(int phy_addr);
+
+/* EMAC Addresses */
+static volatile struct emac_regs *adap_emac =
+ (struct emac_regs *)EMAC_EMACSL_BASE_ADDR;
+static volatile struct mdio_regs *adap_mdio =
+ (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
+
+struct phy_t phy;
+
+static void chip_delay(u32 del)
+{
+ volatile unsigned int i;
+
+ for (i = 0; i < (del / 8); i++)
+ ;
+}
+
+int keystone2_eth_read_mac_addr(struct eth_device *dev)
+{
+ struct eth_priv_t *eth_priv;
+ u32 maca = 0;
+ u32 macb = 0;
+
+ eth_priv = (struct eth_priv_t *)dev->priv;
+
+ /* Read the e-fuse mac address */
+ if (eth_priv->slave_port == 1) {
+ maca = __raw_readl(MAC_ID_BASE_ADDR);
+ macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
+ }
+
+ dev->enetaddr[0] = (macb >> 8) & 0xff;
+ dev->enetaddr[1] = (macb >> 0) & 0xff;
+ dev->enetaddr[2] = (maca >> 24) & 0xff;
+ dev->enetaddr[3] = (maca >> 16) & 0xff;
+ dev->enetaddr[4] = (maca >> 8) & 0xff;
+ dev->enetaddr[5] = (maca >> 0) & 0xff;
+
+ return 0;
+}
+
+static void keystone2_eth_mdio_enable(void)
+{
+ u_int32_t clkdiv;
+
+ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+
+ writel((clkdiv & 0xffff) |
+ MDIO_CONTROL_ENABLE |
+ MDIO_CONTROL_FAULT |
+ MDIO_CONTROL_FAULT_ENABLE,
+ &adap_mdio->CONTROL);
+
+ while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE)
+ ;
+}
+
+/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
+int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+{
+ int tmp;
+
+ while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+ ;
+
+ writel(MDIO_USERACCESS0_GO |
+ MDIO_USERACCESS0_WRITE_READ |
+ ((reg_num & 0x1f) << 21) |
+ ((phy_addr & 0x1f) << 16),
+ &adap_mdio->USERACCESS0);
+
+ /* Wait for command to complete */
+ while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO)
+ ;
+
+ if (tmp & MDIO_USERACCESS0_ACK) {
+ *data = tmp & 0xffff;
+ return 0;
+ }
+
+ *data = -1;
+ return -1;
+}
+
+/* Write to a PHY register via MDIO inteface.
+ * Blocks until operation is complete. */
+int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+{
+ while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+ ;
+
+ writel(MDIO_USERACCESS0_GO |
+ MDIO_USERACCESS0_WRITE_WRITE |
+ ((reg_num & 0x1f) << 21) |
+ ((phy_addr & 0x1f) << 16) |
+ (data & 0xffff),
+ &adap_mdio->USERACCESS0);
+
+ /* Wait for command to complete */
+ while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+ ;
+
+ return 0;
+}
+
+/* PHY functions for a generic PHY */
+static int __attribute__((unused)) gen_init_phy(int phy_addr)
+{
+ int ret = -1;
+
+ if (!gen_get_link_speed(phy_addr)) {
+ /* Try another time */
+ ret = gen_get_link_speed(phy_addr);
+ }
+
+ return ret;
+}
+
+static int __attribute__((unused)) gen_is_phy_connected(int phy_addr)
+{
+ u_int16_t dummy;
+
+ return keystone2_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
+}
+
+static int gen_get_link_speed(int phy_addr)
+{
+ u_int16_t tmp;
+
+ if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
+ (tmp & 0x04)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+static int __attribute__((unused)) gen_auto_negotiate(int phy_addr)
+{
+ u_int16_t tmp;
+
+ if (keystone2_eth_phy_read(phy_addr, MII_BMCR, &tmp))
+ return -1;
+
+ /* Restart Auto_negotiation */
+ tmp |= BMCR_ANENABLE;
+ keystone2_eth_phy_write(phy_addr, MII_BMCR, tmp);
+
+ /*check AutoNegotiate complete */
+ udelay(10000);
+ if (keystone2_eth_phy_read(phy_addr, MII_BMSR, &tmp))
+ return -1;
+
+ if (!(tmp & BMSR_ANEGCOMPLETE))
+ return 0;
+
+ return gen_get_link_speed(phy_addr);
+}
+
+/* PHY functions for Marvell 88E1111 PHY */
+static int marvell_88e1111_init_phy(int phy_addr)
+{
+ int ret = -1;
+
+ if (!marvell_88e1111_get_link_speed(phy_addr)) {
+ /* Try another time */
+ ret = marvell_88e1111_get_link_speed(phy_addr);
+ }
+
+ return ret;
+}
+
+static int marvell_88e1111_is_phy_connected(int phy_addr)
+{
+ u_int16_t dummy;
+
+ return keystone2_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
+}
+
+static int marvell_88e1111_get_link_speed(int phy_addr)
+{
+ u_int16_t tmp;
+
+ if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
+ (tmp & MII_STATUS_LINK_MASK)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+static int marvell_88e1111_auto_negotiate(int phy_addr)
+{
+ u_int16_t tmp;
+
+ if (keystone2_eth_phy_read(phy_addr, MII_BMCR, &tmp))
+ return -1;
+
+ /* Restart Auto_negotiation */
+ tmp |= BMCR_ANENABLE;
+ keystone2_eth_phy_write(phy_addr, MII_BMCR, tmp);
+
+ /*check AutoNegotiate complete */
+ udelay(10000);
+ if (keystone2_eth_phy_read(phy_addr, MII_BMSR, &tmp))
+ return -1;
+
+ if (!(tmp & BMSR_ANEGCOMPLETE))
+ return 0;
+
+ return marvell_88e1111_get_link_speed(phy_addr);
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static int keystone2_mii_phy_read(const char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value)
+{
+ return keystone2_eth_phy_read(addr, reg, value) ? -1 : 0;
+}
+
+static int keystone2_mii_phy_write(const char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
+{
+ return keystone2_eth_phy_write(addr, reg, value) ? -1 : 0;
+}
+#endif
+
+static void __attribute__((unused))
+ keystone2_eth_gigabit_enable(struct eth_device *dev)
+{
+ u_int16_t data;
+ struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+ if (sys_has_mdio) {
+ if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) ||
+ !(data & (1 << 6))) /* speed selection MSB */
+ return;
+ }
+
+ /*
+ * Check if link detected is giga-bit
+ * If Gigabit mode detected, enable gigbit in MAC
+ */
+ writel(readl(&(adap_emac[eth_priv->slave_port - 1].MACCONTROL)) |
+ EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
+ &(adap_emac[eth_priv->slave_port - 1].MACCONTROL))
+ ;
+}
+
+int keystone_sgmii_link_status(int port)
+{
+ u32 status = 0;
+
+ status = __raw_readl(SGMII_STATUS_REG(port));
+
+ return status & SGMII_REG_STATUS_LINK;
+}
+
+
+int keystone_get_link_status(struct eth_device *dev)
+{
+ struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+ int sgmii_link;
+ int link_state = 0;
+#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
+ int j;
+
+ for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0);
+ j++) {
+#endif
+ sgmii_link =
+ keystone_sgmii_link_status(eth_priv->slave_port - 1);
+
+ if (sgmii_link) {
+ link_state = 1;
+
+ if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY)
+ if (phy.get_link_speed(eth_priv->phy_addr))
+ link_state = 0;
+ }
+#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
+ }
+#endif
+ return link_state;
+}
+
+int keystone_sgmii_config(int port, int interface)
+{
+ unsigned int i, status, mask;
+ unsigned int mr_adv_ability, control;
+
+ switch (interface) {
+ case SGMII_LINK_MAC_MAC_AUTONEG:
+ mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE |
+ SGMII_REG_MR_ADV_LINK |
+ SGMII_REG_MR_ADV_FULL_DUPLEX |
+ SGMII_REG_MR_ADV_GIG_MODE);
+ control = (SGMII_REG_CONTROL_MASTER |
+ SGMII_REG_CONTROL_AUTONEG);
+
+ break;
+ case SGMII_LINK_MAC_PHY:
+ case SGMII_LINK_MAC_PHY_FORCED:
+ mr_adv_ability = SGMII_REG_MR_ADV_ENABLE;
+ control = SGMII_REG_CONTROL_AUTONEG;
+
+ break;
+ case SGMII_LINK_MAC_MAC_FORCED:
+ mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE |
+ SGMII_REG_MR_ADV_LINK |
+ SGMII_REG_MR_ADV_FULL_DUPLEX |
+ SGMII_REG_MR_ADV_GIG_MODE);
+ control = SGMII_REG_CONTROL_MASTER;
+
+ break;
+ case SGMII_LINK_MAC_FIBER:
+ mr_adv_ability = 0x20;
+ control = SGMII_REG_CONTROL_AUTONEG;
+
+ break;
+ default:
+ mr_adv_ability = SGMII_REG_MR_ADV_ENABLE;
+ control = SGMII_REG_CONTROL_AUTONEG;
+ }
+
+ __raw_writel(0, SGMII_CTL_REG(port));
+
+ /*
+ * Wait for the SerDes pll to lock,
+ * but don't trap if lock is never read
+ */
+ for (i = 0; i < 1000; i++) {
+ udelay(2000);
+ status = __raw_readl(SGMII_STATUS_REG(port));
+ if ((status & SGMII_REG_STATUS_LOCK) != 0)
+ break;
+ }
+
+ __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port));
+ __raw_writel(control, SGMII_CTL_REG(port));
+
+
+ mask = SGMII_REG_STATUS_LINK;
+
+ if (control & SGMII_REG_CONTROL_AUTONEG)
+ mask |= SGMII_REG_STATUS_AUTONEG;
+
+ for (i = 0; i < 1000; i++) {
+ status = __raw_readl(SGMII_STATUS_REG(port));
+ if ((status & mask) == mask)
+ break;
+ }
+
+ return 0;
+}
+
+int mac_sl_reset(u32 port)
+{
+ u32 i, v;
+
+ if (port >= DEVICE_N_GMACSL_PORTS)
+ return GMACSL_RET_INVALID_PORT;
+
+ /* Set the soft reset bit */
+ DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) +
+ CPGMACSL_REG_RESET, CPGMAC_REG_RESET_VAL_RESET);
+
+ /* Wait for the bit to clear */
+ for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
+ v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) +
+ CPGMACSL_REG_RESET);
+ if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
+ CPGMAC_REG_RESET_VAL_RESET)
+ return GMACSL_RET_OK;
+ }
+
+ /* Timeout on the reset */
+ return GMACSL_RET_WARN_RESET_INCOMPLETE;
+}
+
+int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
+{
+ u32 v, i;
+ int ret = GMACSL_RET_OK;
+
+ if (port >= DEVICE_N_GMACSL_PORTS)
+ return GMACSL_RET_INVALID_PORT;
+
+ if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
+ cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
+ ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
+ }
+
+ /* Must wait if the device is undergoing reset */
+ for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
+ v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) +
+ CPGMACSL_REG_RESET);
+ if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
+ CPGMAC_REG_RESET_VAL_RESET)
+ break;
+ }
+
+ if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
+ return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE;
+
+ DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN,
+ cfg->max_rx_len);
+
+ DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL,
+ cfg->ctl);
+
+ return ret;
+}
+
+int ethss_config(u32 ctl, u32 max_pkt_size)
+{
+ u32 i;
+
+ /* Max length register */
+ DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_MAXLEN, max_pkt_size);
+
+ /* Control register */
+ DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_CTL, ctl);
+
+ /* All statistics enabled by default */
+ DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN,
+ CPSW_REG_VAL_STAT_ENABLE_ALL);
+
+ /* Reset and enable the ALE */
+ DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL,
+ CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
+ CPSW_REG_VAL_ALE_CTL_BYPASS);
+
+ /* All ports put into forward mode */
+ for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++)
+ DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i),
+ CPSW_REG_VAL_PORTCTL_FORWARD_MODE);
+
+ return 0;
+}
+
+int ethss_start(void)
+{
+ int i;
+ struct mac_sl_cfg cfg;
+
+ cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER;
+ cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL;
+
+ for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
+ mac_sl_reset(i);
+ mac_sl_config(i, &cfg);
+ }
+
+ return 0;
+}
+
+int ethss_stop(void)
+{
+ int i;
+
+ for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++)
+ mac_sl_reset(i);
+
+ return 0;
+}
+
+int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
+{
+ if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
+ num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
+
+ return netcp_send(buffer, num_bytes, (slave_port_num) << 16);
+}
+
+/* Eth device open */
+static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
+{
+ u_int32_t clkdiv;
+ int link;
+ struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+ debug_emac("+ emac_open\n");
+
+ net_rx_buffs.rx_flow = eth_priv->rx_flow;
+
+ sys_has_mdio =
+ (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
+
+ psc_enable_module(KS2_LPSC_PA);
+ psc_enable_module(KS2_LPSC_CPGMAC);
+
+ sgmii_serdes_setup_156p25mhz();
+
+ if (sys_has_mdio)
+ keystone2_eth_mdio_enable();
+
+ keystone_sgmii_config(eth_priv->slave_port - 1,
+ eth_priv->sgmii_link_type);
+
+ udelay(10000);
+
+ /* On chip switch configuration */
+ ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
+
+ /* TODO: add error handling code */
+ if (qm_init()) {
+ printf("ERROR: qm_init()\n");
+ return -1;
+ }
+ if (netcp_init(&net_rx_buffs)) {
+ qm_close();
+ printf("ERROR: netcp_init()\n");
+ return -1;
+ }
+
+ /*
+ * Streaming switch configuration. If not present this
+ * statement is defined to void in target.h.
+ * If present this is usually defined to a series of register writes
+ */
+ hw_config_streaming_switch();
+
+ if (sys_has_mdio) {
+ /* Init MDIO & get link state */
+ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+ writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE |
+ MDIO_CONTROL_FAULT, &adap_mdio->CONTROL)
+ ;
+
+ /* We need to wait for MDIO to start */
+ udelay(1000);
+
+ link = keystone_get_link_status(dev);
+ if (link == 0) {
+ netcp_close();
+ qm_close();
+ return -1;
+ }
+ }
+
+ emac_gigabit_enable(dev);
+
+ ethss_start();
+
+ debug_emac("- emac_open\n");
+
+ emac_open = 1;
+
+ return 0;
+}
+
+/* Eth device close */
+void keystone2_eth_close(struct eth_device *dev)
+{
+ debug_emac("+ emac_close\n");
+
+ if (!emac_open)
+ return;
+
+ ethss_stop();
+
+ netcp_close();
+ qm_close();
+
+ emac_open = 0;
+
+ debug_emac("- emac_close\n");
+}
+
+static int tx_send_loop;
+
+/*
+ * This function sends a single packet on the network and returns
+ * positive number (number of bytes transmitted) or negative for error
+ */
+static int keystone2_eth_send_packet(struct eth_device *dev,
+ void *packet, int length)
+{
+ int ret_status = -1;
+ struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+ tx_send_loop = 0;
+
+ if (keystone_get_link_status(dev) == 0)
+ return -1;
+
+ emac_gigabit_enable(dev);
+
+ if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
+ return ret_status;
+
+ if (keystone_get_link_status(dev) == 0)
+ return -1;
+
+ emac_gigabit_enable(dev);
+
+ return length;
+}
+
+/*
+ * This function handles receipt of a packet from the network
+ */
+static int keystone2_eth_rcv_packet(struct eth_device *dev)
+{
+ void *hd;
+ int pkt_size;
+ u32 *pkt;
+
+ hd = netcp_recv(&pkt, &pkt_size);
+ if (hd == NULL)
+ return 0;
+
+ NetReceive((uchar *)pkt, pkt_size);
+
+ netcp_release_rxhd(hd);
+
+ return pkt_size;
+}
+
+/*
+ * This function initializes the EMAC hardware. It does NOT initialize
+ * EMAC modules power or pin multiplexors, that is done by board_init()
+ * much earlier in bootup process. Returns 1 on success, 0 otherwise.
+ */
+int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
+{
+ struct eth_device *dev;
+ static int phy_registered;
+
+ dev = malloc(sizeof(struct eth_device));
+ if (dev == NULL)
+ return -1;
+
+ memset(dev, 0, sizeof(struct eth_device));
+
+ strcpy(dev->name, eth_priv->int_name);
+ dev->priv = eth_priv;
+
+ keystone2_eth_read_mac_addr(dev);
+
+ dev->iobase = 0;
+ dev->init = keystone2_eth_open;
+ dev->halt = keystone2_eth_close;
+ dev->send = keystone2_eth_send_packet;
+ dev->recv = keystone2_eth_rcv_packet;
+
+ eth_register(dev);
+
+ if (sys_has_mdio && !phy_registered) {
+ phy_registered = 1;
+#ifdef CONFIG_ETH_PHY_MARVEL_88E1111
+ sprintf(phy.name, "88E1111");
+ phy.init = marvell_88e1111_init_phy;
+ phy.is_phy_connected = marvell_88e1111_is_phy_connected;
+ phy.get_link_speed = marvell_88e1111_get_link_speed;
+ phy.auto_negotiate = marvell_88e1111_auto_negotiate;
+#else
+ sprintf(phy.name, "GENERIC");
+ phy.init = gen_init_phy;
+ phy.is_phy_connected = gen_is_phy_connected;
+ phy.get_link_speed = gen_get_link_speed;
+ phy.auto_negotiate = gen_auto_negotiate;
+#endif
+ miiphy_register(phy.name, keystone2_mii_phy_read,
+ keystone2_mii_phy_write);
+ }
+
+ return 0;
+}
+
+#define reg_rmw(addr, value, mask) \
+ writel(((readl(addr) & (~(mask))) | (value)), (addr))
+
+void sgmii_serdes_setup_156p25mhz()
+{
+ unsigned int cnt;
+
+ reg_rmw(0x0232a000, 0x00800000, 0xffff0000);
+ reg_rmw(0x0232a014, 0x00008282, 0x0000ffff);
+ reg_rmw(0x0232a060, 0x00142438, 0x00ffffff);
+ reg_rmw(0x0232a064, 0x00c3c700, 0x00ffff00);
+ reg_rmw(0x0232a078, 0x0000c000, 0x0000ff00);
+
+ reg_rmw(0x0232a204, 0x38000080, 0xff0000ff);
+ reg_rmw(0x0232a208, 0x00000000, 0x000000ff);
+ reg_rmw(0x0232a20c, 0x02000000, 0xff000000);
+ reg_rmw(0x0232a210, 0x1b000000, 0xff000000);
+ reg_rmw(0x0232a214, 0x00006fb8, 0x0000ffff);
+ reg_rmw(0x0232a218, 0x758000e4, 0xffff00ff);
+ reg_rmw(0x0232a2ac, 0x00004400, 0x0000ff00);
+ reg_rmw(0x0232a22c, 0x00200800, 0x00ffff00);
+ reg_rmw(0x0232a280, 0x00820082, 0x00ff00ff);
+ reg_rmw(0x0232a284, 0x1d0f0385, 0xffffffff);
+
+ reg_rmw(0x0232a404, 0x38000080, 0xff0000ff);
+ reg_rmw(0x0232a408, 0x00000000, 0x000000ff);
+ reg_rmw(0x0232a40c, 0x02000000, 0xff000000);
+ reg_rmw(0x0232a410, 0x1b000000, 0xff000000);
+ reg_rmw(0x0232a414, 0x00006fb8, 0x0000ffff);
+ reg_rmw(0x0232a418, 0x758000e4, 0xffff00ff);
+ reg_rmw(0x0232a4ac, 0x00004400, 0x0000ff00);
+ reg_rmw(0x0232a42c, 0x00200800, 0x00ffff00);
+ reg_rmw(0x0232a480, 0x00820082, 0x00ff00ff);
+ reg_rmw(0x0232a484, 0x1d0f0385, 0xffffffff);
+
+ reg_rmw(0x0232a604, 0x38000080, 0xff0000ff);
+ reg_rmw(0x0232a608, 0x00000000, 0x000000ff);
+ reg_rmw(0x0232a60c, 0x02000000, 0xff000000);
+ reg_rmw(0x0232a610, 0x1b000000, 0xff000000);
+ reg_rmw(0x0232a614, 0x00006fb8, 0x0000ffff);
+ reg_rmw(0x0232a618, 0x758000e4, 0xffff00ff);
+ reg_rmw(0x0232a6ac, 0x00004400, 0x0000ff00);
+ reg_rmw(0x0232a62c, 0x00200800, 0x00ffff00);
+ reg_rmw(0x0232a680, 0x00820082, 0x00ff00ff);
+ reg_rmw(0x0232a684, 0x1d0f0385, 0xffffffff);
+
+ reg_rmw(0x0232a804, 0x38000080, 0xff0000ff);
+ reg_rmw(0x0232a808, 0x00000000, 0x000000ff);
+ reg_rmw(0x0232a80c, 0x02000000, 0xff000000);
+ reg_rmw(0x0232a810, 0x1b000000, 0xff000000);
+ reg_rmw(0x0232a814, 0x00006fb8, 0x0000ffff);
+ reg_rmw(0x0232a818, 0x758000e4, 0xffff00ff);
+ reg_rmw(0x0232a8ac, 0x00004400, 0x0000ff00);
+ reg_rmw(0x0232a82c, 0x00200800, 0x00ffff00);
+ reg_rmw(0x0232a880, 0x00820082, 0x00ff00ff);
+ reg_rmw(0x0232a884, 0x1d0f0385, 0xffffffff);
+
+ reg_rmw(0x0232aa00, 0x00000800, 0x0000ff00);
+ reg_rmw(0x0232aa08, 0x38a20000, 0xffff0000);
+ reg_rmw(0x0232aa30, 0x008a8a00, 0x00ffff00);
+ reg_rmw(0x0232aa84, 0x00000600, 0x0000ff00);
+ reg_rmw(0x0232aa94, 0x10000000, 0xff000000);
+ reg_rmw(0x0232aaa0, 0x81000000, 0xff000000);
+ reg_rmw(0x0232aabc, 0xff000000, 0xff000000);
+ reg_rmw(0x0232aac0, 0x0000008b, 0x000000ff);
+ reg_rmw(0x0232ab08, 0x583f0000, 0xffff0000);
+ reg_rmw(0x0232ab0c, 0x0000004e, 0x000000ff);
+ reg_rmw(0x0232a000, 0x00000003, 0x000000ff);
+ reg_rmw(0x0232aa00, 0x0000005f, 0x000000ff);
+
+ reg_rmw(0x0232aa48, 0x00fd8c00, 0x00ffff00);
+ reg_rmw(0x0232aa54, 0x002fec72, 0x00ffffff);
+ reg_rmw(0x0232aa58, 0x00f92100, 0xffffff00);
+ reg_rmw(0x0232aa5c, 0x00040060, 0xffffffff);
+ reg_rmw(0x0232aa60, 0x00008000, 0xffffffff);
+ reg_rmw(0x0232aa64, 0x0c581220, 0xffffffff);
+ reg_rmw(0x0232aa68, 0xe13b0602, 0xffffffff);
+ reg_rmw(0x0232aa6c, 0xb8074cc1, 0xffffffff);
+ reg_rmw(0x0232aa70, 0x3f02e989, 0xffffffff);
+ reg_rmw(0x0232aa74, 0x00000001, 0x000000ff);
+ reg_rmw(0x0232ab20, 0x00370000, 0x00ff0000);
+ reg_rmw(0x0232ab1c, 0x37000000, 0xff000000);
+ reg_rmw(0x0232ab20, 0x0000005d, 0x000000ff);
+
+ /*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/
+ reg_rmw(0x0232a010, 0x00000000, 1 << 28);
+
+ /* Enable TX and RX via the LANExCTL_STS 0x0000 + x*4 */
+ reg_rmw(0x0232a228, 0x00000000, 1 << 29);
+ writel(0xF800F8C0, 0x0232bfe0);
+ reg_rmw(0x0232a428, 0x00000000, 1 << 29);
+ writel(0xF800F8C0, 0x0232bfe4);
+ reg_rmw(0x0232a628, 0x00000000, 1 << 29);
+ writel(0xF800F8C0, 0x0232bfe8);
+ reg_rmw(0x0232a828, 0x00000000, 1 << 29);
+ writel(0xF800F8C0, 0x0232bfec);
+
+ /*Enable pll via the pll_ctrl 0x0014*/
+ writel(0xe0000000, 0x0232bff4)
+ ;
+
+ /*Waiting for SGMII Serdes PLL lock.*/
+ for (cnt = 10000; cnt > 0 && ((readl(0x02090114) & 0x10) == 0); cnt--)
+ ;
+
+ for (cnt = 10000; cnt > 0 && ((readl(0x02090214) & 0x10) == 0); cnt--)
+ ;
+
+ for (cnt = 10000; cnt > 0 && ((readl(0x02090414) & 0x10) == 0); cnt--)
+ ;
+
+ for (cnt = 10000; cnt > 0 && ((readl(0x02090514) & 0x10) == 0); cnt--)
+ ;
+
+ chip_delay(45000);
+}
+
+void sgmii_serdes_shutdown()
+{
+ reg_rmw(0x0232bfe0, 0, 3 << 29 | 3 << 13);
+ reg_rmw(0x02320228, 1 << 29, 1 << 29);
+ reg_rmw(0x0232bfe4, 0, 3 << 29 | 3 << 13);
+ reg_rmw(0x02320428, 1 << 29, 1 << 29);
+ reg_rmw(0x0232bfe8, 0, 3 << 29 | 3 << 13);
+ reg_rmw(0x02320628, 1 << 29, 1 << 29);
+ reg_rmw(0x0232bfec, 0, 3 << 29 | 3 << 13);
+ reg_rmw(0x02320828, 1 << 29, 1 << 29);
+
+ reg_rmw(0x02320034, 0, 3 << 29);
+ reg_rmw(0x02320010, 1 << 28, 1 << 28);
+}
+
@@ -106,6 +106,23 @@
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 20
#define CONFIG_ENV_EEPROM_IS_ON_I2C
+/* Network Configuration */
+#define CONFIG_ETH_PHY_MARVEL_88E1111
+
+#define CONFIG_DRIVER_TI_KEYSTONE_NET
+#define CONFIG_MII
+#define CONFIG_BOOTP_DEFAULT
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_NET_RETRY_COUNT 32
+#define CONFIG_NET_MULTI
+#define CONFIG_GET_LINK_STATUS_ATTEMPTS 5
+
+#define CONFIG_SYS_SGMII_REFCLK_MHZ 312
+#define CONFIG_SYS_SGMII_LINERATE_MHZ 1250
+#define CONFIG_SYS_SGMII_RATESCALE 2
+
/* NAND Configuration */
#define CONFIG_NAND_DAVINCI
#define CONFIG_SYS_NAND_CS 2
@@ -179,24 +196,45 @@
"addr_fs=0x82000000\0" \
"addr_ubi=0x82000000\0" \
"fdt_high=0xffffffff\0" \
+ "name_fdt=uImage-k2hk-evm.dtb\0" \
+ "name_fs=arago-console-image.cpio.gz\0" \
+ "name_kern=uImage-keystone-evm.bin\0" \
+ "name_mon=skern-keystone-evm.bin\0" \
+ "name_uboot=u-boot-spi-keystone-evm.gph\0" \
+ "name_ubi=keystone-evm-ubifs.ubi\0" \
"run_mon=mon_install ${addr_mon}\0" \
"run_kern=bootm ${addr_kern} - ${addr_fdt}\0" \
+ "init_net=run args_all args_net\0" \
"init_ubi=run args_all args_ubi; " \
"ubi part ubifs; ubifsmount boot\0" \
+ "get_fdt_net=dhcp ${addr_fdt} ${tftp_root}/${name_fdt}\0" \
"get_fdt_ubi=ubifsload ${addr_fdt} ${name_fdt}\0" \
+ "get_kern_net=dhcp ${addr_kern} ${tftp_root}/${name_kern}\0" \
"get_kern_ubi=ubifsload ${addr_kern} ${name_kern}\0" \
+ "get_mon_net=dhcp ${addr_mon} ${tftp_root}/${name_mon}\0" \
"get_mon_ubi=ubifsload ${addr_mon} ${name_mon}\0" \
+ "get_uboot_net=dhcp ${addr_uboot} ${tftp_root}/${name_uboot}\0" \
"burn_uboot=sf probe; sf erase 0 0x100000; " \
"sf write ${addr_uboot} 0 ${filesize}\0" \
"args_all=setenv bootargs console=ttyS0,115200n8 rootwait=1\0" \
"args_ubi=setenv bootargs ${bootargs} rootfstype=ubifs " \
"root=ubi0:rootfs rootflags=sync rw ubi.mtd=2,2048\0" \
+ "args_net=setenv bootargs ${bootargs} rootfstype=nfs " \
+ "root=/dev/nfs rw nfsroot=${serverip}:${nfs_root}," \
+ "${nfs_options} ip=dhcp\0" \
+ "nfs_options=v3,tcp,rsize=4096,wsize=4096\0" \
+ "get_fdt_ramfs=dhcp ${addr_fdt} ${tftp_root}/${name_fdt}\0" \
+ "get_kern_ramfs=dhcp ${addr_kern} ${tftp_root}/${name_kern}\0" \
+ "get_mon_ramfs=dhcp ${addr_mon} ${tftp_root}/${name_mon}\0" \
+ "get_fs_ramfs=dhcp ${addr_fs} ${tftp_root}/${name_fs}\0" \
+ "get_ubi_net=dhcp ${addr_ubi} ${tftp_root}/${name_ubi}\0" \
"burn_ubi=nand erase.part ubifs; " \
"nand write ${addr_ubi} ubifs ${filesize}\0" \
"init_ramfs=run args_all args_ramfs get_fs_ramfs\0" \
"args_ramfs=setenv bootargs ${bootargs} earlyprintk " \
"rdinit=/sbin/init rw root=/dev/ram0 " \
"initrd=0x802000000,9M\0" \
+ "no_post=1\0" \
"mtdparts=mtdparts=davinci_nand.0:" \
"1024k(bootloader)ro,512k(params)ro,522752k(ubifs)\0"
#define CONFIG_BOOTCOMMAND \