diff options
author | John Crispin <john@openwrt.org> | 2013-06-21 16:54:37 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2013-06-21 16:54:37 +0000 |
commit | 4ebf19b48fafc8d94e14e4ba779969613b241a6a (patch) | |
tree | 9918f890a8915023b49ea30948beb5d048c333fa /package/platform/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c | |
parent | 44b1688e6c7b4f16f7165fbd560e1183aef69090 (diff) | |
download | upstream-4ebf19b48fafc8d94e14e4ba779969613b241a6a.tar.gz upstream-4ebf19b48fafc8d94e14e4ba779969613b241a6a.tar.bz2 upstream-4ebf19b48fafc8d94e14e4ba779969613b241a6a.zip |
packages: clean up the package folder
Signed-off-by: John Crispin <blogic@openwrt.org>
SVN-Revision: 37007
Diffstat (limited to 'package/platform/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c')
-rw-r--r-- | package/platform/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c | 1080 |
1 files changed, 0 insertions, 1080 deletions
diff --git a/package/platform/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c b/package/platform/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c deleted file mode 100644 index 745eb03321..0000000000 --- a/package/platform/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c +++ /dev/null @@ -1,1080 +0,0 @@ -/****************************************************************************** -** -** FILE NAME : ifxmips_ptm_vdsl.c -** PROJECT : UEIP -** MODULES : PTM -** -** DATE : 7 Jul 2009 -** AUTHOR : Xu Liang -** DESCRIPTION : PTM driver common source file (core functions for VR9) -** COPYRIGHT : Copyright (c) 2006 -** Infineon Technologies AG -** Am Campeon 1-12, 85579 Neubiberg, Germany -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** HISTORY -** $Date $Author $Comment -** 07 JUL 2009 Xu Liang Init Version -*******************************************************************************/ - -#include <linux/version.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/ctype.h> -#include <linux/errno.h> -#include <linux/proc_fs.h> -#include <linux/init.h> -#include <linux/ioctl.h> -#include <linux/etherdevice.h> -#include <linux/interrupt.h> - -#include "ifxmips_ptm_vdsl.h" -#include <lantiq_soc.h> - -#define MODULE_PARM_ARRAY(a, b) module_param_array(a, int, NULL, 0) -#define MODULE_PARM(a, b) module_param(a, int, 0) - -static int wanqos_en = 0; -static int queue_gamma_map[4] = {0xFE, 0x01, 0x00, 0x00}; - -MODULE_PARM(wanqos_en, "i"); -MODULE_PARM_DESC(wanqos_en, "WAN QoS support, 1 - enabled, 0 - disabled."); - -MODULE_PARM_ARRAY(queue_gamma_map, "4-4i"); -MODULE_PARM_DESC(queue_gamma_map, "TX QoS queues mapping to 4 TX Gamma interfaces."); - -extern int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *); -extern int (*ifx_mei_atm_showtime_exit)(void); -extern int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr); - -static int g_showtime = 0; -static void *g_xdata_addr = NULL; - - -#define ENABLE_TMP_DBG 0 - -unsigned long cgu_get_pp32_clock(void) -{ - struct clk *c = clk_get_ppe(); - unsigned long rate = clk_get_rate(c); - clk_put(c); - return rate; -} - -static void ptm_setup(struct net_device *, int); -static struct net_device_stats *ptm_get_stats(struct net_device *); -static int ptm_open(struct net_device *); -static int ptm_stop(struct net_device *); - static unsigned int ptm_poll(int, unsigned int); - static int ptm_napi_poll(struct napi_struct *, int); -static int ptm_hard_start_xmit(struct sk_buff *, struct net_device *); -static int ptm_ioctl(struct net_device *, struct ifreq *, int); -static void ptm_tx_timeout(struct net_device *); - -static inline struct sk_buff* alloc_skb_rx(void); -static inline struct sk_buff* alloc_skb_tx(unsigned int); -static inline struct sk_buff *get_skb_pointer(unsigned int); -static inline int get_tx_desc(unsigned int, unsigned int *); - -/* - * Mailbox handler and signal function - */ -static irqreturn_t mailbox_irq_handler(int, void *); - -/* - * Tasklet to Handle Swap Descriptors - */ -static void do_swap_desc_tasklet(unsigned long); - - -/* - * Init & clean-up functions - */ -static inline int init_priv_data(void); -static inline void clear_priv_data(void); -static inline int init_tables(void); -static inline void clear_tables(void); - -static int g_wanqos_en = 0; - -static int g_queue_gamma_map[4]; - -static struct ptm_priv_data g_ptm_priv_data; - -static struct net_device_ops g_ptm_netdev_ops = { - .ndo_get_stats = ptm_get_stats, - .ndo_open = ptm_open, - .ndo_stop = ptm_stop, - .ndo_start_xmit = ptm_hard_start_xmit, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_do_ioctl = ptm_ioctl, - .ndo_tx_timeout = ptm_tx_timeout, -}; - -static struct net_device *g_net_dev[1] = {0}; -static char *g_net_dev_name[1] = {"ptm0"}; - -static int g_ptm_prio_queue_map[8]; - -static DECLARE_TASKLET(g_swap_desc_tasklet, do_swap_desc_tasklet, 0); - - -unsigned int ifx_ptm_dbg_enable = DBG_ENABLE_MASK_ERR; - -/* - * #################################### - * Local Function - * #################################### - */ - -static void ptm_setup(struct net_device *dev, int ndev) -{ - dev->netdev_ops = &g_ptm_netdev_ops; - netif_napi_add(dev, &g_ptm_priv_data.itf[ndev].napi, ptm_napi_poll, 16); - dev->watchdog_timeo = ETH_WATCHDOG_TIMEOUT; - - dev->dev_addr[0] = 0x00; - dev->dev_addr[1] = 0x20; - dev->dev_addr[2] = 0xda; - dev->dev_addr[3] = 0x86; - dev->dev_addr[4] = 0x23; - dev->dev_addr[5] = 0x75 + ndev; -} - -static struct net_device_stats *ptm_get_stats(struct net_device *dev) -{ - struct net_device_stats *s; - - if ( dev != g_net_dev[0] ) - return NULL; -s = &g_ptm_priv_data.itf[0].stats; - - return s; -} - -static int ptm_open(struct net_device *dev) -{ - ASSERT(dev == g_net_dev[0], "incorrect device"); - - napi_enable(&g_ptm_priv_data.itf[0].napi); - - IFX_REG_W32_MASK(0, 1, MBOX_IGU1_IER); - - netif_start_queue(dev); - - return 0; -} - -static int ptm_stop(struct net_device *dev) -{ - ASSERT(dev == g_net_dev[0], "incorrect device"); - - IFX_REG_W32_MASK(1 | (1 << 17), 0, MBOX_IGU1_IER); - - napi_disable(&g_ptm_priv_data.itf[0].napi); - - netif_stop_queue(dev); - - return 0; -} - -static unsigned int ptm_poll(int ndev, unsigned int work_to_do) -{ - unsigned int work_done = 0; - volatile struct rx_descriptor *desc; - struct rx_descriptor reg_desc; - struct sk_buff *skb, *new_skb; - - ASSERT(ndev >= 0 && ndev < ARRAY_SIZE(g_net_dev), "ndev = %d (wrong value)", ndev); - - while ( work_done < work_to_do ) { - desc = &WAN_RX_DESC_BASE[g_ptm_priv_data.itf[0].rx_desc_pos]; - if ( desc->own /* || !desc->c */ ) // if PP32 hold descriptor or descriptor not completed - break; - if ( ++g_ptm_priv_data.itf[0].rx_desc_pos == WAN_RX_DESC_NUM ) - g_ptm_priv_data.itf[0].rx_desc_pos = 0; - - reg_desc = *desc; - skb = get_skb_pointer(reg_desc.dataptr); - ASSERT(skb != NULL, "invalid pointer skb == NULL"); - - new_skb = alloc_skb_rx(); - if ( new_skb != NULL ) { - skb_reserve(skb, reg_desc.byteoff); - skb_put(skb, reg_desc.datalen); - - // parse protocol header - skb->dev = g_net_dev[0]; - skb->protocol = eth_type_trans(skb, skb->dev); - - g_net_dev[0]->last_rx = jiffies; - - netif_receive_skb(skb); - - g_ptm_priv_data.itf[0].stats.rx_packets++; - g_ptm_priv_data.itf[0].stats.rx_bytes += reg_desc.datalen; - - reg_desc.dataptr = (unsigned int)new_skb->data & 0x0FFFFFFF; - reg_desc.byteoff = RX_HEAD_MAC_ADDR_ALIGNMENT; - } - - reg_desc.datalen = RX_MAX_BUFFER_SIZE - RX_HEAD_MAC_ADDR_ALIGNMENT; - reg_desc.own = 1; - reg_desc.c = 0; - - /* write discriptor to memory */ - *((volatile unsigned int *)desc + 1) = *((unsigned int *)®_desc + 1); - wmb(); - *(volatile unsigned int *)desc = *(unsigned int *)®_desc; - - work_done++; - } - - return work_done; -} - -static int ptm_napi_poll(struct napi_struct *napi, int budget) -{ - int ndev = 0; - unsigned int work_done; - - work_done = ptm_poll(ndev, budget); - - // interface down - if ( !netif_running(napi->dev) ) { - napi_complete(napi); - return work_done; - } - - // clear interrupt - IFX_REG_W32_MASK(0, 1, MBOX_IGU1_ISRC); - // no more traffic - if ( WAN_RX_DESC_BASE[g_ptm_priv_data.itf[0].rx_desc_pos].own ) { // if PP32 hold descriptor - napi_complete(napi); - IFX_REG_W32_MASK(0, 1, MBOX_IGU1_IER); - return work_done; - } - - // next round - return work_done; -} - -static int ptm_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned int f_full; - int desc_base; - volatile struct tx_descriptor *desc; - struct tx_descriptor reg_desc = {0}; - struct sk_buff *skb_to_free; - unsigned int byteoff; - - ASSERT(dev == g_net_dev[0], "incorrect device"); - - if ( !g_showtime ) { - err("not in showtime"); - goto PTM_HARD_START_XMIT_FAIL; - } - - /* allocate descriptor */ - desc_base = get_tx_desc(0, &f_full); - if ( f_full ) { - dev->trans_start = jiffies; - netif_stop_queue(dev); - - IFX_REG_W32_MASK(0, 1 << 17, MBOX_IGU1_ISRC); - IFX_REG_W32_MASK(0, 1 << 17, MBOX_IGU1_IER); - } - if ( desc_base < 0 ) - goto PTM_HARD_START_XMIT_FAIL; - desc = &CPU_TO_WAN_TX_DESC_BASE[desc_base]; - - byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); - if ( skb_headroom(skb) < sizeof(struct sk_buff *) + byteoff || skb_cloned(skb) ) { - struct sk_buff *new_skb; - - ASSERT(skb_headroom(skb) >= sizeof(struct sk_buff *) + byteoff, "skb_headroom(skb) < sizeof(struct sk_buff *) + byteoff"); - ASSERT(!skb_cloned(skb), "skb is cloned"); - - new_skb = alloc_skb_tx(skb->len); - if ( new_skb == NULL ) { - dbg("no memory"); - goto ALLOC_SKB_TX_FAIL; - } - skb_put(new_skb, skb->len); - memcpy(new_skb->data, skb->data, skb->len); - dev_kfree_skb_any(skb); - skb = new_skb; - byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); - /* write back to physical memory */ - dma_cache_wback((unsigned long)skb->data, skb->len); - } - - *(struct sk_buff **)((unsigned int)skb->data - byteoff - sizeof(struct sk_buff *)) = skb; - /* write back to physical memory */ - dma_cache_wback((unsigned long)skb->data - byteoff - sizeof(struct sk_buff *), skb->len + byteoff + sizeof(struct sk_buff *)); - - /* free previous skb */ - skb_to_free = get_skb_pointer(desc->dataptr); - if ( skb_to_free != NULL ) - dev_kfree_skb_any(skb_to_free); - - /* update descriptor */ - reg_desc.small = 0; - reg_desc.dataptr = (unsigned int)skb->data & (0x0FFFFFFF ^ (DATA_BUFFER_ALIGNMENT - 1)); - reg_desc.datalen = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; - reg_desc.qid = g_ptm_prio_queue_map[skb->priority > 7 ? 7 : skb->priority]; - reg_desc.byteoff = byteoff; - reg_desc.own = 1; - reg_desc.c = 1; - reg_desc.sop = reg_desc.eop = 1; - - /* update MIB */ - g_ptm_priv_data.itf[0].stats.tx_packets++; - g_ptm_priv_data.itf[0].stats.tx_bytes += reg_desc.datalen; - - /* write discriptor to memory */ - *((volatile unsigned int *)desc + 1) = *((unsigned int *)®_desc + 1); - wmb(); - *(volatile unsigned int *)desc = *(unsigned int *)®_desc; - - dev->trans_start = jiffies; - - return 0; - -ALLOC_SKB_TX_FAIL: -PTM_HARD_START_XMIT_FAIL: - dev_kfree_skb_any(skb); - g_ptm_priv_data.itf[0].stats.tx_dropped++; - return 0; -} - -static int ptm_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - ASSERT(dev == g_net_dev[0], "incorrect device"); - - switch ( cmd ) - { - case IFX_PTM_MIB_CW_GET: - ((PTM_CW_IF_ENTRY_T *)ifr->ifr_data)->ifRxNoIdleCodewords = IFX_REG_R32(DREG_AR_CELL0) + IFX_REG_R32(DREG_AR_CELL1); - ((PTM_CW_IF_ENTRY_T *)ifr->ifr_data)->ifRxIdleCodewords = IFX_REG_R32(DREG_AR_IDLE_CNT0) + IFX_REG_R32(DREG_AR_IDLE_CNT1); - ((PTM_CW_IF_ENTRY_T *)ifr->ifr_data)->ifRxCodingViolation = IFX_REG_R32(DREG_AR_CVN_CNT0) + IFX_REG_R32(DREG_AR_CVN_CNT1) + IFX_REG_R32(DREG_AR_CVNP_CNT0) + IFX_REG_R32(DREG_AR_CVNP_CNT1); - ((PTM_CW_IF_ENTRY_T *)ifr->ifr_data)->ifTxNoIdleCodewords = IFX_REG_R32(DREG_AT_CELL0) + IFX_REG_R32(DREG_AT_CELL1); - ((PTM_CW_IF_ENTRY_T *)ifr->ifr_data)->ifTxIdleCodewords = IFX_REG_R32(DREG_AT_IDLE_CNT0) + IFX_REG_R32(DREG_AT_IDLE_CNT1); - break; - case IFX_PTM_MIB_FRAME_GET: - { - PTM_FRAME_MIB_T data = {0}; - int i; - - data.RxCorrect = IFX_REG_R32(DREG_AR_HEC_CNT0) + IFX_REG_R32(DREG_AR_HEC_CNT1) + IFX_REG_R32(DREG_AR_AIIDLE_CNT0) + IFX_REG_R32(DREG_AR_AIIDLE_CNT1); - for ( i = 0; i < 4; i++ ) - data.RxDropped += WAN_RX_MIB_TABLE(i)->wrx_dropdes_pdu; - for ( i = 0; i < 8; i++ ) - data.TxSend += WAN_TX_MIB_TABLE(i)->wtx_total_pdu; - - *((PTM_FRAME_MIB_T *)ifr->ifr_data) = data; - } - break; - case IFX_PTM_CFG_GET: - // use bear channel 0 preemption gamma interface settings - ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxEthCrcPresent = 1; - ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxEthCrcCheck = RX_GAMMA_ITF_CFG(0)->rx_eth_fcs_ver_dis == 0 ? 1 : 0; - ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxTcCrcCheck = RX_GAMMA_ITF_CFG(0)->rx_tc_crc_ver_dis == 0 ? 1 : 0;; - ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxTcCrcLen = RX_GAMMA_ITF_CFG(0)->rx_tc_crc_size == 0 ? 0 : (RX_GAMMA_ITF_CFG(0)->rx_tc_crc_size * 16); - ((IFX_PTM_CFG_T *)ifr->ifr_data)->TxEthCrcGen = TX_GAMMA_ITF_CFG(0)->tx_eth_fcs_gen_dis == 0 ? 1 : 0; - ((IFX_PTM_CFG_T *)ifr->ifr_data)->TxTcCrcGen = TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size == 0 ? 0 : 1; - ((IFX_PTM_CFG_T *)ifr->ifr_data)->TxTcCrcLen = TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size == 0 ? 0 : (TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size * 16); - break; - case IFX_PTM_CFG_SET: - { - int i; - - for ( i = 0; i < 4; i++ ) { - RX_GAMMA_ITF_CFG(i)->rx_eth_fcs_ver_dis = ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxEthCrcCheck ? 0 : 1; - - RX_GAMMA_ITF_CFG(0)->rx_tc_crc_ver_dis = ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxTcCrcCheck ? 0 : 1; - - switch ( ((IFX_PTM_CFG_T *)ifr->ifr_data)->RxTcCrcLen ) { - case 16: RX_GAMMA_ITF_CFG(0)->rx_tc_crc_size = 1; break; - case 32: RX_GAMMA_ITF_CFG(0)->rx_tc_crc_size = 2; break; - default: RX_GAMMA_ITF_CFG(0)->rx_tc_crc_size = 0; - } - - TX_GAMMA_ITF_CFG(0)->tx_eth_fcs_gen_dis = ((IFX_PTM_CFG_T *)ifr->ifr_data)->TxEthCrcGen ? 0 : 1; - - if ( ((IFX_PTM_CFG_T *)ifr->ifr_data)->TxTcCrcGen ) { - switch ( ((IFX_PTM_CFG_T *)ifr->ifr_data)->TxTcCrcLen ) { - case 16: TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size = 1; break; - case 32: TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size = 2; break; - default: TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size = 0; - } - } - else - TX_GAMMA_ITF_CFG(0)->tx_tc_crc_size = 0; - } - } - break; - case IFX_PTM_MAP_PKT_PRIO_TO_Q: - { - struct ppe_prio_q_map cmd; - - if ( copy_from_user(&cmd, ifr->ifr_data, sizeof(cmd)) ) - return -EFAULT; - - if ( cmd.pkt_prio < 0 || cmd.pkt_prio >= ARRAY_SIZE(g_ptm_prio_queue_map) ) - return -EINVAL; - - if ( cmd.qid < 0 || cmd.qid >= g_wanqos_en ) - return -EINVAL; - - g_ptm_prio_queue_map[cmd.pkt_prio] = cmd.qid; - } - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static void ptm_tx_timeout(struct net_device *dev) -{ - ASSERT(dev == g_net_dev[0], "incorrect device"); - - /* disable TX irq, release skb when sending new packet */ - IFX_REG_W32_MASK(1 << 17, 0, MBOX_IGU1_IER); - - /* wake up TX queue */ - netif_wake_queue(dev); - - return; -} - -static inline struct sk_buff* alloc_skb_rx(void) -{ - struct sk_buff *skb; - - /* allocate memroy including trailer and padding */ - skb = dev_alloc_skb(RX_MAX_BUFFER_SIZE + DATA_BUFFER_ALIGNMENT); - if ( skb != NULL ) { - /* must be burst length alignment and reserve two more bytes for MAC address alignment */ - if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 ) - skb_reserve(skb, ~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1)); - /* pub skb in reserved area "skb->data - 4" */ - *((struct sk_buff **)skb->data - 1) = skb; - wmb(); - /* write back and invalidate cache */ - dma_cache_wback_inv((unsigned long)skb->data - sizeof(skb), sizeof(skb)); - /* invalidate cache */ - dma_cache_inv((unsigned long)skb->data, (unsigned int)skb->end - (unsigned int)skb->data); - } - - return skb; -} - -static inline struct sk_buff* alloc_skb_tx(unsigned int size) -{ - struct sk_buff *skb; - - /* allocate memory including padding */ - size = RX_MAX_BUFFER_SIZE; - size = (size + DATA_BUFFER_ALIGNMENT - 1) & ~(DATA_BUFFER_ALIGNMENT - 1); - skb = dev_alloc_skb(size + DATA_BUFFER_ALIGNMENT); - /* must be burst length alignment */ - if ( skb != NULL ) - skb_reserve(skb, ~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1)); - return skb; -} - -static inline struct sk_buff *get_skb_pointer(unsigned int dataptr) -{ - unsigned int skb_dataptr; - struct sk_buff *skb; - - // usually, CPE memory is less than 256M bytes - // so NULL means invalid pointer - if ( dataptr == 0 ) { - dbg("dataptr is 0, it's supposed to be invalid pointer"); - return NULL; - } - - skb_dataptr = (dataptr - 4) | KSEG1; - skb = *(struct sk_buff **)skb_dataptr; - - ASSERT((unsigned int)skb >= KSEG0, "invalid skb - skb = %#08x, dataptr = %#08x", (unsigned int)skb, dataptr); - ASSERT((((unsigned int)skb->data & (0x0FFFFFFF ^ (DATA_BUFFER_ALIGNMENT - 1))) | KSEG1) == (dataptr | KSEG1), "invalid skb - skb = %#08x, skb->data = %#08x, dataptr = %#08x", (unsigned int)skb, (unsigned int)skb->data, dataptr); - - return skb; -} - -static inline int get_tx_desc(unsigned int itf, unsigned int *f_full) -{ - int desc_base = -1; - struct ptm_itf *p_itf = &g_ptm_priv_data.itf[0]; - - // assume TX is serial operation - // no protection provided - - *f_full = 1; - - if ( CPU_TO_WAN_TX_DESC_BASE[p_itf->tx_desc_pos].own == 0 ) { - desc_base = p_itf->tx_desc_pos; - if ( ++(p_itf->tx_desc_pos) == CPU_TO_WAN_TX_DESC_NUM ) - p_itf->tx_desc_pos = 0; - if ( CPU_TO_WAN_TX_DESC_BASE[p_itf->tx_desc_pos].own == 0 ) - *f_full = 0; - } - - return desc_base; -} - -static irqreturn_t mailbox_irq_handler(int irq, void *dev_id) -{ - unsigned int isr; - int i; - - isr = IFX_REG_R32(MBOX_IGU1_ISR); - IFX_REG_W32(isr, MBOX_IGU1_ISRC); - isr &= IFX_REG_R32(MBOX_IGU1_IER); - - if (isr & BIT(0)) { - IFX_REG_W32_MASK(1, 0, MBOX_IGU1_IER); - napi_schedule(&g_ptm_priv_data.itf[0].napi); -#if defined(ENABLE_TMP_DBG) && ENABLE_TMP_DBG - { - volatile struct rx_descriptor *desc = &WAN_RX_DESC_BASE[g_ptm_priv_data.itf[0].rx_desc_pos]; - - if ( desc->own ) { // PP32 hold - err("invalid interrupt"); - } - } -#endif - } - if (isr & BIT(16)) { - IFX_REG_W32_MASK(1 << 16, 0, MBOX_IGU1_IER); - tasklet_hi_schedule(&g_swap_desc_tasklet); - } - if (isr & BIT(17)) { - IFX_REG_W32_MASK(1 << 17, 0, MBOX_IGU1_IER); - netif_wake_queue(g_net_dev[0]); - } - - return IRQ_HANDLED; -} - -static void do_swap_desc_tasklet(unsigned long arg) -{ - int budget = 32; - volatile struct tx_descriptor *desc; - struct sk_buff *skb; - unsigned int byteoff; - - while ( budget-- > 0 ) { - if ( WAN_SWAP_DESC_BASE[g_ptm_priv_data.itf[0].tx_swap_desc_pos].own ) // if PP32 hold descriptor - break; - - desc = &WAN_SWAP_DESC_BASE[g_ptm_priv_data.itf[0].tx_swap_desc_pos]; - if ( ++g_ptm_priv_data.itf[0].tx_swap_desc_pos == WAN_SWAP_DESC_NUM ) - g_ptm_priv_data.itf[0].tx_swap_desc_pos = 0; - - skb = get_skb_pointer(desc->dataptr); - if ( skb != NULL ) - dev_kfree_skb_any(skb); - - skb = alloc_skb_tx(RX_MAX_BUFFER_SIZE); - if ( skb == NULL ) - panic("can't allocate swap buffer for PPE firmware use\n"); - byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); - *(struct sk_buff **)((unsigned int)skb->data - byteoff - sizeof(struct sk_buff *)) = skb; - - desc->dataptr = (unsigned int)skb->data & 0x0FFFFFFF; - desc->own = 1; - } - - // clear interrupt - IFX_REG_W32_MASK(0, 16, MBOX_IGU1_ISRC); - // no more skb to be replaced - if ( WAN_SWAP_DESC_BASE[g_ptm_priv_data.itf[0].tx_swap_desc_pos].own ) { // if PP32 hold descriptor - IFX_REG_W32_MASK(0, 1 << 16, MBOX_IGU1_IER); - return; - } - - tasklet_hi_schedule(&g_swap_desc_tasklet); - return; -} - - -static inline int ifx_ptm_version(char *buf) -{ - int len = 0; - unsigned int major, minor; - - ifx_ptm_get_fw_ver(&major, &minor); - - len += sprintf(buf + len, "PTM %d.%d.%d", IFX_PTM_VER_MAJOR, IFX_PTM_VER_MID, IFX_PTM_VER_MINOR); - len += sprintf(buf + len, " PTM (E1) firmware version %d.%d\n", major, minor); - - return len; -} - -static inline int init_priv_data(void) -{ - int i, j; - - g_wanqos_en = wanqos_en ? wanqos_en : 8; - if ( g_wanqos_en > 8 ) - g_wanqos_en = 8; - - for ( i = 0; i < ARRAY_SIZE(g_queue_gamma_map); i++ ) - { - g_queue_gamma_map[i] = queue_gamma_map[i] & ((1 << g_wanqos_en) - 1); - for ( j = 0; j < i; j++ ) - g_queue_gamma_map[i] &= ~g_queue_gamma_map[j]; - } - - memset(&g_ptm_priv_data, 0, sizeof(g_ptm_priv_data)); - - { - int max_packet_priority = ARRAY_SIZE(g_ptm_prio_queue_map); - int tx_num_q; - int q_step, q_accum, p_step; - - tx_num_q = __ETH_WAN_TX_QUEUE_NUM; - q_step = tx_num_q - 1; - p_step = max_packet_priority - 1; - for ( j = 0, q_accum = 0; j < max_packet_priority; j++, q_accum += q_step ) - g_ptm_prio_queue_map[j] = q_step - (q_accum + (p_step >> 1)) / p_step; - } - - return 0; -} - -static inline void clear_priv_data(void) -{ -} - -static inline int init_tables(void) -{ - struct sk_buff *skb_pool[WAN_RX_DESC_NUM] = {0}; - struct cfg_std_data_len cfg_std_data_len = {0}; - struct tx_qos_cfg tx_qos_cfg = {0}; - struct psave_cfg psave_cfg = {0}; - struct eg_bwctrl_cfg eg_bwctrl_cfg = {0}; - struct test_mode test_mode = {0}; - struct rx_bc_cfg rx_bc_cfg = {0}; - struct tx_bc_cfg tx_bc_cfg = {0}; - struct gpio_mode gpio_mode = {0}; - struct gpio_wm_cfg gpio_wm_cfg = {0}; - struct rx_gamma_itf_cfg rx_gamma_itf_cfg = {0}; - struct tx_gamma_itf_cfg tx_gamma_itf_cfg = {0}; - struct wtx_qos_q_desc_cfg wtx_qos_q_desc_cfg = {0}; - struct rx_descriptor rx_desc = {0}; - struct tx_descriptor tx_desc = {0}; - int i; - - for ( i = 0; i < WAN_RX_DESC_NUM; i++ ) { - skb_pool[i] = alloc_skb_rx(); - if ( skb_pool[i] == NULL ) - goto ALLOC_SKB_RX_FAIL; - } - - cfg_std_data_len.byte_off = RX_HEAD_MAC_ADDR_ALIGNMENT; // this field replaces byte_off in rx descriptor of VDSL ingress - cfg_std_data_len.data_len = 1600; - *CFG_STD_DATA_LEN = cfg_std_data_len; - - tx_qos_cfg.time_tick = cgu_get_pp32_clock() / 62500; // 16 * (cgu_get_pp32_clock() / 1000000) - tx_qos_cfg.overhd_bytes = 0; - tx_qos_cfg.eth1_eg_qnum = __ETH_WAN_TX_QUEUE_NUM; - tx_qos_cfg.eth1_burst_chk = 1; - tx_qos_cfg.eth1_qss = 0; - tx_qos_cfg.shape_en = 0; // disable - tx_qos_cfg.wfq_en = 0; // strict priority - *TX_QOS_CFG = tx_qos_cfg; - - psave_cfg.start_state = 0; - psave_cfg.sleep_en = 1; // enable sleep mode - *PSAVE_CFG = psave_cfg; - - eg_bwctrl_cfg.fdesc_wm = 16; - eg_bwctrl_cfg.class_len = 128; - *EG_BWCTRL_CFG = eg_bwctrl_cfg; - - //*GPIO_ADDR = (unsigned int)IFX_GPIO_P0_OUT; - *GPIO_ADDR = (unsigned int)0x00000000; // disabled by default - - gpio_mode.gpio_bit_bc1 = 2; - gpio_mode.gpio_bit_bc0 = 1; - gpio_mode.gpio_bc1_en = 0; - gpio_mode.gpio_bc0_en = 0; - *GPIO_MODE = gpio_mode; - - gpio_wm_cfg.stop_wm_bc1 = 2; - gpio_wm_cfg.start_wm_bc1 = 4; - gpio_wm_cfg.stop_wm_bc0 = 2; - gpio_wm_cfg.start_wm_bc0 = 4; - *GPIO_WM_CFG = gpio_wm_cfg; - - test_mode.mib_clear_mode = 0; - test_mode.test_mode = 0; - *TEST_MODE = test_mode; - - rx_bc_cfg.local_state = 0; - rx_bc_cfg.remote_state = 0; - rx_bc_cfg.to_false_th = 7; - rx_bc_cfg.to_looking_th = 3; - *RX_BC_CFG(0) = rx_bc_cfg; - *RX_BC_CFG(1) = rx_bc_cfg; - - tx_bc_cfg.fill_wm = 2; - tx_bc_cfg.uflw_wm = 2; - *TX_BC_CFG(0) = tx_bc_cfg; - *TX_BC_CFG(1) = tx_bc_cfg; - - rx_gamma_itf_cfg.receive_state = 0; - rx_gamma_itf_cfg.rx_min_len = 60; - rx_gamma_itf_cfg.rx_pad_en = 1; - rx_gamma_itf_cfg.rx_eth_fcs_ver_dis = 0; - rx_gamma_itf_cfg.rx_rm_eth_fcs = 1; - rx_gamma_itf_cfg.rx_tc_crc_ver_dis = 0; - rx_gamma_itf_cfg.rx_tc_crc_size = 1; - rx_gamma_itf_cfg.rx_eth_fcs_result = 0xC704DD7B; - rx_gamma_itf_cfg.rx_tc_crc_result = 0x1D0F1D0F; - rx_gamma_itf_cfg.rx_crc_cfg = 0x2500; - rx_gamma_itf_cfg.rx_eth_fcs_init_value = 0xFFFFFFFF; - rx_gamma_itf_cfg.rx_tc_crc_init_value = 0x0000FFFF; - rx_gamma_itf_cfg.rx_max_len_sel = 0; - rx_gamma_itf_cfg.rx_edit_num2 = 0; - rx_gamma_itf_cfg.rx_edit_pos2 = 0; - rx_gamma_itf_cfg.rx_edit_type2 = 0; - rx_gamma_itf_cfg.rx_edit_en2 = 0; - rx_gamma_itf_cfg.rx_edit_num1 = 0; - rx_gamma_itf_cfg.rx_edit_pos1 = 0; - rx_gamma_itf_cfg.rx_edit_type1 = 0; - rx_gamma_itf_cfg.rx_edit_en1 = 0; - rx_gamma_itf_cfg.rx_inserted_bytes_1l = 0; - rx_gamma_itf_cfg.rx_inserted_bytes_1h = 0; - rx_gamma_itf_cfg.rx_inserted_bytes_2l = 0; - rx_gamma_itf_cfg.rx_inserted_bytes_2h = 0; - rx_gamma_itf_cfg.rx_len_adj = -6; - for ( i = 0; i < 4; i++ ) - *RX_GAMMA_ITF_CFG(i) = rx_gamma_itf_cfg; - - tx_gamma_itf_cfg.tx_len_adj = 6; - tx_gamma_itf_cfg.tx_crc_off_adj = 6; - tx_gamma_itf_cfg.tx_min_len = 0; - tx_gamma_itf_cfg.tx_eth_fcs_gen_dis = 0; - tx_gamma_itf_cfg.tx_tc_crc_size = 1; - tx_gamma_itf_cfg.tx_crc_cfg = 0x2F00; - tx_gamma_itf_cfg.tx_eth_fcs_init_value = 0xFFFFFFFF; - tx_gamma_itf_cfg.tx_tc_crc_init_value = 0x0000FFFF; - for ( i = 0; i < ARRAY_SIZE(g_queue_gamma_map); i++ ) { - tx_gamma_itf_cfg.queue_mapping = g_queue_gamma_map[i]; - *TX_GAMMA_ITF_CFG(i) = tx_gamma_itf_cfg; - } - - for ( i = 0; i < __ETH_WAN_TX_QUEUE_NUM; i++ ) { - wtx_qos_q_desc_cfg.length = WAN_TX_DESC_NUM; - wtx_qos_q_desc_cfg.addr = __ETH_WAN_TX_DESC_BASE(i); - *WTX_QOS_Q_DESC_CFG(i) = wtx_qos_q_desc_cfg; - } - - // default TX queue QoS config is all ZERO - - // TX Ctrl K Table - IFX_REG_W32(0x90111293, TX_CTRL_K_TABLE(0)); - IFX_REG_W32(0x14959617, TX_CTRL_K_TABLE(1)); - IFX_REG_W32(0x18999A1B, TX_CTRL_K_TABLE(2)); - IFX_REG_W32(0x9C1D1E9F, TX_CTRL_K_TABLE(3)); - IFX_REG_W32(0xA02122A3, TX_CTRL_K_TABLE(4)); - IFX_REG_W32(0x24A5A627, TX_CTRL_K_TABLE(5)); - IFX_REG_W32(0x28A9AA2B, TX_CTRL_K_TABLE(6)); - IFX_REG_W32(0xAC2D2EAF, TX_CTRL_K_TABLE(7)); - IFX_REG_W32(0x30B1B233, TX_CTRL_K_TABLE(8)); - IFX_REG_W32(0xB43536B7, TX_CTRL_K_TABLE(9)); - IFX_REG_W32(0xB8393ABB, TX_CTRL_K_TABLE(10)); - IFX_REG_W32(0x3CBDBE3F, TX_CTRL_K_TABLE(11)); - IFX_REG_W32(0xC04142C3, TX_CTRL_K_TABLE(12)); - IFX_REG_W32(0x44C5C647, TX_CTRL_K_TABLE(13)); - IFX_REG_W32(0x48C9CA4B, TX_CTRL_K_TABLE(14)); - IFX_REG_W32(0xCC4D4ECF, TX_CTRL_K_TABLE(15)); - - // init RX descriptor - rx_desc.own = 1; - rx_desc.c = 0; - rx_desc.sop = 1; - rx_desc.eop = 1; - rx_desc.byteoff = RX_HEAD_MAC_ADDR_ALIGNMENT; - rx_desc.datalen = RX_MAX_BUFFER_SIZE - RX_HEAD_MAC_ADDR_ALIGNMENT; - for ( i = 0; i < WAN_RX_DESC_NUM; i++ ) { - rx_desc.dataptr = (unsigned int)skb_pool[i]->data & 0x0FFFFFFF; - WAN_RX_DESC_BASE[i] = rx_desc; - } - - // init TX descriptor - tx_desc.own = 0; - tx_desc.c = 0; - tx_desc.sop = 1; - tx_desc.eop = 1; - tx_desc.byteoff = 0; - tx_desc.qid = 0; - tx_desc.datalen = 0; - tx_desc.small = 0; - tx_desc.dataptr = 0; - for ( i = 0; i < CPU_TO_WAN_TX_DESC_NUM; i++ ) - CPU_TO_WAN_TX_DESC_BASE[i] = tx_desc; - for ( i = 0; i < WAN_TX_DESC_NUM_TOTAL; i++ ) - WAN_TX_DESC_BASE(0)[i] = tx_desc; - - // init Swap descriptor - for ( i = 0; i < WAN_SWAP_DESC_NUM; i++ ) - WAN_SWAP_DESC_BASE[i] = tx_desc; - - // init fastpath TX descriptor - tx_desc.own = 1; - for ( i = 0; i < FASTPATH_TO_WAN_TX_DESC_NUM; i++ ) - FASTPATH_TO_WAN_TX_DESC_BASE[i] = tx_desc; - - return 0; - -ALLOC_SKB_RX_FAIL: - while ( i-- > 0 ) - dev_kfree_skb_any(skb_pool[i]); - return -1; -} - -static inline void clear_tables(void) -{ - struct sk_buff *skb; - int i, j; - - for ( i = 0; i < WAN_RX_DESC_NUM; i++ ) { - skb = get_skb_pointer(WAN_RX_DESC_BASE[i].dataptr); - if ( skb != NULL ) - dev_kfree_skb_any(skb); - } - - for ( i = 0; i < CPU_TO_WAN_TX_DESC_NUM; i++ ) { - skb = get_skb_pointer(CPU_TO_WAN_TX_DESC_BASE[i].dataptr); - if ( skb != NULL ) - dev_kfree_skb_any(skb); - } - - for ( j = 0; j < 8; j++ ) - for ( i = 0; i < WAN_TX_DESC_NUM; i++ ) { - skb = get_skb_pointer(WAN_TX_DESC_BASE(j)[i].dataptr); - if ( skb != NULL ) - dev_kfree_skb_any(skb); - } - - for ( i = 0; i < WAN_SWAP_DESC_NUM; i++ ) { - skb = get_skb_pointer(WAN_SWAP_DESC_BASE[i].dataptr); - if ( skb != NULL ) - dev_kfree_skb_any(skb); - } - - for ( i = 0; i < FASTPATH_TO_WAN_TX_DESC_NUM; i++ ) { - skb = get_skb_pointer(FASTPATH_TO_WAN_TX_DESC_BASE[i].dataptr); - if ( skb != NULL ) - dev_kfree_skb_any(skb); - } -} - -static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr) -{ - ASSERT(port_cell != NULL, "port_cell is NULL"); - ASSERT(xdata_addr != NULL, "xdata_addr is NULL"); - - // TODO: ReTX set xdata_addr - g_xdata_addr = xdata_addr; - - g_showtime = 1; - - IFX_REG_W32(0x0F, UTP_CFG); - - //#ifdef CONFIG_VR9 - // IFX_REG_W32_MASK(1 << 17, 0, FFSM_CFG0); - //#endif - - printk("enter showtime\n"); - - return 0; -} - -static int ptm_showtime_exit(void) -{ - if ( !g_showtime ) - return -1; - - //#ifdef CONFIG_VR9 - // IFX_REG_W32_MASK(0, 1 << 17, FFSM_CFG0); - //#endif - - IFX_REG_W32(0x00, UTP_CFG); - - g_showtime = 0; - - // TODO: ReTX clean state - g_xdata_addr = NULL; - - printk("leave showtime\n"); - - return 0; -} - - - -static int ifx_ptm_init(void) -{ - int ret; - int i; - char ver_str[128]; - struct port_cell_info port_cell = {0}; - - ret = init_priv_data(); - if ( ret != 0 ) { - err("INIT_PRIV_DATA_FAIL"); - goto INIT_PRIV_DATA_FAIL; - } - - ifx_ptm_init_chip(); - ret = init_tables(); - if ( ret != 0 ) { - err("INIT_TABLES_FAIL"); - goto INIT_TABLES_FAIL; - } - - for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) { - g_net_dev[i] = alloc_netdev(0, g_net_dev_name[i], ether_setup); - if ( g_net_dev[i] == NULL ) - goto ALLOC_NETDEV_FAIL; - ptm_setup(g_net_dev[i], i); - } - - for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) { - ret = register_netdev(g_net_dev[i]); - if ( ret != 0 ) - goto REGISTER_NETDEV_FAIL; - } - - /* register interrupt handler */ - ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, IRQF_DISABLED, "ptm_mailbox_isr", &g_ptm_priv_data); - if ( ret ) { - if ( ret == -EBUSY ) { - err("IRQ may be occupied by other driver, please reconfig to disable it."); - } - else { - err("request_irq fail"); - } - goto REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL; - } - disable_irq(PPE_MAILBOX_IGU1_INT); - - ret = ifx_pp32_start(0); - if ( ret ) { - err("ifx_pp32_start fail!"); - goto PP32_START_FAIL; - } - IFX_REG_W32(1 << 16, MBOX_IGU1_IER); // enable SWAP interrupt - IFX_REG_W32(~0, MBOX_IGU1_ISRC); - - enable_irq(PPE_MAILBOX_IGU1_INT); - - ifx_mei_atm_showtime_check(&g_showtime, &port_cell, &g_xdata_addr); - - ifx_mei_atm_showtime_enter = ptm_showtime_enter; - ifx_mei_atm_showtime_exit = ptm_showtime_exit; - - ifx_ptm_version(ver_str); - printk(KERN_INFO "%s", ver_str); - - printk("ifxmips_ptm: PTM init succeed\n"); - - return 0; - -PP32_START_FAIL: - free_irq(PPE_MAILBOX_IGU1_INT, &g_ptm_priv_data); -REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL: - i = ARRAY_SIZE(g_net_dev); -REGISTER_NETDEV_FAIL: - while ( i-- ) - unregister_netdev(g_net_dev[i]); - i = ARRAY_SIZE(g_net_dev); -ALLOC_NETDEV_FAIL: - while ( i-- ) { - free_netdev(g_net_dev[i]); - g_net_dev[i] = NULL; - } -INIT_TABLES_FAIL: -INIT_PRIV_DATA_FAIL: - clear_priv_data(); - printk("ifxmips_ptm: PTM init failed\n"); - return ret; -} - -static void __exit ifx_ptm_exit(void) -{ - int i; - ifx_mei_atm_showtime_enter = NULL; - ifx_mei_atm_showtime_exit = NULL; - - - ifx_pp32_stop(0); - - free_irq(PPE_MAILBOX_IGU1_INT, &g_ptm_priv_data); - - for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) - unregister_netdev(g_net_dev[i]); - - for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) { - free_netdev(g_net_dev[i]); - g_net_dev[i] = NULL; - } - - clear_tables(); - - ifx_ptm_uninit_chip(); - - clear_priv_data(); -} - -#ifndef MODULE -static int __init wanqos_en_setup(char *line) -{ - wanqos_en = simple_strtoul(line, NULL, 0); - - if ( wanqos_en < 1 || wanqos_en > 8 ) - wanqos_en = 0; - - return 0; -} - -static int __init queue_gamma_map_setup(char *line) -{ - char *p; - int i; - - for ( i = 0, p = line; i < ARRAY_SIZE(queue_gamma_map) && isxdigit(*p); i++ ) - { - queue_gamma_map[i] = simple_strtoul(p, &p, 0); - if ( *p == ',' || *p == ';' || *p == ':' ) - p++; - } - - return 0; -} -#endif -module_init(ifx_ptm_init); -module_exit(ifx_ptm_exit); -#ifndef MODULE - __setup("wanqos_en=", wanqos_en_setup); - __setup("queue_gamma_map=", queue_gamma_map_setup); -#endif - -MODULE_LICENSE("GPL"); |