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 "dwmac1000.h"
32 
dwmac1000_core_init(void __iomem * ioaddr)33 static void dwmac1000_core_init(void __iomem *ioaddr)
34 {
35 	u32 value = readl(ioaddr + GMAC_CONTROL);
36 	value |= GMAC_CORE_INIT;
37 	writel(value, ioaddr + GMAC_CONTROL);
38 
39 	/* STBus Bridge Configuration */
40 	/*writel(0xc5608, ioaddr + 0x00007000);*/
41 
42 	/* Freeze MMC counters */
43 	writel(0x8, ioaddr + GMAC_MMC_CTRL);
44 	/* Mask GMAC interrupts */
45 	writel(0x207, ioaddr + GMAC_INT_MASK);
46 
47 #ifdef STMMAC_VLAN_TAG_USED
48 	/* Tag detection without filtering */
49 	writel(0x0, ioaddr + GMAC_VLAN_TAG);
50 #endif
51 }
52 
dwmac1000_rx_coe_supported(void __iomem * ioaddr)53 static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
54 {
55 	u32 value = readl(ioaddr + GMAC_CONTROL);
56 
57 	value |= GMAC_CONTROL_IPC;
58 	writel(value, ioaddr + GMAC_CONTROL);
59 
60 	value = readl(ioaddr + GMAC_CONTROL);
61 
62 	return !!(value & GMAC_CONTROL_IPC);
63 }
64 
dwmac1000_dump_regs(void __iomem * ioaddr)65 static void dwmac1000_dump_regs(void __iomem *ioaddr)
66 {
67 	int i;
68 	pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
69 
70 	for (i = 0; i < 55; i++) {
71 		int offset = i * 4;
72 		pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
73 			offset, readl(ioaddr + offset));
74 	}
75 }
76 
dwmac1000_set_umac_addr(void __iomem * ioaddr,unsigned char * addr,unsigned int reg_n)77 static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
78 				unsigned int reg_n)
79 {
80 	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
81 				GMAC_ADDR_LOW(reg_n));
82 }
83 
dwmac1000_get_umac_addr(void __iomem * ioaddr,unsigned char * addr,unsigned int reg_n)84 static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
85 				unsigned int reg_n)
86 {
87 	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
88 				GMAC_ADDR_LOW(reg_n));
89 }
90 
dwmac1000_set_filter(struct net_device * dev)91 static void dwmac1000_set_filter(struct net_device *dev)
92 {
93 	void __iomem *ioaddr = (void __iomem *) dev->base_addr;
94 	unsigned int value = 0;
95 
96 	CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
97 		 __func__, netdev_mc_count(dev), netdev_uc_count(dev));
98 
99 	if (dev->flags & IFF_PROMISC)
100 		value = GMAC_FRAME_FILTER_PR;
101 	else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
102 		   || (dev->flags & IFF_ALLMULTI)) {
103 		value = GMAC_FRAME_FILTER_PM;	/* pass all multi */
104 		writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
105 		writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
106 	} else if (!netdev_mc_empty(dev)) {
107 		u32 mc_filter[2];
108 		struct netdev_hw_addr *ha;
109 
110 		/* Hash filter for multicast */
111 		value = GMAC_FRAME_FILTER_HMC;
112 
113 		memset(mc_filter, 0, sizeof(mc_filter));
114 		netdev_for_each_mc_addr(ha, dev) {
115 			/* The upper 6 bits of the calculated CRC are used to
116 			   index the contens of the hash table */
117 			int bit_nr =
118 			    bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26;
119 			/* The most significant bit determines the register to
120 			 * use (H/L) while the other 5 bits determine the bit
121 			 * within the register. */
122 			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
123 		}
124 		writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
125 		writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
126 	}
127 
128 	/* Handle multiple unicast addresses (perfect filtering)*/
129 	if (netdev_uc_count(dev) > GMAC_MAX_UNICAST_ADDRESSES)
130 		/* Switch to promiscuous mode is more than 16 addrs
131 		   are required */
132 		value |= GMAC_FRAME_FILTER_PR;
133 	else {
134 		int reg = 1;
135 		struct netdev_hw_addr *ha;
136 
137 		netdev_for_each_uc_addr(ha, dev) {
138 			dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
139 			reg++;
140 		}
141 	}
142 
143 #ifdef FRAME_FILTER_DEBUG
144 	/* Enable Receive all mode (to debug filtering_fail errors) */
145 	value |= GMAC_FRAME_FILTER_RA;
146 #endif
147 	writel(value, ioaddr + GMAC_FRAME_FILTER);
148 
149 	CHIP_DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: "
150 	    "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER),
151 	    readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
152 }
153 
dwmac1000_flow_ctrl(void __iomem * ioaddr,unsigned int duplex,unsigned int fc,unsigned int pause_time)154 static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
155 			   unsigned int fc, unsigned int pause_time)
156 {
157 	unsigned int flow = 0;
158 
159 	CHIP_DBG(KERN_DEBUG "GMAC Flow-Control:\n");
160 	if (fc & FLOW_RX) {
161 		CHIP_DBG(KERN_DEBUG "\tReceive Flow-Control ON\n");
162 		flow |= GMAC_FLOW_CTRL_RFE;
163 	}
164 	if (fc & FLOW_TX) {
165 		CHIP_DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n");
166 		flow |= GMAC_FLOW_CTRL_TFE;
167 	}
168 
169 	if (duplex) {
170 		CHIP_DBG(KERN_DEBUG "\tduplex mode: PAUSE %d\n", pause_time);
171 		flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
172 	}
173 
174 	writel(flow, ioaddr + GMAC_FLOW_CTRL);
175 }
176 
dwmac1000_pmt(void __iomem * ioaddr,unsigned long mode)177 static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
178 {
179 	unsigned int pmt = 0;
180 
181 	if (mode == WAKE_MAGIC) {
182 		CHIP_DBG(KERN_DEBUG "GMAC: WOL Magic frame\n");
183 		pmt |= power_down | magic_pkt_en;
184 	} else if (mode == WAKE_UCAST) {
185 		CHIP_DBG(KERN_DEBUG "GMAC: WOL on global unicast\n");
186 		pmt |= global_unicast;
187 	}
188 
189 	writel(pmt, ioaddr + GMAC_PMT);
190 }
191 
192 
dwmac1000_irq_status(void __iomem * ioaddr)193 static void dwmac1000_irq_status(void __iomem *ioaddr)
194 {
195 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
196 
197 	/* Not used events (e.g. MMC interrupts) are not handled. */
198 	if ((intr_status & mmc_tx_irq))
199 		CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
200 		    readl(ioaddr + GMAC_MMC_TX_INTR));
201 	if (unlikely(intr_status & mmc_rx_irq))
202 		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
203 		    readl(ioaddr + GMAC_MMC_RX_INTR));
204 	if (unlikely(intr_status & mmc_rx_csum_offload_irq))
205 		CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
206 		    readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
207 	if (unlikely(intr_status & pmt_irq)) {
208 		CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
209 		/* clear the PMT bits 5 and 6 by reading the PMT
210 		 * status register. */
211 		readl(ioaddr + GMAC_PMT);
212 	}
213 }
214 
215 static const struct stmmac_ops dwmac1000_ops = {
216 	.core_init = dwmac1000_core_init,
217 	.rx_coe = dwmac1000_rx_coe_supported,
218 	.dump_regs = dwmac1000_dump_regs,
219 	.host_irq_status = dwmac1000_irq_status,
220 	.set_filter = dwmac1000_set_filter,
221 	.flow_ctrl = dwmac1000_flow_ctrl,
222 	.pmt = dwmac1000_pmt,
223 	.set_umac_addr = dwmac1000_set_umac_addr,
224 	.get_umac_addr = dwmac1000_get_umac_addr,
225 };
226 
dwmac1000_setup(void __iomem * ioaddr)227 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
228 {
229 	struct mac_device_info *mac;
230 	u32 uid = readl(ioaddr + GMAC_VERSION);
231 
232 	pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n",
233 		((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));
234 
235 	mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
236 	if (!mac)
237 		return NULL;
238 
239 	mac->mac = &dwmac1000_ops;
240 	mac->dma = &dwmac1000_dma_ops;
241 
242 	mac->link.port = GMAC_CONTROL_PS;
243 	mac->link.duplex = GMAC_CONTROL_DM;
244 	mac->link.speed = GMAC_CONTROL_FES;
245 	mac->mii.addr = GMAC_MII_ADDR;
246 	mac->mii.data = GMAC_MII_DATA;
247 
248 	return mac;
249 }
250