dwmac1000_core.c revision 2e19a3818bd6438213e312fce14af6217a5a749b
1/*******************************************************************************
2  This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
3  DWC Ether MAC 10/100/1000 Universal version 3.41a  has been used for
4  developing this code.
5
6  This only implements the mac core functions for this chip.
7
8  Copyright (C) 2007-2009  STMicroelectronics Ltd
9
10  This program is free software; you can redistribute it and/or modify it
11  under the terms and conditions of the GNU General Public License,
12  version 2, as published by the Free Software Foundation.
13
14  This program is distributed in the hope it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  more details.
18
19  You should have received a copy of the GNU General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc.,
21  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22
23  The full GNU General Public License is included in this distribution in
24  the file called "COPYING".
25
26  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
27*******************************************************************************/
28
29#include <linux/crc32.h>
30#include <linux/slab.h>
31#include <asm/io.h>
32#include "dwmac1000.h"
33
34static void dwmac1000_core_init(void __iomem *ioaddr)
35{
36	u32 value = readl(ioaddr + GMAC_CONTROL);
37	value |= GMAC_CORE_INIT;
38	writel(value, ioaddr + GMAC_CONTROL);
39
40	/* Freeze MMC counters */
41	writel(0x8, ioaddr + GMAC_MMC_CTRL);
42	/* Mask GMAC interrupts */
43	writel(0x207, ioaddr + GMAC_INT_MASK);
44
45#ifdef STMMAC_VLAN_TAG_USED
46	/* Tag detection without filtering */
47	writel(0x0, ioaddr + GMAC_VLAN_TAG);
48#endif
49}
50
51static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
52{
53	u32 value = readl(ioaddr + GMAC_CONTROL);
54
55	value |= GMAC_CONTROL_IPC;
56	writel(value, ioaddr + GMAC_CONTROL);
57
58	value = readl(ioaddr + GMAC_CONTROL);
59
60	return !!(value & GMAC_CONTROL_IPC);
61}
62
63static void dwmac1000_dump_regs(void __iomem *ioaddr)
64{
65	int i;
66	pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
67
68	for (i = 0; i < 55; i++) {
69		int offset = i * 4;
70		pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
71			offset, readl(ioaddr + offset));
72	}
73}
74
75static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
76				unsigned int reg_n)
77{
78	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
79				GMAC_ADDR_LOW(reg_n));
80}
81
82static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
83				unsigned int reg_n)
84{
85	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
86				GMAC_ADDR_LOW(reg_n));
87}
88
89static void dwmac1000_set_filter(struct net_device *dev)
90{
91	void __iomem *ioaddr = (void __iomem *) dev->base_addr;
92	unsigned int value = 0;
93
94	CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
95		 __func__, netdev_mc_count(dev), netdev_uc_count(dev));
96
97	if (dev->flags & IFF_PROMISC)
98		value = GMAC_FRAME_FILTER_PR;
99	else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
100		   || (dev->flags & IFF_ALLMULTI)) {
101		value = GMAC_FRAME_FILTER_PM;	/* pass all multi */
102		writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
103		writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
104	} else if (!netdev_mc_empty(dev)) {
105		u32 mc_filter[2];
106		struct netdev_hw_addr *ha;
107
108		/* Hash filter for multicast */
109		value = GMAC_FRAME_FILTER_HMC;
110
111		memset(mc_filter, 0, sizeof(mc_filter));
112		netdev_for_each_mc_addr(ha, dev) {
113			/* The upper 6 bits of the calculated CRC are used to
114			   index the contens of the hash table */
115			int bit_nr =
116			    bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26;
117			/* The most significant bit determines the register to
118			 * use (H/L) while the other 5 bits determine the bit
119			 * within the register. */
120			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
121		}
122		writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
123		writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
124	}
125
126	/* Handle multiple unicast addresses (perfect filtering)*/
127	if (netdev_uc_count(dev) > GMAC_MAX_UNICAST_ADDRESSES)
128		/* Switch to promiscuous mode is more than 16 addrs
129		   are required */
130		value |= GMAC_FRAME_FILTER_PR;
131	else {
132		int reg = 1;
133		struct netdev_hw_addr *ha;
134
135		netdev_for_each_uc_addr(ha, dev) {
136			dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
137			reg++;
138		}
139	}
140
141#ifdef FRAME_FILTER_DEBUG
142	/* Enable Receive all mode (to debug filtering_fail errors) */
143	value |= GMAC_FRAME_FILTER_RA;
144#endif
145	writel(value, ioaddr + GMAC_FRAME_FILTER);
146
147	CHIP_DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: "
148	    "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER),
149	    readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
150}
151
152static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
153			   unsigned int fc, unsigned int pause_time)
154{
155	unsigned int flow = 0;
156
157	CHIP_DBG(KERN_DEBUG "GMAC Flow-Control:\n");
158	if (fc & FLOW_RX) {
159		CHIP_DBG(KERN_DEBUG "\tReceive Flow-Control ON\n");
160		flow |= GMAC_FLOW_CTRL_RFE;
161	}
162	if (fc & FLOW_TX) {
163		CHIP_DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n");
164		flow |= GMAC_FLOW_CTRL_TFE;
165	}
166
167	if (duplex) {
168		CHIP_DBG(KERN_DEBUG "\tduplex mode: PAUSE %d\n", pause_time);
169		flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
170	}
171
172	writel(flow, ioaddr + GMAC_FLOW_CTRL);
173}
174
175static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
176{
177	unsigned int pmt = 0;
178
179	if (mode & WAKE_MAGIC) {
180		CHIP_DBG(KERN_DEBUG "GMAC: WOL Magic frame\n");
181		pmt |= power_down | magic_pkt_en;
182	}
183	if (mode & WAKE_UCAST) {
184		CHIP_DBG(KERN_DEBUG "GMAC: WOL on global unicast\n");
185		pmt |= global_unicast;
186	}
187
188	writel(pmt, ioaddr + GMAC_PMT);
189}
190
191
192static void dwmac1000_irq_status(void __iomem *ioaddr)
193{
194	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
195
196	/* Not used events (e.g. MMC interrupts) are not handled. */
197	if ((intr_status & mmc_tx_irq))
198		CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
199		    readl(ioaddr + GMAC_MMC_TX_INTR));
200	if (unlikely(intr_status & mmc_rx_irq))
201		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
202		    readl(ioaddr + GMAC_MMC_RX_INTR));
203	if (unlikely(intr_status & mmc_rx_csum_offload_irq))
204		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
205		    readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
206	if (unlikely(intr_status & pmt_irq)) {
207		CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
208		/* clear the PMT bits 5 and 6 by reading the PMT
209		 * status register. */
210		readl(ioaddr + GMAC_PMT);
211	}
212}
213
214static const struct stmmac_ops dwmac1000_ops = {
215	.core_init = dwmac1000_core_init,
216	.rx_coe = dwmac1000_rx_coe_supported,
217	.dump_regs = dwmac1000_dump_regs,
218	.host_irq_status = dwmac1000_irq_status,
219	.set_filter = dwmac1000_set_filter,
220	.flow_ctrl = dwmac1000_flow_ctrl,
221	.pmt = dwmac1000_pmt,
222	.set_umac_addr = dwmac1000_set_umac_addr,
223	.get_umac_addr = dwmac1000_get_umac_addr,
224};
225
226struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
227{
228	struct mac_device_info *mac;
229	u32 uid = readl(ioaddr + GMAC_VERSION);
230
231	pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n",
232		((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));
233
234	mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
235	if (!mac)
236		return NULL;
237
238	mac->mac = &dwmac1000_ops;
239	mac->dma = &dwmac1000_dma_ops;
240
241	mac->link.port = GMAC_CONTROL_PS;
242	mac->link.duplex = GMAC_CONTROL_DM;
243	mac->link.speed = GMAC_CONTROL_FES;
244	mac->mii.addr = GMAC_MII_ADDR;
245	mac->mii.data = GMAC_MII_DATA;
246
247	return mac;
248}
249