xref: /openbmc/linux/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c (revision c595db6d7c8bcf87ef42204391fa890e5950e566)
175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
248863ce5SAlexandre TORGUE /*
348863ce5SAlexandre TORGUE  * Copyright (C) 2007-2015  STMicroelectronics Ltd
448863ce5SAlexandre TORGUE  *
548863ce5SAlexandre TORGUE  * Author: Alexandre Torgue <alexandre.torgue@st.com>
648863ce5SAlexandre TORGUE  */
748863ce5SAlexandre TORGUE 
848863ce5SAlexandre TORGUE #include <linux/io.h>
945d0da49SDejin Zheng #include <linux/iopoll.h>
1048863ce5SAlexandre TORGUE #include <linux/delay.h>
1148863ce5SAlexandre TORGUE #include "common.h"
1248863ce5SAlexandre TORGUE #include "dwmac4_dma.h"
1348863ce5SAlexandre TORGUE #include "dwmac4.h"
1433719b57SAndrew Halaney #include "stmmac.h"
1548863ce5SAlexandre TORGUE 
dwmac4_dma_reset(void __iomem * ioaddr)1648863ce5SAlexandre TORGUE int dwmac4_dma_reset(void __iomem *ioaddr)
1748863ce5SAlexandre TORGUE {
1848863ce5SAlexandre TORGUE 	u32 value = readl(ioaddr + DMA_BUS_MODE);
1948863ce5SAlexandre TORGUE 
2048863ce5SAlexandre TORGUE 	/* DMA SW reset */
2148863ce5SAlexandre TORGUE 	value |= DMA_BUS_MODE_SFT_RESET;
2248863ce5SAlexandre TORGUE 	writel(value, ioaddr + DMA_BUS_MODE);
2348863ce5SAlexandre TORGUE 
2445d0da49SDejin Zheng 	return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
2545d0da49SDejin Zheng 				 !(value & DMA_BUS_MODE_SFT_RESET),
269d14edfdSFugang Duan 				 10000, 1000000);
2748863ce5SAlexandre TORGUE }
2848863ce5SAlexandre TORGUE 
dwmac4_set_rx_tail_ptr(struct stmmac_priv * priv,void __iomem * ioaddr,u32 tail_ptr,u32 chan)291d84b487SAndrew Halaney void dwmac4_set_rx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr,
301d84b487SAndrew Halaney 			    u32 tail_ptr, u32 chan)
3148863ce5SAlexandre TORGUE {
3233719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
3333719b57SAndrew Halaney 
3433719b57SAndrew Halaney 	writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(dwmac4_addrs, chan));
3548863ce5SAlexandre TORGUE }
3648863ce5SAlexandre TORGUE 
dwmac4_set_tx_tail_ptr(struct stmmac_priv * priv,void __iomem * ioaddr,u32 tail_ptr,u32 chan)371d84b487SAndrew Halaney void dwmac4_set_tx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr,
381d84b487SAndrew Halaney 			    u32 tail_ptr, u32 chan)
3948863ce5SAlexandre TORGUE {
4033719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
4133719b57SAndrew Halaney 
4233719b57SAndrew Halaney 	writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(dwmac4_addrs, chan));
4348863ce5SAlexandre TORGUE }
4448863ce5SAlexandre TORGUE 
dwmac4_dma_start_tx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)451d84b487SAndrew Halaney void dwmac4_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
461d84b487SAndrew Halaney 			 u32 chan)
4748863ce5SAlexandre TORGUE {
4833719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
4933719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
5048863ce5SAlexandre TORGUE 
5148863ce5SAlexandre TORGUE 	value |= DMA_CONTROL_ST;
5233719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
5348863ce5SAlexandre TORGUE 
5448863ce5SAlexandre TORGUE 	value = readl(ioaddr + GMAC_CONFIG);
5548863ce5SAlexandre TORGUE 	value |= GMAC_CONFIG_TE;
5648863ce5SAlexandre TORGUE 	writel(value, ioaddr + GMAC_CONFIG);
5748863ce5SAlexandre TORGUE }
5848863ce5SAlexandre TORGUE 
dwmac4_dma_stop_tx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)591d84b487SAndrew Halaney void dwmac4_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
601d84b487SAndrew Halaney 			u32 chan)
6148863ce5SAlexandre TORGUE {
6233719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
6333719b57SAndrew Halaney 
6433719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
6548863ce5SAlexandre TORGUE 
6648863ce5SAlexandre TORGUE 	value &= ~DMA_CONTROL_ST;
6733719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
6848863ce5SAlexandre TORGUE }
6948863ce5SAlexandre TORGUE 
dwmac4_dma_start_rx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)701d84b487SAndrew Halaney void dwmac4_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
711d84b487SAndrew Halaney 			 u32 chan)
7248863ce5SAlexandre TORGUE {
7333719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
7433719b57SAndrew Halaney 
7533719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
7648863ce5SAlexandre TORGUE 
7748863ce5SAlexandre TORGUE 	value |= DMA_CONTROL_SR;
7848863ce5SAlexandre TORGUE 
7933719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
8048863ce5SAlexandre TORGUE 
8148863ce5SAlexandre TORGUE 	value = readl(ioaddr + GMAC_CONFIG);
8248863ce5SAlexandre TORGUE 	value |= GMAC_CONFIG_RE;
8348863ce5SAlexandre TORGUE 	writel(value, ioaddr + GMAC_CONFIG);
8448863ce5SAlexandre TORGUE }
8548863ce5SAlexandre TORGUE 
dwmac4_dma_stop_rx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)861d84b487SAndrew Halaney void dwmac4_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
871d84b487SAndrew Halaney 			u32 chan)
8848863ce5SAlexandre TORGUE {
8933719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
9033719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
9148863ce5SAlexandre TORGUE 
9248863ce5SAlexandre TORGUE 	value &= ~DMA_CONTROL_SR;
9333719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
9448863ce5SAlexandre TORGUE }
9548863ce5SAlexandre TORGUE 
dwmac4_set_tx_ring_len(struct stmmac_priv * priv,void __iomem * ioaddr,u32 len,u32 chan)961d84b487SAndrew Halaney void dwmac4_set_tx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr,
971d84b487SAndrew Halaney 			    u32 len, u32 chan)
9848863ce5SAlexandre TORGUE {
9933719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
10033719b57SAndrew Halaney 
10133719b57SAndrew Halaney 	writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(dwmac4_addrs, chan));
10248863ce5SAlexandre TORGUE }
10348863ce5SAlexandre TORGUE 
dwmac4_set_rx_ring_len(struct stmmac_priv * priv,void __iomem * ioaddr,u32 len,u32 chan)1041d84b487SAndrew Halaney void dwmac4_set_rx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr,
1051d84b487SAndrew Halaney 			    u32 len, u32 chan)
10648863ce5SAlexandre TORGUE {
10733719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
10833719b57SAndrew Halaney 
10933719b57SAndrew Halaney 	writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(dwmac4_addrs, chan));
11048863ce5SAlexandre TORGUE }
11148863ce5SAlexandre TORGUE 
dwmac4_enable_dma_irq(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan,bool rx,bool tx)1121d84b487SAndrew Halaney void dwmac4_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
1131d84b487SAndrew Halaney 			   u32 chan, bool rx, bool tx)
11448863ce5SAlexandre TORGUE {
11533719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
11633719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
117021bd5e3SJose Abreu 
118021bd5e3SJose Abreu 	if (rx)
119021bd5e3SJose Abreu 		value |= DMA_CHAN_INTR_DEFAULT_RX;
120021bd5e3SJose Abreu 	if (tx)
121021bd5e3SJose Abreu 		value |= DMA_CHAN_INTR_DEFAULT_TX;
122021bd5e3SJose Abreu 
12333719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
12448863ce5SAlexandre TORGUE }
12548863ce5SAlexandre TORGUE 
dwmac410_enable_dma_irq(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan,bool rx,bool tx)1261d84b487SAndrew Halaney void dwmac410_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
1271d84b487SAndrew Halaney 			     u32 chan, bool rx, bool tx)
12848863ce5SAlexandre TORGUE {
12933719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
13033719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
131021bd5e3SJose Abreu 
132021bd5e3SJose Abreu 	if (rx)
133021bd5e3SJose Abreu 		value |= DMA_CHAN_INTR_DEFAULT_RX_4_10;
134021bd5e3SJose Abreu 	if (tx)
135021bd5e3SJose Abreu 		value |= DMA_CHAN_INTR_DEFAULT_TX_4_10;
136021bd5e3SJose Abreu 
13733719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
13848863ce5SAlexandre TORGUE }
13948863ce5SAlexandre TORGUE 
dwmac4_disable_dma_irq(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan,bool rx,bool tx)1401d84b487SAndrew Halaney void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
1411d84b487SAndrew Halaney 			    u32 chan, bool rx, bool tx)
14248863ce5SAlexandre TORGUE {
14333719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
14433719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
145021bd5e3SJose Abreu 
146021bd5e3SJose Abreu 	if (rx)
147021bd5e3SJose Abreu 		value &= ~DMA_CHAN_INTR_DEFAULT_RX;
148021bd5e3SJose Abreu 	if (tx)
149021bd5e3SJose Abreu 		value &= ~DMA_CHAN_INTR_DEFAULT_TX;
150021bd5e3SJose Abreu 
15133719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
152021bd5e3SJose Abreu }
153021bd5e3SJose Abreu 
dwmac410_disable_dma_irq(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan,bool rx,bool tx)1541d84b487SAndrew Halaney void dwmac410_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
1551d84b487SAndrew Halaney 			      u32 chan, bool rx, bool tx)
156021bd5e3SJose Abreu {
15733719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
15833719b57SAndrew Halaney 	u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
159021bd5e3SJose Abreu 
160021bd5e3SJose Abreu 	if (rx)
161021bd5e3SJose Abreu 		value &= ~DMA_CHAN_INTR_DEFAULT_RX_4_10;
162021bd5e3SJose Abreu 	if (tx)
163021bd5e3SJose Abreu 		value &= ~DMA_CHAN_INTR_DEFAULT_TX_4_10;
164021bd5e3SJose Abreu 
16533719b57SAndrew Halaney 	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
16648863ce5SAlexandre TORGUE }
16748863ce5SAlexandre TORGUE 
dwmac4_dma_interrupt(struct stmmac_priv * priv,void __iomem * ioaddr,struct stmmac_extra_stats * x,u32 chan,u32 dir)1681d84b487SAndrew Halaney int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
1697e1c520cSOng Boon Leong 			 struct stmmac_extra_stats *x, u32 chan, u32 dir)
17048863ce5SAlexandre TORGUE {
17133719b57SAndrew Halaney 	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
17233719b57SAndrew Halaney 	u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
17333719b57SAndrew Halaney 	u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
174*9680b2abSPetr Tesarik 	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
1751103d3a5SJose Abreu 	int ret = 0;
17648863ce5SAlexandre TORGUE 
1777e1c520cSOng Boon Leong 	if (dir == DMA_DIR_RX)
1787e1c520cSOng Boon Leong 		intr_status &= DMA_CHAN_STATUS_MSK_RX;
1797e1c520cSOng Boon Leong 	else if (dir == DMA_DIR_TX)
1807e1c520cSOng Boon Leong 		intr_status &= DMA_CHAN_STATUS_MSK_TX;
1817e1c520cSOng Boon Leong 
18248863ce5SAlexandre TORGUE 	/* ABNORMAL interrupts */
18348863ce5SAlexandre TORGUE 	if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) {
18448863ce5SAlexandre TORGUE 		if (unlikely(intr_status & DMA_CHAN_STATUS_RBU))
18548863ce5SAlexandre TORGUE 			x->rx_buf_unav_irq++;
18648863ce5SAlexandre TORGUE 		if (unlikely(intr_status & DMA_CHAN_STATUS_RPS))
18748863ce5SAlexandre TORGUE 			x->rx_process_stopped_irq++;
18848863ce5SAlexandre TORGUE 		if (unlikely(intr_status & DMA_CHAN_STATUS_RWT))
18948863ce5SAlexandre TORGUE 			x->rx_watchdog_irq++;
19048863ce5SAlexandre TORGUE 		if (unlikely(intr_status & DMA_CHAN_STATUS_ETI))
19148863ce5SAlexandre TORGUE 			x->tx_early_irq++;
19248863ce5SAlexandre TORGUE 		if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) {
19348863ce5SAlexandre TORGUE 			x->tx_process_stopped_irq++;
19448863ce5SAlexandre TORGUE 			ret = tx_hard_error;
19548863ce5SAlexandre TORGUE 		}
19648863ce5SAlexandre TORGUE 		if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) {
19748863ce5SAlexandre TORGUE 			x->fatal_bus_error_irq++;
19848863ce5SAlexandre TORGUE 			ret = tx_hard_error;
19948863ce5SAlexandre TORGUE 		}
20048863ce5SAlexandre TORGUE 	}
20148863ce5SAlexandre TORGUE 	/* TX/RX NORMAL interrupts */
20248863ce5SAlexandre TORGUE 	if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
203*9680b2abSPetr Tesarik 		u64_stats_update_begin(&stats->syncp);
204*9680b2abSPetr Tesarik 		u64_stats_inc(&stats->rx_normal_irq_n[chan]);
205*9680b2abSPetr Tesarik 		u64_stats_update_end(&stats->syncp);
20648863ce5SAlexandre TORGUE 		ret |= handle_rx;
20748863ce5SAlexandre TORGUE 	}
2081975df88SVoon Weifeng 	if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
209*9680b2abSPetr Tesarik 		u64_stats_update_begin(&stats->syncp);
210*9680b2abSPetr Tesarik 		u64_stats_inc(&stats->tx_normal_irq_n[chan]);
211*9680b2abSPetr Tesarik 		u64_stats_update_end(&stats->syncp);
21248863ce5SAlexandre TORGUE 		ret |= handle_tx;
21348863ce5SAlexandre TORGUE 	}
214133466c3SJisheng Zhang 
2151975df88SVoon Weifeng 	if (unlikely(intr_status & DMA_CHAN_STATUS_TBU))
2161975df88SVoon Weifeng 		ret |= handle_tx;
21748863ce5SAlexandre TORGUE 	if (unlikely(intr_status & DMA_CHAN_STATUS_ERI))
21848863ce5SAlexandre TORGUE 		x->rx_early_irq++;
21948863ce5SAlexandre TORGUE 
22033719b57SAndrew Halaney 	writel(intr_status & intr_en,
22133719b57SAndrew Halaney 	       ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
22248863ce5SAlexandre TORGUE 	return ret;
22348863ce5SAlexandre TORGUE }
22448863ce5SAlexandre TORGUE 
stmmac_dwmac4_set_mac_addr(void __iomem * ioaddr,const u8 addr[6],unsigned int high,unsigned int low)22576660757SJakub Kicinski void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
22648863ce5SAlexandre TORGUE 				unsigned int high, unsigned int low)
22748863ce5SAlexandre TORGUE {
22848863ce5SAlexandre TORGUE 	unsigned long data;
22948863ce5SAlexandre TORGUE 
23048863ce5SAlexandre TORGUE 	data = (addr[5] << 8) | addr[4];
23148863ce5SAlexandre TORGUE 	/* For MAC Addr registers se have to set the Address Enable (AE)
23248863ce5SAlexandre TORGUE 	 * bit that has no effect on the High Reg 0 where the bit 31 (MO)
23348863ce5SAlexandre TORGUE 	 * is RO.
23448863ce5SAlexandre TORGUE 	 */
23548863ce5SAlexandre TORGUE 	data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT);
23648863ce5SAlexandre TORGUE 	writel(data | GMAC_HI_REG_AE, ioaddr + high);
23748863ce5SAlexandre TORGUE 	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
23848863ce5SAlexandre TORGUE 	writel(data, ioaddr + low);
23948863ce5SAlexandre TORGUE }
24048863ce5SAlexandre TORGUE 
24148863ce5SAlexandre TORGUE /* Enable disable MAC RX/TX */
stmmac_dwmac4_set_mac(void __iomem * ioaddr,bool enable)24248863ce5SAlexandre TORGUE void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
24348863ce5SAlexandre TORGUE {
24448863ce5SAlexandre TORGUE 	u32 value = readl(ioaddr + GMAC_CONFIG);
245284779dbSVincent Whitchurch 	u32 old_val = value;
24648863ce5SAlexandre TORGUE 
24748863ce5SAlexandre TORGUE 	if (enable)
24848863ce5SAlexandre TORGUE 		value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
24948863ce5SAlexandre TORGUE 	else
25048863ce5SAlexandre TORGUE 		value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
25148863ce5SAlexandre TORGUE 
252284779dbSVincent Whitchurch 	if (value != old_val)
25348863ce5SAlexandre TORGUE 		writel(value, ioaddr + GMAC_CONFIG);
25448863ce5SAlexandre TORGUE }
25548863ce5SAlexandre TORGUE 
stmmac_dwmac4_get_mac_addr(void __iomem * ioaddr,unsigned char * addr,unsigned int high,unsigned int low)25648863ce5SAlexandre TORGUE void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
25748863ce5SAlexandre TORGUE 				unsigned int high, unsigned int low)
25848863ce5SAlexandre TORGUE {
25948863ce5SAlexandre TORGUE 	unsigned int hi_addr, lo_addr;
26048863ce5SAlexandre TORGUE 
26148863ce5SAlexandre TORGUE 	/* Read the MAC address from the hardware */
26248863ce5SAlexandre TORGUE 	hi_addr = readl(ioaddr + high);
26348863ce5SAlexandre TORGUE 	lo_addr = readl(ioaddr + low);
26448863ce5SAlexandre TORGUE 
26548863ce5SAlexandre TORGUE 	/* Extract the MAC address from the high and low words */
26648863ce5SAlexandre TORGUE 	addr[0] = lo_addr & 0xff;
26748863ce5SAlexandre TORGUE 	addr[1] = (lo_addr >> 8) & 0xff;
26848863ce5SAlexandre TORGUE 	addr[2] = (lo_addr >> 16) & 0xff;
26948863ce5SAlexandre TORGUE 	addr[3] = (lo_addr >> 24) & 0xff;
27048863ce5SAlexandre TORGUE 	addr[4] = hi_addr & 0xff;
27148863ce5SAlexandre TORGUE 	addr[5] = (hi_addr >> 8) & 0xff;
27248863ce5SAlexandre TORGUE }
273