From 9fc29db116d147adbee0ad07b0e72a657f961305 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Mon, 26 Oct 2015 19:47:44 +0800 Subject: [PATCH] net/fm: Add support for 64-bit platforms The FMan IM driver is developed for 32-bit platfroms and isn't friendly to 64-bit platforms, so do the minimal refactor: 1. Refine the MURAM management and access. 2. Correct the initialization and operations for QDs and BDs. Signed-off-by: Hou Zhiqiang Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 61 ++++++++++++++++++++++++++++++-------------- drivers/net/fm/fm.c | 20 +++++++++------ drivers/net/fm/fm.h | 12 ++++----- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 368d554475..8ecfd069cc 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -108,12 +108,12 @@ static int tgec_is_fibre(struct eth_device *dev) static u16 muram_readw(u16 *addr) { - u32 base = (u32)addr & ~0x3; - u32 val32 = in_be32((u32 *)base); + ulong base = (ulong)addr & ~0x3UL; + u32 val32 = in_be32((void *)base); int byte_pos; u16 ret; - byte_pos = (u32)addr & 0x3; + byte_pos = (ulong)addr & 0x3UL; if (byte_pos) ret = (u16)(val32 & 0x0000ffff); else @@ -124,18 +124,18 @@ static u16 muram_readw(u16 *addr) static void muram_writew(u16 *addr, u16 val) { - u32 base = (u32)addr & ~0x3; - u32 org32 = in_be32((u32 *)base); + ulong base = (ulong)addr & ~0x3UL; + u32 org32 = in_be32((void *)base); u32 val32; int byte_pos; - byte_pos = (u32)addr & 0x3; + byte_pos = (ulong)addr & 0x3UL; if (byte_pos) val32 = (org32 & 0xffff0000) | val; else val32 = (org32 & 0x0000ffff) | ((u32)val << 16); - out_be32((u32 *)base, val32); + out_be32((void *)base, val32); } static void bmi_rx_port_disable(struct fm_bmi_rx_port *rx_port) @@ -199,6 +199,8 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) u32 pram_page_offset; void *rx_bd_ring_base; void *rx_buf_pool; + u32 bd_ring_base_lo, bd_ring_base_hi; + u32 buf_lo, buf_hi; struct fm_port_bd *rxbd; struct fm_port_qd *rxqd; struct fm_bmi_rx_port *bmi_rx_port = fm_eth->rx_port; @@ -207,10 +209,15 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); + if (!pram) { + printf("%s: No muram for Rx global parameter\n", __func__); + return 0; + } + fm_eth->rx_pram = pram; /* parameter page offset to MURAM */ - pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); + pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ out_be32(&pram->mode, PRAM_MODE_GLOBAL); @@ -234,6 +241,7 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) if (!rx_buf_pool) return 0; memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE); + debug("%s: rx_buf_pool = %p\n", __func__, rx_buf_pool); /* save them to fm_eth */ fm_eth->rx_bd_ring = rx_bd_ring_base; @@ -245,17 +253,22 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) for (i = 0; i < RX_BD_RING_SIZE; i++) { muram_writew(&rxbd->status, RxBD_EMPTY); muram_writew(&rxbd->len, 0); - muram_writew(&rxbd->buf_ptr_hi, 0); - out_be32(&rxbd->buf_ptr_lo, (u32)rx_buf_pool + - i * MAX_RXBUF_LEN); + buf_hi = upper_32_bits(virt_to_phys(rx_buf_pool + + i * MAX_RXBUF_LEN)); + buf_lo = lower_32_bits(virt_to_phys(rx_buf_pool + + i * MAX_RXBUF_LEN)); + muram_writew(&rxbd->buf_ptr_hi, (u16)buf_hi); + out_be32(&rxbd->buf_ptr_lo, buf_lo); rxbd++; } /* set the Rx queue descriptor */ rxqd = &pram->rxqd; muram_writew(&rxqd->gen, 0); - muram_writew(&rxqd->bd_ring_base_hi, 0); - out_be32(&rxqd->bd_ring_base_lo, (u32)rx_bd_ring_base); + bd_ring_base_hi = upper_32_bits(virt_to_phys(rx_bd_ring_base)); + bd_ring_base_lo = lower_32_bits(virt_to_phys(rx_bd_ring_base)); + muram_writew(&rxqd->bd_ring_base_hi, (u16)bd_ring_base_hi); + out_be32(&rxqd->bd_ring_base_lo, bd_ring_base_lo); muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); muram_writew(&rxqd->offset_in, 0); @@ -272,6 +285,7 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) struct fm_port_global_pram *pram; u32 pram_page_offset; void *tx_bd_ring_base; + u32 bd_ring_base_lo, bd_ring_base_hi; struct fm_port_bd *txbd; struct fm_port_qd *txqd; struct fm_bmi_tx_port *bmi_tx_port = fm_eth->tx_port; @@ -280,10 +294,14 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); + if (!pram) { + printf("%s: No muram for Tx global parameter\n", __func__); + return 0; + } fm_eth->tx_pram = pram; /* parameter page offset to MURAM */ - pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); + pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ out_be32(&pram->mode, PRAM_MODE_GLOBAL); @@ -314,8 +332,10 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) /* set the Tx queue decriptor */ txqd = &pram->txqd; - muram_writew(&txqd->bd_ring_base_hi, 0); - out_be32(&txqd->bd_ring_base_lo, (u32)tx_bd_ring_base); + bd_ring_base_hi = upper_32_bits(virt_to_phys(tx_bd_ring_base)); + bd_ring_base_lo = lower_32_bits(virt_to_phys(tx_bd_ring_base)); + muram_writew(&txqd->bd_ring_base_hi, (u16)bd_ring_base_hi); + out_be32(&txqd->bd_ring_base_lo, bd_ring_base_lo); muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); muram_writew(&txqd->offset_in, 0); @@ -480,8 +500,8 @@ static int fm_eth_send(struct eth_device *dev, void *buf, int len) } } /* setup TxBD */ - muram_writew(&txbd->buf_ptr_hi, 0); - out_be32(&txbd->buf_ptr_lo, (u32)buf); + muram_writew(&txbd->buf_ptr_hi, (u16)upper_32_bits(virt_to_phys(buf))); + out_be32(&txbd->buf_ptr_lo, lower_32_bits(virt_to_phys(buf))); muram_writew(&txbd->len, len); sync(); muram_writew(&txbd->status, TxBD_READY | TxBD_LAST); @@ -522,6 +542,7 @@ static int fm_eth_recv(struct eth_device *dev) struct fm_port_global_pram *pram; struct fm_port_bd *rxbd, *rxbd_base; u16 status, len; + u32 buf_lo, buf_hi; u8 *data; u16 offset_out; int ret = 1; @@ -533,7 +554,9 @@ static int fm_eth_recv(struct eth_device *dev) while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { - data = (u8 *)in_be32(&rxbd->buf_ptr_lo); + buf_hi = muram_readw(&rxbd->buf_ptr_hi); + buf_lo = in_be32(&rxbd->buf_ptr_lo); + data = (u8 *)((ulong)(buf_hi << 16) << 16 | buf_lo); len = muram_readw(&rxbd->len); net_process_received_packet(data, len); } else { diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index eb0eb3d5da..df5db723ba 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -22,21 +22,22 @@ struct fm_muram muram[CONFIG_SYS_NUM_FMAN]; -u32 fm_muram_base(int fm_idx) +void *fm_muram_base(int fm_idx) { return muram[fm_idx].base; } -u32 fm_muram_alloc(int fm_idx, u32 size, u32 align) +void *fm_muram_alloc(int fm_idx, size_t size, ulong align) { - u32 ret; - u32 align_mask, off; - u32 save; + void *ret; + ulong align_mask; + size_t off; + void *save; align_mask = align - 1; save = muram[fm_idx].alloc; - off = save & align_mask; + off = (ulong)save & align_mask; if (off != 0) muram[fm_idx].alloc += (align - off); off = size & align_mask; @@ -45,6 +46,7 @@ u32 fm_muram_alloc(int fm_idx, u32 size, u32 align) if ((muram[fm_idx].alloc + size) >= muram[fm_idx].top) { muram[fm_idx].alloc = save; printf("%s: run out of ram.\n", __func__); + return NULL; } ret = muram[fm_idx].alloc; @@ -56,7 +58,7 @@ u32 fm_muram_alloc(int fm_idx, u32 size, u32 align) static void fm_init_muram(int fm_idx, void *reg) { - u32 base = (u32)reg; + void *base = reg; muram[fm_idx].base = base; muram[fm_idx].size = CONFIG_SYS_FM_MURAM_SIZE; @@ -256,7 +258,9 @@ static void fm_init_fpm(struct fm_fpm *fpm) static int fm_init_bmi(int fm_idx, struct fm_bmi_common *bmi) { int blk, i, port_id; - u32 val, offset, base; + u32 val; + size_t offset; + void *base; /* alloc free buffer pool in MURAM */ base = fm_muram_alloc(fm_idx, FM_FREE_POOL_SIZE, FM_FREE_POOL_ALIGN); diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h index a9691c635a..73c525e3d7 100644 --- a/drivers/net/fm/fm.h +++ b/drivers/net/fm/fm.h @@ -26,10 +26,10 @@ #define MIIM_TIMEOUT 0xFFFF struct fm_muram { - u32 base; - u32 top; - u32 size; - u32 alloc; + void *base; + void *top; + size_t size; + void *alloc; }; #define FM_MURAM_RES_SIZE 0x01000 @@ -95,8 +95,8 @@ struct fm_port_global_pram { #endif #define FM_FREE_POOL_ALIGN 256 -u32 fm_muram_alloc(int fm_idx, u32 size, u32 align); -u32 fm_muram_base(int fm_idx); +void *fm_muram_alloc(int fm_idx, size_t size, ulong align); +void *fm_muram_base(int fm_idx); int fm_init_common(int index, struct ccsr_fman *reg); int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info); phy_interface_t fman_port_enet_if(enum fm_port port);