aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre TORGUE <alexandre.torgue@st.com>2016-04-01 05:37:30 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-02 20:23:08 -0400
commit48863ce5940fa5420096c8beba44e5e1bc0c8ca1 (patch)
tree18f4790a802e5b90834586887b819eb2d34e18af
parent35f74c0c5dce138bd9000d98abf4959af782a96d (diff)
stmmac: add DMA support for GMAC 4.xx
DMA behavior is linked to descriptor management: -descriptor mechanism (Tx for example, but it is exactly the same for RX): -useful registers: -DMA_CH#_TxDesc_Ring_Len: length of transmit descriptor ring -DMA_CH#_TxDesc_List_Address: start address of the ring -DMA_CH#_TxDesc_Tail_Pointer: address of the last descriptor to send + 1. -DMA_CH#_TxDesc_Current_App_TxDesc: address of the current descriptor -The descriptor Tail Pointer register contains the pointer to the descriptor address (N). The base address and the current descriptor decide the address of the current descriptor that the DMA can process. The descriptors up to one location less than the one indicated by the descriptor tail pointer (N-1) are owned by the DMA. The DMA continues to process the descriptors until the following condition occurs: "current descriptor pointer == Descriptor Tail pointer" Then the DMA goes into suspend mode. The application must perform a write to descriptor tail pointer register and update the tail pointer to have the following condition and to start a new transfer: "current descriptor pointer < Descriptor tail pointer" The DMA automatically wraps around the base address when the end of ring is reached. Up to 8 DMA could be use but currently we only use one (channel0) Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c354
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h202
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c225
5 files changed, 793 insertions, 1 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index fa000fd36efc..9398acef0125 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -3,7 +3,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
3 chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ 3 chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
4 dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ 4 dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
5 mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ 5 mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \
6 $(stmmac-y) 6 dwmac4_dma.o dwmac4_lib.o $(stmmac-y)
7 7
8# Ordering matters. Generic driver must be last. 8# Ordering matters. Generic driver must be last.
9obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o 9obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index ea7eb0d5ce98..2a5126e3d3df 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -41,6 +41,8 @@
41/* Synopsys Core versions */ 41/* Synopsys Core versions */
42#define DWMAC_CORE_3_40 0x34 42#define DWMAC_CORE_3_40 0x34
43#define DWMAC_CORE_3_50 0x35 43#define DWMAC_CORE_3_50 0x35
44#define DWMAC_CORE_4_00 0x40
45#define STMMAC_CHAN0 0 /* Always supported and default for all chips */
44 46
45#define DMA_TX_SIZE 512 47#define DMA_TX_SIZE 512
46#define DMA_RX_SIZE 512 48#define DMA_RX_SIZE 512
@@ -270,6 +272,7 @@ enum dma_irq_status {
270#define CORE_PCS_ANE_COMPLETE (1 << 5) 272#define CORE_PCS_ANE_COMPLETE (1 << 5)
271#define CORE_PCS_LINK_STATUS (1 << 6) 273#define CORE_PCS_LINK_STATUS (1 << 6)
272#define CORE_RGMII_IRQ (1 << 7) 274#define CORE_RGMII_IRQ (1 << 7)
275#define CORE_IRQ_MTL_RX_OVERFLOW BIT(8)
273 276
274/* Physical Coding Sublayer */ 277/* Physical Coding Sublayer */
275struct rgmii_adv { 278struct rgmii_adv {
@@ -301,8 +304,10 @@ struct dma_features {
301 /* 802.3az - Energy-Efficient Ethernet (EEE) */ 304 /* 802.3az - Energy-Efficient Ethernet (EEE) */
302 unsigned int eee; 305 unsigned int eee;
303 unsigned int av; 306 unsigned int av;
307 unsigned int tsoen;
304 /* TX and RX csum */ 308 /* TX and RX csum */
305 unsigned int tx_coe; 309 unsigned int tx_coe;
310 unsigned int rx_coe;
306 unsigned int rx_coe_type1; 311 unsigned int rx_coe_type1;
307 unsigned int rx_coe_type2; 312 unsigned int rx_coe_type2;
308 unsigned int rxfifo_over_2048; 313 unsigned int rxfifo_over_2048;
@@ -425,6 +430,11 @@ struct stmmac_dma_ops {
425 struct dma_features *dma_cap); 430 struct dma_features *dma_cap);
426 /* Program the HW RX Watchdog */ 431 /* Program the HW RX Watchdog */
427 void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); 432 void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
433 void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len);
434 void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len);
435 void (*set_rx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
436 void (*set_tx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
437 void (*enable_tso)(void __iomem *ioaddr, bool en, u32 chan);
428}; 438};
429 439
430struct mac_device_info; 440struct mac_device_info;
@@ -473,6 +483,7 @@ struct stmmac_hwtimestamp {
473}; 483};
474 484
475extern const struct stmmac_hwtimestamp stmmac_ptp; 485extern const struct stmmac_hwtimestamp stmmac_ptp;
486extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
476 487
477struct mac_link { 488struct mac_link {
478 int port; 489 int port;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
new file mode 100644
index 000000000000..116151cd6a95
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -0,0 +1,354 @@
1/*
2 * This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
3 * DWC Ether MAC version 4.xx has been used for developing this code.
4 *
5 * This contains the functions to handle the dma.
6 *
7 * Copyright (C) 2015 STMicroelectronics Ltd
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * Author: Alexandre Torgue <alexandre.torgue@st.com>
14 */
15
16#include <linux/io.h>
17#include "dwmac4.h"
18#include "dwmac4_dma.h"
19
20static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
21{
22 u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
23 int i;
24
25 pr_info("dwmac4: Master AXI performs %s burst length\n",
26 (value & DMA_SYS_BUS_FB) ? "fixed" : "any");
27
28 if (axi->axi_lpi_en)
29 value |= DMA_AXI_EN_LPI;
30 if (axi->axi_xit_frm)
31 value |= DMA_AXI_LPI_XIT_FRM;
32
33 value |= (axi->axi_wr_osr_lmt & DMA_AXI_OSR_MAX) <<
34 DMA_AXI_WR_OSR_LMT_SHIFT;
35
36 value |= (axi->axi_rd_osr_lmt & DMA_AXI_OSR_MAX) <<
37 DMA_AXI_RD_OSR_LMT_SHIFT;
38
39 /* Depending on the UNDEF bit the Master AXI will perform any burst
40 * length according to the BLEN programmed (by default all BLEN are
41 * set).
42 */
43 for (i = 0; i < AXI_BLEN; i++) {
44 switch (axi->axi_blen[i]) {
45 case 256:
46 value |= DMA_AXI_BLEN256;
47 break;
48 case 128:
49 value |= DMA_AXI_BLEN128;
50 break;
51 case 64:
52 value |= DMA_AXI_BLEN64;
53 break;
54 case 32:
55 value |= DMA_AXI_BLEN32;
56 break;
57 case 16:
58 value |= DMA_AXI_BLEN16;
59 break;
60 case 8:
61 value |= DMA_AXI_BLEN8;
62 break;
63 case 4:
64 value |= DMA_AXI_BLEN4;
65 break;
66 }
67 }
68
69 writel(value, ioaddr + DMA_SYS_BUS_MODE);
70}
71
72static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl,
73 u32 dma_tx_phy, u32 dma_rx_phy,
74 u32 channel)
75{
76 u32 value;
77
78 /* set PBL for each channels. Currently we affect same configuration
79 * on each channel
80 */
81 value = readl(ioaddr + DMA_CHAN_CONTROL(channel));
82 value = value | DMA_BUS_MODE_PBL;
83 writel(value, ioaddr + DMA_CHAN_CONTROL(channel));
84
85 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel));
86 value = value | (pbl << DMA_BUS_MODE_PBL_SHIFT);
87 writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel));
88
89 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel));
90 value = value | (pbl << DMA_BUS_MODE_RPBL_SHIFT);
91 writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel));
92
93 /* Mask interrupts by writing to CSR7 */
94 writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(channel));
95
96 writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(channel));
97 writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(channel));
98}
99
100static void dwmac4_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
101 int aal, u32 dma_tx, u32 dma_rx, int atds)
102{
103 u32 value = readl(ioaddr + DMA_SYS_BUS_MODE);
104 int i;
105
106 /* Set the Fixed burst mode */
107 if (fb)
108 value |= DMA_SYS_BUS_FB;
109
110 /* Mixed Burst has no effect when fb is set */
111 if (mb)
112 value |= DMA_SYS_BUS_MB;
113
114 if (aal)
115 value |= DMA_SYS_BUS_AAL;
116
117 writel(value, ioaddr + DMA_SYS_BUS_MODE);
118
119 for (i = 0; i < DMA_CHANNEL_NB_MAX; i++)
120 dwmac4_dma_init_channel(ioaddr, pbl, dma_tx, dma_rx, i);
121}
122
123static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel)
124{
125 pr_debug(" Channel %d\n", channel);
126 pr_debug("\tDMA_CHAN_CONTROL, offset: 0x%x, val: 0x%x\n", 0,
127 readl(ioaddr + DMA_CHAN_CONTROL(channel)));
128 pr_debug("\tDMA_CHAN_TX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x4,
129 readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)));
130 pr_debug("\tDMA_CHAN_RX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x8,
131 readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)));
132 pr_debug("\tDMA_CHAN_TX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x14,
133 readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(channel)));
134 pr_debug("\tDMA_CHAN_RX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x1c,
135 readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)));
136 pr_debug("\tDMA_CHAN_TX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x20,
137 readl(ioaddr + DMA_CHAN_TX_END_ADDR(channel)));
138 pr_debug("\tDMA_CHAN_RX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x28,
139 readl(ioaddr + DMA_CHAN_RX_END_ADDR(channel)));
140 pr_debug("\tDMA_CHAN_TX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x2c,
141 readl(ioaddr + DMA_CHAN_TX_RING_LEN(channel)));
142 pr_debug("\tDMA_CHAN_RX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x30,
143 readl(ioaddr + DMA_CHAN_RX_RING_LEN(channel)));
144 pr_debug("\tDMA_CHAN_INTR_ENA, offset: 0x%x, val: 0x%x\n", 0x34,
145 readl(ioaddr + DMA_CHAN_INTR_ENA(channel)));
146 pr_debug("\tDMA_CHAN_RX_WATCHDOG, offset: 0x%x, val: 0x%x\n", 0x38,
147 readl(ioaddr + DMA_CHAN_RX_WATCHDOG(channel)));
148 pr_debug("\tDMA_CHAN_SLOT_CTRL_STATUS, offset: 0x%x, val: 0x%x\n", 0x3c,
149 readl(ioaddr + DMA_CHAN_SLOT_CTRL_STATUS(channel)));
150 pr_debug("\tDMA_CHAN_CUR_TX_DESC, offset: 0x%x, val: 0x%x\n", 0x44,
151 readl(ioaddr + DMA_CHAN_CUR_TX_DESC(channel)));
152 pr_debug("\tDMA_CHAN_CUR_RX_DESC, offset: 0x%x, val: 0x%x\n", 0x4c,
153 readl(ioaddr + DMA_CHAN_CUR_RX_DESC(channel)));
154 pr_debug("\tDMA_CHAN_CUR_TX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x54,
155 readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(channel)));
156 pr_debug("\tDMA_CHAN_CUR_RX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x5c,
157 readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(channel)));
158 pr_debug("\tDMA_CHAN_STATUS, offset: 0x%x, val: 0x%x\n", 0x60,
159 readl(ioaddr + DMA_CHAN_STATUS(channel)));
160}
161
162static void dwmac4_dump_dma_regs(void __iomem *ioaddr)
163{
164 int i;
165
166 pr_debug(" GMAC4 DMA registers\n");
167
168 for (i = 0; i < DMA_CHANNEL_NB_MAX; i++)
169 _dwmac4_dump_dma_regs(ioaddr, i);
170}
171
172static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt)
173{
174 int i;
175
176 for (i = 0; i < DMA_CHANNEL_NB_MAX; i++)
177 writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(i));
178}
179
180static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode,
181 int rxmode, u32 channel)
182{
183 u32 mtl_tx_op, mtl_rx_op, mtl_rx_int;
184
185 /* Following code only done for channel 0, other channels not yet
186 * supported.
187 */
188 mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel));
189
190 if (txmode == SF_DMA_MODE) {
191 pr_debug("GMAC: enable TX store and forward mode\n");
192 /* Transmit COE type 2 cannot be done in cut-through mode. */
193 mtl_tx_op |= MTL_OP_MODE_TSF;
194 } else {
195 pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode);
196 mtl_tx_op &= ~MTL_OP_MODE_TSF;
197 mtl_tx_op &= MTL_OP_MODE_TTC_MASK;
198 /* Set the transmit threshold */
199 if (txmode <= 32)
200 mtl_tx_op |= MTL_OP_MODE_TTC_32;
201 else if (txmode <= 64)
202 mtl_tx_op |= MTL_OP_MODE_TTC_64;
203 else if (txmode <= 96)
204 mtl_tx_op |= MTL_OP_MODE_TTC_96;
205 else if (txmode <= 128)
206 mtl_tx_op |= MTL_OP_MODE_TTC_128;
207 else if (txmode <= 192)
208 mtl_tx_op |= MTL_OP_MODE_TTC_192;
209 else if (txmode <= 256)
210 mtl_tx_op |= MTL_OP_MODE_TTC_256;
211 else if (txmode <= 384)
212 mtl_tx_op |= MTL_OP_MODE_TTC_384;
213 else
214 mtl_tx_op |= MTL_OP_MODE_TTC_512;
215 }
216
217 writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
218
219 mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel));
220
221 if (rxmode == SF_DMA_MODE) {
222 pr_debug("GMAC: enable RX store and forward mode\n");
223 mtl_rx_op |= MTL_OP_MODE_RSF;
224 } else {
225 pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode);
226 mtl_rx_op &= ~MTL_OP_MODE_RSF;
227 mtl_rx_op &= MTL_OP_MODE_RTC_MASK;
228 if (rxmode <= 32)
229 mtl_rx_op |= MTL_OP_MODE_RTC_32;
230 else if (rxmode <= 64)
231 mtl_rx_op |= MTL_OP_MODE_RTC_64;
232 else if (rxmode <= 96)
233 mtl_rx_op |= MTL_OP_MODE_RTC_96;
234 else
235 mtl_rx_op |= MTL_OP_MODE_RTC_128;
236 }
237
238 writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel));
239
240 /* Enable MTL RX overflow */
241 mtl_rx_int = readl(ioaddr + MTL_CHAN_INT_CTRL(channel));
242 writel(mtl_rx_int | MTL_RX_OVERFLOW_INT_EN,
243 ioaddr + MTL_CHAN_INT_CTRL(channel));
244}
245
246static void dwmac4_dma_operation_mode(void __iomem *ioaddr, int txmode,
247 int rxmode, int rxfifosz)
248{
249 /* Only Channel 0 is actually configured and used */
250 dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0);
251}
252
253static void dwmac4_get_hw_feature(void __iomem *ioaddr,
254 struct dma_features *dma_cap)
255{
256 u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
257
258 /* MAC HW feature0 */
259 dma_cap->mbps_10_100 = (hw_cap & GMAC_HW_FEAT_MIISEL);
260 dma_cap->mbps_1000 = (hw_cap & GMAC_HW_FEAT_GMIISEL) >> 1;
261 dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2;
262 dma_cap->hash_filter = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4;
263 dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18;
264 dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3;
265 dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5;
266 dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >> 6;
267 dma_cap->pmt_magic_frame = (hw_cap & GMAC_HW_FEAT_MGKSEL) >> 7;
268 /* MMC */
269 dma_cap->rmon = (hw_cap & GMAC_HW_FEAT_MMCSEL) >> 8;
270 /* IEEE 1588-2008 */
271 dma_cap->atime_stamp = (hw_cap & GMAC_HW_FEAT_TSSEL) >> 12;
272 /* 802.3az - Energy-Efficient Ethernet (EEE) */
273 dma_cap->eee = (hw_cap & GMAC_HW_FEAT_EEESEL) >> 13;
274 /* TX and RX csum */
275 dma_cap->tx_coe = (hw_cap & GMAC_HW_FEAT_TXCOSEL) >> 14;
276 dma_cap->rx_coe = (hw_cap & GMAC_HW_FEAT_RXCOESEL) >> 16;
277
278 /* MAC HW feature1 */
279 hw_cap = readl(ioaddr + GMAC_HW_FEATURE1);
280 dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
281 dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
282 /* MAC HW feature2 */
283 hw_cap = readl(ioaddr + GMAC_HW_FEATURE2);
284 /* TX and RX number of channels */
285 dma_cap->number_rx_channel =
286 ((hw_cap & GMAC_HW_FEAT_RXCHCNT) >> 12) + 1;
287 dma_cap->number_tx_channel =
288 ((hw_cap & GMAC_HW_FEAT_TXCHCNT) >> 18) + 1;
289
290 /* IEEE 1588-2002 */
291 dma_cap->time_stamp = 0;
292}
293
294/* Enable/disable TSO feature and set MSS */
295static void dwmac4_enable_tso(void __iomem *ioaddr, bool en, u32 chan)
296{
297 u32 value;
298
299 if (en) {
300 /* enable TSO */
301 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
302 writel(value | DMA_CONTROL_TSE,
303 ioaddr + DMA_CHAN_TX_CONTROL(chan));
304 } else {
305 /* enable TSO */
306 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
307 writel(value & ~DMA_CONTROL_TSE,
308 ioaddr + DMA_CHAN_TX_CONTROL(chan));
309 }
310}
311
312const struct stmmac_dma_ops dwmac4_dma_ops = {
313 .reset = dwmac4_dma_reset,
314 .init = dwmac4_dma_init,
315 .axi = dwmac4_dma_axi,
316 .dump_regs = dwmac4_dump_dma_regs,
317 .dma_mode = dwmac4_dma_operation_mode,
318 .enable_dma_irq = dwmac4_enable_dma_irq,
319 .disable_dma_irq = dwmac4_disable_dma_irq,
320 .start_tx = dwmac4_dma_start_tx,
321 .stop_tx = dwmac4_dma_stop_tx,
322 .start_rx = dwmac4_dma_start_rx,
323 .stop_rx = dwmac4_dma_stop_rx,
324 .dma_interrupt = dwmac4_dma_interrupt,
325 .get_hw_feature = dwmac4_get_hw_feature,
326 .rx_watchdog = dwmac4_rx_watchdog,
327 .set_rx_ring_len = dwmac4_set_rx_ring_len,
328 .set_tx_ring_len = dwmac4_set_tx_ring_len,
329 .set_rx_tail_ptr = dwmac4_set_rx_tail_ptr,
330 .set_tx_tail_ptr = dwmac4_set_tx_tail_ptr,
331 .enable_tso = dwmac4_enable_tso,
332};
333
334const struct stmmac_dma_ops dwmac410_dma_ops = {
335 .reset = dwmac4_dma_reset,
336 .init = dwmac4_dma_init,
337 .axi = dwmac4_dma_axi,
338 .dump_regs = dwmac4_dump_dma_regs,
339 .dma_mode = dwmac4_dma_operation_mode,
340 .enable_dma_irq = dwmac410_enable_dma_irq,
341 .disable_dma_irq = dwmac4_disable_dma_irq,
342 .start_tx = dwmac4_dma_start_tx,
343 .stop_tx = dwmac4_dma_stop_tx,
344 .start_rx = dwmac4_dma_start_rx,
345 .stop_rx = dwmac4_dma_stop_rx,
346 .dma_interrupt = dwmac4_dma_interrupt,
347 .get_hw_feature = dwmac4_get_hw_feature,
348 .rx_watchdog = dwmac4_rx_watchdog,
349 .set_rx_ring_len = dwmac4_set_rx_ring_len,
350 .set_tx_ring_len = dwmac4_set_tx_ring_len,
351 .set_rx_tail_ptr = dwmac4_set_rx_tail_ptr,
352 .set_tx_tail_ptr = dwmac4_set_tx_tail_ptr,
353 .enable_tso = dwmac4_enable_tso,
354};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
new file mode 100644
index 000000000000..1b06df749e2b
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
@@ -0,0 +1,202 @@
1/*
2 * DWMAC4 DMA Header file.
3 *
4 *
5 * Copyright (C) 2007-2015 STMicroelectronics Ltd
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * Author: Alexandre Torgue <alexandre.torgue@st.com>
12 */
13
14#ifndef __DWMAC4_DMA_H__
15#define __DWMAC4_DMA_H__
16
17/* Define the max channel number used for tx (also rx).
18 * dwmac4 accepts up to 8 channels for TX (and also 8 channels for RX
19 */
20#define DMA_CHANNEL_NB_MAX 1
21
22#define DMA_BUS_MODE 0x00001000
23#define DMA_SYS_BUS_MODE 0x00001004
24#define DMA_STATUS 0x00001008
25#define DMA_DEBUG_STATUS_0 0x0000100c
26#define DMA_DEBUG_STATUS_1 0x00001010
27#define DMA_DEBUG_STATUS_2 0x00001014
28#define DMA_AXI_BUS_MODE 0x00001028
29
30/* DMA Bus Mode bitmap */
31#define DMA_BUS_MODE_SFT_RESET BIT(0)
32
33/* DMA SYS Bus Mode bitmap */
34#define DMA_BUS_MODE_SPH BIT(24)
35#define DMA_BUS_MODE_PBL BIT(16)
36#define DMA_BUS_MODE_PBL_SHIFT 16
37#define DMA_BUS_MODE_RPBL_SHIFT 16
38#define DMA_BUS_MODE_MB BIT(14)
39#define DMA_BUS_MODE_FB BIT(0)
40
41/* DMA Interrupt top status */
42#define DMA_STATUS_MAC BIT(17)
43#define DMA_STATUS_MTL BIT(16)
44#define DMA_STATUS_CHAN7 BIT(7)
45#define DMA_STATUS_CHAN6 BIT(6)
46#define DMA_STATUS_CHAN5 BIT(5)
47#define DMA_STATUS_CHAN4 BIT(4)
48#define DMA_STATUS_CHAN3 BIT(3)
49#define DMA_STATUS_CHAN2 BIT(2)
50#define DMA_STATUS_CHAN1 BIT(1)
51#define DMA_STATUS_CHAN0 BIT(0)
52
53/* DMA debug status bitmap */
54#define DMA_DEBUG_STATUS_TS_MASK 0xf
55#define DMA_DEBUG_STATUS_RS_MASK 0xf
56
57/* DMA AXI bitmap */
58#define DMA_AXI_EN_LPI BIT(31)
59#define DMA_AXI_LPI_XIT_FRM BIT(30)
60#define DMA_AXI_WR_OSR_LMT GENMASK(27, 24)
61#define DMA_AXI_WR_OSR_LMT_SHIFT 24
62#define DMA_AXI_RD_OSR_LMT GENMASK(19, 16)
63#define DMA_AXI_RD_OSR_LMT_SHIFT 16
64
65#define DMA_AXI_OSR_MAX 0xf
66#define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \
67 (DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT))
68
69#define DMA_SYS_BUS_MB BIT(14)
70#define DMA_AXI_1KBBE BIT(13)
71#define DMA_SYS_BUS_AAL BIT(12)
72#define DMA_AXI_BLEN256 BIT(7)
73#define DMA_AXI_BLEN128 BIT(6)
74#define DMA_AXI_BLEN64 BIT(5)
75#define DMA_AXI_BLEN32 BIT(4)
76#define DMA_AXI_BLEN16 BIT(3)
77#define DMA_AXI_BLEN8 BIT(2)
78#define DMA_AXI_BLEN4 BIT(1)
79#define DMA_SYS_BUS_FB BIT(0)
80
81#define DMA_BURST_LEN_DEFAULT (DMA_AXI_BLEN256 | DMA_AXI_BLEN128 | \
82 DMA_AXI_BLEN64 | DMA_AXI_BLEN32 | \
83 DMA_AXI_BLEN16 | DMA_AXI_BLEN8 | \
84 DMA_AXI_BLEN4)
85
86#define DMA_AXI_BURST_LEN_MASK 0x000000FE
87
88/* Following DMA defines are chanels oriented */
89#define DMA_CHAN_BASE_ADDR 0x00001100
90#define DMA_CHAN_BASE_OFFSET 0x80
91#define DMA_CHANX_BASE_ADDR(x) (DMA_CHAN_BASE_ADDR + \
92 (x * DMA_CHAN_BASE_OFFSET))
93#define DMA_CHAN_REG_NUMBER 17
94
95#define DMA_CHAN_CONTROL(x) DMA_CHANX_BASE_ADDR(x)
96#define DMA_CHAN_TX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x4)
97#define DMA_CHAN_RX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x8)
98#define DMA_CHAN_TX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x14)
99#define DMA_CHAN_RX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x1c)
100#define DMA_CHAN_TX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x20)
101#define DMA_CHAN_RX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x28)
102#define DMA_CHAN_TX_RING_LEN(x) (DMA_CHANX_BASE_ADDR(x) + 0x2c)
103#define DMA_CHAN_RX_RING_LEN(x) (DMA_CHANX_BASE_ADDR(x) + 0x30)
104#define DMA_CHAN_INTR_ENA(x) (DMA_CHANX_BASE_ADDR(x) + 0x34)
105#define DMA_CHAN_RX_WATCHDOG(x) (DMA_CHANX_BASE_ADDR(x) + 0x38)
106#define DMA_CHAN_SLOT_CTRL_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x3c)
107#define DMA_CHAN_CUR_TX_DESC(x) (DMA_CHANX_BASE_ADDR(x) + 0x44)
108#define DMA_CHAN_CUR_RX_DESC(x) (DMA_CHANX_BASE_ADDR(x) + 0x4c)
109#define DMA_CHAN_CUR_TX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x54)
110#define DMA_CHAN_CUR_RX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x5c)
111#define DMA_CHAN_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x60)
112
113/* DMA Control X */
114#define DMA_CONTROL_MSS_MASK GENMASK(13, 0)
115
116/* DMA Tx Channel X Control register defines */
117#define DMA_CONTROL_TSE BIT(12)
118#define DMA_CONTROL_OSP BIT(4)
119#define DMA_CONTROL_ST BIT(0)
120
121/* DMA Rx Channel X Control register defines */
122#define DMA_CONTROL_SR BIT(0)
123
124/* Interrupt status per channel */
125#define DMA_CHAN_STATUS_REB GENMASK(21, 19)
126#define DMA_CHAN_STATUS_REB_SHIFT 19
127#define DMA_CHAN_STATUS_TEB GENMASK(18, 16)
128#define DMA_CHAN_STATUS_TEB_SHIFT 16
129#define DMA_CHAN_STATUS_NIS BIT(15)
130#define DMA_CHAN_STATUS_AIS BIT(14)
131#define DMA_CHAN_STATUS_CDE BIT(13)
132#define DMA_CHAN_STATUS_FBE BIT(12)
133#define DMA_CHAN_STATUS_ERI BIT(11)
134#define DMA_CHAN_STATUS_ETI BIT(10)
135#define DMA_CHAN_STATUS_RWT BIT(9)
136#define DMA_CHAN_STATUS_RPS BIT(8)
137#define DMA_CHAN_STATUS_RBU BIT(7)
138#define DMA_CHAN_STATUS_RI BIT(6)
139#define DMA_CHAN_STATUS_TBU BIT(2)
140#define DMA_CHAN_STATUS_TPS BIT(1)
141#define DMA_CHAN_STATUS_TI BIT(0)
142
143/* Interrupt enable bits per channel */
144#define DMA_CHAN_INTR_ENA_NIE BIT(16)
145#define DMA_CHAN_INTR_ENA_AIE BIT(15)
146#define DMA_CHAN_INTR_ENA_NIE_4_10 BIT(15)
147#define DMA_CHAN_INTR_ENA_AIE_4_10 BIT(14)
148#define DMA_CHAN_INTR_ENA_CDE BIT(13)
149#define DMA_CHAN_INTR_ENA_FBE BIT(12)
150#define DMA_CHAN_INTR_ENA_ERE BIT(11)
151#define DMA_CHAN_INTR_ENA_ETE BIT(10)
152#define DMA_CHAN_INTR_ENA_RWE BIT(9)
153#define DMA_CHAN_INTR_ENA_RSE BIT(8)
154#define DMA_CHAN_INTR_ENA_RBUE BIT(7)
155#define DMA_CHAN_INTR_ENA_RIE BIT(6)
156#define DMA_CHAN_INTR_ENA_TBUE BIT(2)
157#define DMA_CHAN_INTR_ENA_TSE BIT(1)
158#define DMA_CHAN_INTR_ENA_TIE BIT(0)
159
160#define DMA_CHAN_INTR_NORMAL (DMA_CHAN_INTR_ENA_NIE | \
161 DMA_CHAN_INTR_ENA_RIE | \
162 DMA_CHAN_INTR_ENA_TIE)
163
164#define DMA_CHAN_INTR_ABNORMAL (DMA_CHAN_INTR_ENA_AIE | \
165 DMA_CHAN_INTR_ENA_FBE)
166/* DMA default interrupt mask for 4.00 */
167#define DMA_CHAN_INTR_DEFAULT_MASK (DMA_CHAN_INTR_NORMAL | \
168 DMA_CHAN_INTR_ABNORMAL)
169
170#define DMA_CHAN_INTR_NORMAL_4_10 (DMA_CHAN_INTR_ENA_NIE_4_10 | \
171 DMA_CHAN_INTR_ENA_RIE | \
172 DMA_CHAN_INTR_ENA_TIE)
173
174#define DMA_CHAN_INTR_ABNORMAL_4_10 (DMA_CHAN_INTR_ENA_AIE_4_10 | \
175 DMA_CHAN_INTR_ENA_FBE)
176/* DMA default interrupt mask for 4.10a */
177#define DMA_CHAN_INTR_DEFAULT_MASK_4_10 (DMA_CHAN_INTR_NORMAL_4_10 | \
178 DMA_CHAN_INTR_ABNORMAL_4_10)
179
180/* channel 0 specific fields */
181#define DMA_CHAN0_DBG_STAT_TPS GENMASK(15, 12)
182#define DMA_CHAN0_DBG_STAT_TPS_SHIFT 12
183#define DMA_CHAN0_DBG_STAT_RPS GENMASK(11, 8)
184#define DMA_CHAN0_DBG_STAT_RPS_SHIFT 8
185
186int dwmac4_dma_reset(void __iomem *ioaddr);
187void dwmac4_enable_dma_transmission(void __iomem *ioaddr, u32 tail_ptr);
188void dwmac4_enable_dma_irq(void __iomem *ioaddr);
189void dwmac410_enable_dma_irq(void __iomem *ioaddr);
190void dwmac4_disable_dma_irq(void __iomem *ioaddr);
191void dwmac4_dma_start_tx(void __iomem *ioaddr);
192void dwmac4_dma_stop_tx(void __iomem *ioaddr);
193void dwmac4_dma_start_rx(void __iomem *ioaddr);
194void dwmac4_dma_stop_rx(void __iomem *ioaddr);
195int dwmac4_dma_interrupt(void __iomem *ioaddr,
196 struct stmmac_extra_stats *x);
197void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len);
198void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len);
199void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
200void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
201
202#endif /* __DWMAC4_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
new file mode 100644
index 000000000000..c7326d5b2f43
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -0,0 +1,225 @@
1/*
2 * Copyright (C) 2007-2015 STMicroelectronics Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * Author: Alexandre Torgue <alexandre.torgue@st.com>
9 */
10
11#include <linux/io.h>
12#include <linux/delay.h>
13#include "common.h"
14#include "dwmac4_dma.h"
15#include "dwmac4.h"
16
17int dwmac4_dma_reset(void __iomem *ioaddr)
18{
19 u32 value = readl(ioaddr + DMA_BUS_MODE);
20 int limit;
21
22 /* DMA SW reset */
23 value |= DMA_BUS_MODE_SFT_RESET;
24 writel(value, ioaddr + DMA_BUS_MODE);
25 limit = 10;
26 while (limit--) {
27 if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
28 break;
29 mdelay(10);
30 }
31
32 if (limit < 0)
33 return -EBUSY;
34
35 return 0;
36}
37
38void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
39{
40 writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(0));
41}
42
43void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
44{
45 writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(0));
46}
47
48void dwmac4_dma_start_tx(void __iomem *ioaddr)
49{
50 u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0));
51
52 value |= DMA_CONTROL_ST;
53 writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0));
54
55 value = readl(ioaddr + GMAC_CONFIG);
56 value |= GMAC_CONFIG_TE;
57 writel(value, ioaddr + GMAC_CONFIG);
58}
59
60void dwmac4_dma_stop_tx(void __iomem *ioaddr)
61{
62 u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0));
63
64 value &= ~DMA_CONTROL_ST;
65 writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0));
66
67 value = readl(ioaddr + GMAC_CONFIG);
68 value &= ~GMAC_CONFIG_TE;
69 writel(value, ioaddr + GMAC_CONFIG);
70}
71
72void dwmac4_dma_start_rx(void __iomem *ioaddr)
73{
74 u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0));
75
76 value |= DMA_CONTROL_SR;
77
78 writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0));
79
80 value = readl(ioaddr + GMAC_CONFIG);
81 value |= GMAC_CONFIG_RE;
82 writel(value, ioaddr + GMAC_CONFIG);
83}
84
85void dwmac4_dma_stop_rx(void __iomem *ioaddr)
86{
87 u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0));
88
89 value &= ~DMA_CONTROL_SR;
90 writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0));
91
92 value = readl(ioaddr + GMAC_CONFIG);
93 value &= ~GMAC_CONFIG_RE;
94 writel(value, ioaddr + GMAC_CONFIG);
95}
96
97void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len)
98{
99 writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(STMMAC_CHAN0));
100}
101
102void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len)
103{
104 writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(STMMAC_CHAN0));
105}
106
107void dwmac4_enable_dma_irq(void __iomem *ioaddr)
108{
109 writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr +
110 DMA_CHAN_INTR_ENA(STMMAC_CHAN0));
111}
112
113void dwmac410_enable_dma_irq(void __iomem *ioaddr)
114{
115 writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10,
116 ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0));
117}
118
119void dwmac4_disable_dma_irq(void __iomem *ioaddr)
120{
121 writel(0, ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0));
122}
123
124int dwmac4_dma_interrupt(void __iomem *ioaddr,
125 struct stmmac_extra_stats *x)
126{
127 int ret = 0;
128
129 u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(0));
130
131 /* ABNORMAL interrupts */
132 if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) {
133 if (unlikely(intr_status & DMA_CHAN_STATUS_RBU))
134 x->rx_buf_unav_irq++;
135 if (unlikely(intr_status & DMA_CHAN_STATUS_RPS))
136 x->rx_process_stopped_irq++;
137 if (unlikely(intr_status & DMA_CHAN_STATUS_RWT))
138 x->rx_watchdog_irq++;
139 if (unlikely(intr_status & DMA_CHAN_STATUS_ETI))
140 x->tx_early_irq++;
141 if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) {
142 x->tx_process_stopped_irq++;
143 ret = tx_hard_error;
144 }
145 if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) {
146 x->fatal_bus_error_irq++;
147 ret = tx_hard_error;
148 }
149 }
150 /* TX/RX NORMAL interrupts */
151 if (likely(intr_status & DMA_CHAN_STATUS_NIS)) {
152 x->normal_irq_n++;
153 if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
154 u32 value;
155
156 value = readl(ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0));
157 /* to schedule NAPI on real RIE event. */
158 if (likely(value & DMA_CHAN_INTR_ENA_RIE)) {
159 x->rx_normal_irq_n++;
160 ret |= handle_rx;
161 }
162 }
163 if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
164 x->tx_normal_irq_n++;
165 ret |= handle_tx;
166 }
167 if (unlikely(intr_status & DMA_CHAN_STATUS_ERI))
168 x->rx_early_irq++;
169 }
170
171 /* Clear the interrupt by writing a logic 1 to the chanX interrupt
172 * status [21-0] expect reserved bits [5-3]
173 */
174 writel((intr_status & 0x3fffc7),
175 ioaddr + DMA_CHAN_STATUS(STMMAC_CHAN0));
176
177 return ret;
178}
179
180void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
181 unsigned int high, unsigned int low)
182{
183 unsigned long data;
184
185 data = (addr[5] << 8) | addr[4];
186 /* For MAC Addr registers se have to set the Address Enable (AE)
187 * bit that has no effect on the High Reg 0 where the bit 31 (MO)
188 * is RO.
189 */
190 data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT);
191 writel(data | GMAC_HI_REG_AE, ioaddr + high);
192 data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
193 writel(data, ioaddr + low);
194}
195
196/* Enable disable MAC RX/TX */
197void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
198{
199 u32 value = readl(ioaddr + GMAC_CONFIG);
200
201 if (enable)
202 value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
203 else
204 value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
205
206 writel(value, ioaddr + GMAC_CONFIG);
207}
208
209void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
210 unsigned int high, unsigned int low)
211{
212 unsigned int hi_addr, lo_addr;
213
214 /* Read the MAC address from the hardware */
215 hi_addr = readl(ioaddr + high);
216 lo_addr = readl(ioaddr + low);
217
218 /* Extract the MAC address from the high and low words */
219 addr[0] = lo_addr & 0xff;
220 addr[1] = (lo_addr >> 8) & 0xff;
221 addr[2] = (lo_addr >> 16) & 0xff;
222 addr[3] = (lo_addr >> 24) & 0xff;
223 addr[4] = hi_addr & 0xff;
224 addr[5] = (hi_addr >> 8) & 0xff;
225}