1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2009-2011 Freescale Semiconductor, Inc.
4 */
5
6#include <common.h>
7#include <asm/types.h>
8#include <asm/io.h>
9#include <fsl_dtsec.h>
10#include <fsl_mdio.h>
11#include <phy.h>
12#include <linux/delay.h>
13
14#include "fm.h"
15
16#define RCTRL_INIT	(RCTRL_GRS | RCTRL_UPROM)
17#define TCTRL_INIT	TCTRL_GTS
18#define MACCFG1_INIT	MACCFG1_SOFT_RST
19
20#define MACCFG2_INIT	(MACCFG2_PRE_LEN(0x7) | MACCFG2_LEN_CHECK | \
21			 MACCFG2_PAD_CRC | MACCFG2_FULL_DUPLEX | \
22			 MACCFG2_IF_MODE_NIBBLE)
23
24/* MAXFRM - maximum frame length register */
25#define MAXFRM_MASK		0x00003fff
26
27static void dtsec_init_mac(struct fsl_enet_mac *mac)
28{
29	struct dtsec *regs = mac->base;
30
31	/* soft reset */
32	out_be32(&regs->maccfg1, MACCFG1_SOFT_RST);
33	udelay(1000);
34
35	/* clear soft reset, Rx/Tx MAC disable */
36	out_be32(&regs->maccfg1, 0);
37
38	/* graceful stop rx */
39	out_be32(&regs->rctrl, RCTRL_INIT);
40	udelay(1000);
41
42	/* graceful stop tx */
43	out_be32(&regs->tctrl, TCTRL_INIT);
44	udelay(1000);
45
46	/* disable all interrupts */
47	out_be32(&regs->imask, IMASK_MASK_ALL);
48
49	/* clear all events */
50	out_be32(&regs->ievent, IEVENT_CLEAR_ALL);
51
52	/* set the max Rx length */
53	out_be32(&regs->maxfrm, mac->max_rx_len & MAXFRM_MASK);
54
55	/* set the ecntrl to reset value */
56	out_be32(&regs->ecntrl, ECNTRL_DEFAULT);
57
58	/*
59	 * Rx length check, no strip CRC for Rx, pad and append CRC for Tx,
60	 * full duplex
61	 */
62	out_be32(&regs->maccfg2, MACCFG2_INIT);
63}
64
65static void dtsec_enable_mac(struct fsl_enet_mac *mac)
66{
67	struct dtsec *regs = mac->base;
68
69	/* enable Rx/Tx MAC */
70	setbits_be32(&regs->maccfg1, MACCFG1_RXTX_EN);
71
72	/* clear the graceful Rx stop */
73	clrbits_be32(&regs->rctrl, RCTRL_GRS);
74
75	/* clear the graceful Tx stop */
76	clrbits_be32(&regs->tctrl, TCTRL_GTS);
77}
78
79static void dtsec_disable_mac(struct fsl_enet_mac *mac)
80{
81	struct dtsec *regs = mac->base;
82
83	/* graceful Rx stop */
84	setbits_be32(&regs->rctrl, RCTRL_GRS);
85
86	/* graceful Tx stop */
87	setbits_be32(&regs->tctrl, TCTRL_GTS);
88
89	/* disable Rx/Tx MAC */
90	clrbits_be32(&regs->maccfg1, MACCFG1_RXTX_EN);
91}
92
93static void dtsec_set_mac_addr(struct fsl_enet_mac *mac, u8 *mac_addr)
94{
95	struct dtsec *regs = mac->base;
96	u32 mac_addr1, mac_addr2;
97
98	/*
99	 * if a station address of 0x12345678ABCD, perform a write to
100	 * MACSTNADDR1 of 0xCDAB7856, MACSTNADDR2 of 0x34120000
101	 */
102	mac_addr1 = (mac_addr[5] << 24) | (mac_addr[4] << 16) | \
103			(mac_addr[3] << 8)  | (mac_addr[2]);
104	out_be32(&regs->macstnaddr1, mac_addr1);
105
106	mac_addr2 = ((mac_addr[1] << 24) | (mac_addr[0] << 16)) & 0xffff0000;
107	out_be32(&regs->macstnaddr2, mac_addr2);
108}
109
110static void dtsec_set_interface_mode(struct fsl_enet_mac *mac,
111		phy_interface_t type, int speed)
112{
113	struct dtsec *regs = mac->base;
114	u32 ecntrl, maccfg2;
115
116	/* clear all bits relative with interface mode */
117	ecntrl = in_be32(&regs->ecntrl);
118	ecntrl &= ~(ECNTRL_TBIM | ECNTRL_GMIIM | ECNTRL_RPM |
119				  ECNTRL_R100M | ECNTRL_SGMIIM);
120
121	maccfg2 = in_be32(&regs->maccfg2);
122	maccfg2 &= ~MACCFG2_IF_MODE_MASK;
123
124	if (speed == SPEED_1000)
125		maccfg2 |= MACCFG2_IF_MODE_BYTE;
126	else
127		maccfg2 |= MACCFG2_IF_MODE_NIBBLE;
128
129	/* set interface mode */
130	switch (type) {
131	case PHY_INTERFACE_MODE_GMII:
132		ecntrl |= ECNTRL_GMIIM;
133		break;
134	case PHY_INTERFACE_MODE_RGMII:
135		ecntrl |= (ECNTRL_GMIIM | ECNTRL_RPM);
136		if (speed == SPEED_100)
137			ecntrl |= ECNTRL_R100M;
138		break;
139	case PHY_INTERFACE_MODE_RMII:
140		if (speed == SPEED_100)
141			ecntrl |= ECNTRL_R100M;
142		break;
143	case PHY_INTERFACE_MODE_SGMII:
144		ecntrl |= (ECNTRL_SGMIIM | ECNTRL_TBIM);
145		if (speed == SPEED_100)
146			ecntrl |= ECNTRL_R100M;
147		break;
148	default:
149		break;
150	}
151
152	out_be32(&regs->ecntrl, ecntrl);
153	out_be32(&regs->maccfg2, maccfg2);
154}
155
156void init_dtsec(struct fsl_enet_mac *mac, void *base,
157		void *phyregs, int max_rx_len)
158{
159	mac->base = base;
160	mac->phyregs = phyregs;
161	mac->max_rx_len = max_rx_len;
162	mac->init_mac = dtsec_init_mac;
163	mac->enable_mac = dtsec_enable_mac;
164	mac->disable_mac = dtsec_disable_mac;
165	mac->set_mac_addr = dtsec_set_mac_addr;
166	mac->set_if_mode = dtsec_set_interface_mode;
167}
168