/** @file Copyright (c) 2016 - 2017, Socionext Inc. All rights reserved.
Copyright (c) 2017, Linaro, Ltd. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "ogma_config.h" #include "ogma_internal.h" #include "ogma_basic_access.h" #include "ogma_misc_internal.h" #include ogma_global_t ogma_global = { OGMA_FALSE, 0, NULL }; static const ogma_uint32 hw_ver_reg_addr = OGMA_REG_ADDR_HW_VER; static const ogma_uint32 mc_ver_reg_addr = OGMA_REG_ADDR_MC_VER; static const ogma_uint32 desc_ring_irq_status_reg_addr[OGMA_DESC_RING_ID_MAX + 1] = { OGMA_REG_ADDR_NRM_TX_STATUS, OGMA_REG_ADDR_NRM_RX_STATUS, }; static const ogma_uint32 desc_ring_config_reg_addr[OGMA_DESC_RING_ID_MAX + 1] = { OGMA_REG_ADDR_NRM_TX_CONFIG, OGMA_REG_ADDR_NRM_RX_CONFIG, }; /* Internal function definition*/ #ifndef OGMA_CONFIG_DISABLE_CLK_CTRL STATIC void ogma_set_clk_en_reg ( ogma_ctrl_t *ctrl_p ); #endif /* OGMA_CONFIG_DISABLE_CLK_CTRL */ STATIC void ogma_global_init ( void); STATIC ogma_err_t ogma_probe_hardware ( void *base_addr ); STATIC void ogma_reset_hardware ( ogma_ctrl_t *ctrl_p ); STATIC void ogma_set_microcode( ogma_ctrl_t *ctrl_p, const void *dma_hm_mc_addr, ogma_uint32 dma_hm_mc_len, const void *dma_mh_mc_addr, ogma_uint32 dma_mh_mc_len, const void *pktc_mc_addr, ogma_uint32 pktc_mc_len ); STATIC ogma_uint32 ogma_calc_pkt_ctrl_reg_param ( const ogma_pkt_ctrl_param_t *pkt_ctrl_param_p ); STATIC void ogma_internal_terminate ( ogma_ctrl_t *ctrl_p ); #ifdef OGMA_CONFIG_DISABLE_CLK_CTRL #define ogma_set_clk_en_reg( ctrl_p) #else /* OGMA_CONFIG_DISABLE_CLK_CTRL */ STATIC void ogma_set_clk_en_reg ( ogma_ctrl_t *ctrl_p ) { ogma_uint32 value = 0; if ( ctrl_p->clk_ctrl.mac_req_num != 0) { value |= OGMA_CLK_EN_REG_DOM_G; } ogma_write_reg( ctrl_p, OGMA_REG_ADDR_CLK_EN, value); } #endif /* OGMA_CONFIG_DISABLE_CLK_CTRL */ void ogma_push_clk_req ( ogma_ctrl_t *ctrl_p, ogma_uint32 domain ) { pfdep_hard_lock_ctx_t clk_ctrl_hard_lock_ctx; pfdep_acquire_hard_lock ( &ctrl_p->clk_ctrl_hard_lock, &clk_ctrl_hard_lock_ctx); if ( ( domain & OGMA_CLK_EN_REG_DOM_G) != 0) { ++ctrl_p->clk_ctrl.mac_req_num; } ogma_set_clk_en_reg( ctrl_p); pfdep_release_hard_lock( &ctrl_p->clk_ctrl_hard_lock, &clk_ctrl_hard_lock_ctx); } void ogma_pop_clk_req( ogma_ctrl_t *ctrl_p, ogma_uint32 domain ) { pfdep_hard_lock_ctx_t clk_ctrl_hard_lock_ctx; pfdep_acquire_hard_lock( &ctrl_p->clk_ctrl_hard_lock, &clk_ctrl_hard_lock_ctx); if ( ( domain & OGMA_CLK_EN_REG_DOM_G) != 0) { --ctrl_p->clk_ctrl.mac_req_num; } ogma_set_clk_en_reg( ctrl_p); pfdep_release_hard_lock( &ctrl_p->clk_ctrl_hard_lock, &clk_ctrl_hard_lock_ctx); } /* Internal function */ STATIC void ogma_global_init ( void) { ogma_global.valid_flag = OGMA_TRUE; } STATIC ogma_err_t ogma_probe_hardware ( void *base_addr ) { ogma_uint32 value; /* Read HW_VER Register */ value = pfdep_iomem_read((void *) ((pfdep_cpu_addr_t)base_addr + (OGMA_REG_ADDR_HW_VER << 2))); if ( value != OGMA_VER_NETSEC) { pfdep_print(PFDEP_DEBUG_LEVEL_WARNING, "Hardware version check warning. Actual:0x%08x, Expected:0x%08x\n", (unsigned int)value, (unsigned int)OGMA_VER_NETSEC); } if ( OGMA_VER_MAJOR_NUM(value) != OGMA_VER_MAJOR_NUM(OGMA_VER_NETSEC) ) { pfdep_print(PFDEP_DEBUG_LEVEL_FATAL, "Hardware Major version check failed. Actual:0x%08x, Expected:0x%08x\n", (unsigned int)OGMA_VER_MAJOR_NUM(value), (unsigned int)OGMA_VER_MAJOR_NUM(OGMA_VER_NETSEC) ); return OGMA_ERR_NOTAVAIL; } /* Print hardware version information. */ pfdep_print(PFDEP_DEBUG_LEVEL_NOTICE, "NETSEC found. Hardware version: %08x\n", value); return OGMA_ERR_OK; } STATIC void ogma_reset_hardware ( ogma_ctrl_t *ctrl_p ) { ogma_write_reg( ctrl_p, OGMA_REG_ADDR_CLK_EN, OGMA_CLK_EN_REG_DOM_ALL); /* * Stop dma engines if cores are enabled */ if (ogma_read_reg(ctrl_p, OGMA_REG_ADDR_DIS_CORE) == 0) { ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMA_HM_CTRL, OGMA_DMA_CTRL_REG_STOP); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMA_MH_CTRL, OGMA_DMA_CTRL_REG_STOP); while ( ( ogma_read_reg( ctrl_p, OGMA_REG_ADDR_DMA_HM_CTRL) & OGMA_DMA_CTRL_REG_STOP) != 0) { ; } while ( ( ogma_read_reg( ctrl_p, OGMA_REG_ADDR_DMA_MH_CTRL) & OGMA_DMA_CTRL_REG_STOP) != 0) { ; } } if ( ctrl_p->param.use_gmac_flag) { /* Reset F_GMAC4MT */ ogma_set_mac_reg( ctrl_p, OGMA_GMAC_REG_ADDR_BMR, OGMA_GMAC_BMR_REG_RESET); } ogma_write_reg( ctrl_p, OGMA_REG_ADDR_SOFT_RST, OGMA_SOFT_RST_REG_RESET); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_SOFT_RST, OGMA_SOFT_RST_REG_RUN); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_COM_INIT, OGMA_COM_INIT_REG_ALL); while (ogma_read_reg(ctrl_p, OGMA_REG_ADDR_COM_INIT) != 0) { ; } if ( ctrl_p->param.use_gmac_flag) { /* MAC desc init */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_MAC_DESC_INIT, OGMA_MAC_DESC_INIT_REG_INIT); /* Wait MAC desc init done */ while ( ( ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_DESC_INIT) & OGMA_MAC_DESC_INIT_REG_INIT) != 0) { ; } /* set MAC_INTF_SEL */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTF_SEL, ctrl_p->param.gmac_config.phy_interface); } } #define OGMA_ROUND_UP(numerator,denominator) (((numerator) + (denominator)) - 1 / (denominator)) STATIC void ogma_set_microcode ( ogma_ctrl_t *ctrl_p, const void *dma_hm_mc_addr, ogma_uint32 dma_hm_mc_len, const void *dma_mh_mc_addr, ogma_uint32 dma_mh_mc_len, const void *pktc_mc_addr, ogma_uint32 pktc_mc_len ) { ogma_uint i; const UINT32 *dmac_hm_cmd_data = (const UINT32 *)dma_hm_mc_addr; const UINT32 *dmac_mh_cmd_data = (const UINT32 *)dma_mh_mc_addr; const UINT32 *core_cmd_data = (const UINT32 *)pktc_mc_addr; /* Loads microcodes to microengines. */ for( i = 0; i < dma_hm_mc_len; i++) { UINT32 data = MmioRead32((UINTN)dmac_hm_cmd_data); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMAC_HM_CMD_BUF, data ); dmac_hm_cmd_data++; } for( i = 0; i < dma_mh_mc_len; i++) { UINT32 data = MmioRead32((UINTN)dmac_mh_cmd_data); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMAC_MH_CMD_BUF, data ); dmac_mh_cmd_data++; } for( i = 0; i < pktc_mc_len; i++) { UINT32 data = MmioRead32((UINTN)core_cmd_data); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKTC_CMD_BUF, data ); core_cmd_data++; } } STATIC ogma_uint32 ogma_calc_pkt_ctrl_reg_param ( const ogma_pkt_ctrl_param_t *pkt_ctrl_param_p ) { ogma_uint32 param = 0; if ( pkt_ctrl_param_p->log_chksum_er_flag) { param |= OGMA_PKT_CTRL_REG_LOG_CHKSUM_ER; } if ( pkt_ctrl_param_p->log_hd_imcomplete_flag) { param |= OGMA_PKT_CTRL_REG_LOG_HD_INCOMPLETE; } if ( pkt_ctrl_param_p->log_hd_er_flag) { param |= OGMA_PKT_CTRL_REG_LOG_HD_ER; } if ( pkt_ctrl_param_p->drp_no_match_flag) { param |= OGMA_PKT_CTRL_REG_DRP_NO_MATCH; } return param; } STATIC void ogma_pre_init_microengine ( ogma_handle_t ogma_handle ) { UINT16 Data; /* Remove dormant settings */ Data = ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) & ~((1U << OGMA_PHY_CONTROL_REG_POWER_DOWN) | (1U << OGMA_PHY_CONTROL_REG_ISOLATE)); ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data); while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) & ((1U << OGMA_PHY_CONTROL_REG_POWER_DOWN) | (1U << OGMA_PHY_CONTROL_REG_ISOLATE))) != 0); /* Put phy in loopback mode to guarantee RXCLK input */ Data |= (1U << OGMA_PHY_CONTROL_REG_LOOPBACK); ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data); while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) & (1U << OGMA_PHY_CONTROL_REG_LOOPBACK)) == 0); } STATIC void ogma_post_init_microengine ( IN ogma_handle_t ogma_handle ) { UINT16 Data; /* Get phy back to normal operation */ Data = ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) & ~(1U << OGMA_PHY_CONTROL_REG_LOOPBACK); ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data); while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) & (1U << OGMA_PHY_CONTROL_REG_LOOPBACK)) != 0); Data |= (1U << OGMA_PHY_CONTROL_REG_RESET); /* Apply software reset */ ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data); while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) & (1U << OGMA_PHY_CONTROL_REG_RESET)) != 0); } ogma_err_t ogma_init ( void *base_addr, pfdep_dev_handle_t dev_handle, const ogma_param_t *param_p, const void *dma_hm_mc_addr, ogma_uint32 dma_hm_mc_len, const void *dma_mh_mc_addr, ogma_uint32 dma_mh_mc_len, const void *pktc_mc_addr, ogma_uint32 pktc_mc_len, ogma_handle_t *ogma_handle_p ) { ogma_int i; ogma_uint32 domain = 0, value; ogma_err_t ogma_err; ogma_ctrl_t *ctrl_p = NULL; ogma_bool inten_reg_hard_lock_init_flag = OGMA_FALSE; ogma_bool clk_ctrl_hard_lock_init_flag = OGMA_FALSE; ogma_bool all_lock_init_done_flag = OGMA_FALSE; pfdep_err_t pfdep_err; if ( ( param_p == NULL) || ( ogma_handle_p == NULL) ) { return OGMA_ERR_PARAM; } if ( ogma_global.list_entry_num + 1 > OGMA_INSTANCE_NUM_MAX) { return OGMA_ERR_INVALID; } if ((! param_p->desc_ring_param[OGMA_DESC_RING_ID_NRM_TX].valid_flag) && (! param_p->desc_ring_param[OGMA_DESC_RING_ID_NRM_RX].valid_flag)) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Please set invalid packet desc_ring_param valid_flag.\n"); return OGMA_ERR_DATA; } if ( param_p->use_gmac_flag) { if ( ( param_p->gmac_config.phy_interface != OGMA_PHY_INTERFACE_GMII) && ( param_p->gmac_config.phy_interface != OGMA_PHY_INTERFACE_RGMII) && ( param_p->gmac_config.phy_interface != OGMA_PHY_INTERFACE_RMII) ) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Please set phy_interface to valid value.\n"); return OGMA_ERR_DATA; } } else { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Please set use_gmac_flag OGMA_TRUE.\n"); return OGMA_ERR_DATA; } if ( param_p->phy_addr >= 32) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "Error: phy_addr out of range\n"); return OGMA_ERR_DATA; } ogma_err = ogma_probe_hardware( base_addr); if ( ogma_err != OGMA_ERR_OK) { return ogma_err; } if ( !ogma_global.valid_flag) { ogma_global_init(); } if ( ( ctrl_p = pfdep_malloc( sizeof( ogma_ctrl_t) ) ) == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to ogma_handle memory allocation.\n"); return OGMA_ERR_ALLOC; } pfdep_memset( ctrl_p, 0, sizeof( ogma_ctrl_t) ); ctrl_p->base_addr = base_addr; ctrl_p->dev_handle = dev_handle; pfdep_memcpy( ( void *)&ctrl_p->param, ( void *)param_p, sizeof( ogma_param_t) ); /* Initialize hardware lock */ pfdep_err = pfdep_init_hard_lock( &ctrl_p->inten_reg_hard_lock); if ( pfdep_err != PFDEP_ERR_OK) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to inten_reg_hard_lock's initialization.\n"); ogma_err = OGMA_ERR_ALLOC; goto err; } inten_reg_hard_lock_init_flag = OGMA_TRUE; pfdep_err = pfdep_init_hard_lock( &ctrl_p->clk_ctrl_hard_lock); if ( pfdep_err != PFDEP_ERR_OK) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to clk_ctrl_hard_lock's initialization.\n"); ogma_err = OGMA_ERR_ALLOC; goto err; } clk_ctrl_hard_lock_init_flag = OGMA_TRUE; all_lock_init_done_flag = OGMA_TRUE; pfdep_err = pfdep_dma_malloc( dev_handle, OGMA_DUMMY_DESC_ENTRY_LEN, &ctrl_p->dummy_desc_entry_addr, &ctrl_p->dummy_desc_entry_phys_addr); if ( pfdep_err != PFDEP_ERR_OK) { ogma_err = OGMA_ERR_ALLOC; pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to dummy_desc_entry's memory allocation.\n"); goto err; } /* clear dummy desc entry */ pfdep_memset( ctrl_p->dummy_desc_entry_addr, 0, OGMA_DUMMY_DESC_ENTRY_LEN); ogma_reset_hardware( ctrl_p); if ( param_p->use_gmac_flag) { domain |= OGMA_CLK_EN_REG_DOM_G; } ogma_push_clk_req( ctrl_p, domain); /* set PKT_CTRL */ value = ogma_calc_pkt_ctrl_reg_param( ¶m_p->pkt_ctrl_param); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_CTRL, value); if ( param_p->use_jumbo_pkt_flag) { ctrl_p->rx_pkt_buf_len = OGMA_RX_JUMBO_PKT_BUF_LEN; value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_CTRL); value |= OGMA_PKT_CTRL_REG_EN_JUMBO; ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_CTRL, value); } else { ctrl_p->rx_pkt_buf_len = OGMA_RX_PKT_BUF_LEN; } /* set pkt desc ring config */ for ( i = 0; i <= OGMA_DESC_RING_ID_MAX; i++) { if ( ctrl_p->param.desc_ring_param[i].valid_flag) { value = ( ctrl_p->param.desc_ring_param[i].tmr_mode_flag << OGMA_REG_DESC_RING_CONFIG_TMR_MODE) | ( ctrl_p->param.desc_ring_param[i].little_endian_flag << OGMA_REG_DESC_RING_CONFIG_DAT_ENDIAN) ; ogma_write_reg( ctrl_p, desc_ring_config_reg_addr[i], value); } } /* set microengines */ ogma_set_microcode(ctrl_p, dma_hm_mc_addr, dma_hm_mc_len, dma_mh_mc_addr, dma_mh_mc_len, pktc_mc_addr, pktc_mc_len); /* alloc desc_ring*/ for( i = 0; i <= OGMA_DESC_RING_ID_MAX; i++) { ogma_err = ogma_alloc_desc_ring( ctrl_p, (ogma_desc_ring_id_t)i); if ( ogma_err != OGMA_ERR_OK) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to ring id NO.%d memory allocation.\n", i); goto err; } } if ( param_p->desc_ring_param[OGMA_DESC_RING_ID_NRM_RX].valid_flag) { if ( ( ogma_err = ogma_setup_rx_desc_ring( ctrl_p, &ctrl_p->desc_ring[OGMA_DESC_RING_ID_NRM_RX] ) ) != OGMA_ERR_OK) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to NRM_RX packet memory allocation.\n"); goto err; } } /* microengines need domain G */ ogma_push_clk_req( ctrl_p, OGMA_CLK_EN_REG_DOM_G); /* set DMA tmr ctrl*/ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMA_TMR_CTRL, ( ogma_uint32)( ( OGMA_CONFIG_CLK_HZ / OGMA_CLK_MHZ) - 1) ); /* * Do pre-initialization tasks for microengine * * In particular, we put phy in loopback mode * in order to make sure RXCLK keeps provided to mac * irrespective of phy link status, * which is required for microengine intialization. * This will be disabled once microengine initialization complete. */ ogma_pre_init_microengine (ctrl_p); /* start microengines */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DIS_CORE, 0); if ( pfdep_msleep(1) != PFDEP_ERR_OK) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to waiting for microcode initialize end.\n"); ogma_err = OGMA_ERR_INTERRUPT; goto err; } /* check microcode load end & start core */ value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS); if ( ( value & OGMA_TOP_IRQ_REG_ME_START) == 0) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_init.\n" "Failed to microcode loading.\n"); ogma_err = OGMA_ERR_INVALID; goto err; } /* * Do post-initialization tasks for microengine * * We put phy in normal mode and apply reset. */ ogma_post_init_microengine (ctrl_p); /* clear microcode load end status */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS, OGMA_TOP_IRQ_REG_ME_START); ogma_pop_clk_req( ctrl_p, OGMA_CLK_EN_REG_DOM_G); ctrl_p->core_enabled_flag = OGMA_TRUE; ctrl_p->next_p = ogma_global.list_head_p; ogma_global.list_head_p = ctrl_p; ++ogma_global.list_entry_num; *ogma_handle_p = ctrl_p; #if 1 { #define OGMA_PKT_CTRL_REG_MODE_TAIKI (1UL << 28) #define OGMA_DMA_MH_CTRL_REG_MODE_TRANS (1UL << 20) #define OGMA_TOP_IRQ_REG_MODE_TRANS_COMP (1UL << 4) #define OGMA_MODE_TRANS_COMP_IRQ_T2N (1UL << 19) /* Read Pkt ctrl register */ value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_CTRL); value |= OGMA_PKT_CTRL_REG_MODE_TAIKI; /* change to noromal mode */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMA_MH_CTRL, OGMA_DMA_MH_CTRL_REG_MODE_TRANS); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_CTRL, value); while ((ogma_read_reg(ctrl_p, OGMA_REG_ADDR_MODE_TRANS_COMP_STATUS) & OGMA_MODE_TRANS_COMP_IRQ_T2N) == 0) { ; } } #endif /* Print microcode version information. */ pfdep_print(PFDEP_DEBUG_LEVEL_NOTICE, "Microcode version: %08x\n", ogma_read_reg( ctrl_p, mc_ver_reg_addr) ); return OGMA_ERR_OK; err: if ( !all_lock_init_done_flag) { if ( clk_ctrl_hard_lock_init_flag) { pfdep_uninit_hard_lock( &ctrl_p->clk_ctrl_hard_lock); } if ( inten_reg_hard_lock_init_flag) { pfdep_uninit_hard_lock( &ctrl_p->inten_reg_hard_lock); } } else { ogma_internal_terminate( ctrl_p); } pfdep_free( ctrl_p); return ogma_err; } STATIC void ogma_internal_terminate ( ogma_ctrl_t *ctrl_p ) { ogma_int i; ogma_reset_hardware( ctrl_p); /* free desc_ring */ for( i = 0; i <= OGMA_DESC_RING_ID_MAX; i++) { ogma_free_desc_ring( ctrl_p, &ctrl_p->desc_ring[i] ); } if ( ctrl_p->dummy_desc_entry_addr != NULL) { pfdep_dma_free( ctrl_p->dev_handle, OGMA_DUMMY_DESC_ENTRY_LEN, ctrl_p->dummy_desc_entry_addr, ctrl_p->dummy_desc_entry_phys_addr); } pfdep_uninit_hard_lock ( &ctrl_p->inten_reg_hard_lock); pfdep_uninit_hard_lock ( &ctrl_p->clk_ctrl_hard_lock); } void ogma_terminate ( ogma_handle_t ogma_handle ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; ogma_ctrl_t *tmp_ctrl_p = NULL, *old_tmp_ctrl_p = NULL; ogma_uint32 domain = 0; if ( ( ctrl_p == NULL) || ( ogma_global.list_entry_num == 0) ) { return; } pfdep_assert( ogma_global.list_head_p != NULL); if ( ctrl_p->param.use_gmac_flag) { domain |= OGMA_CLK_EN_REG_DOM_G; } /* pop domain clock */ ogma_pop_clk_req( ctrl_p, domain); tmp_ctrl_p = ogma_global.list_head_p; while(1) { if ( tmp_ctrl_p == NULL) { /* Could not found ctrl_p specified from the list */ return; } if ( ctrl_p == tmp_ctrl_p) { if ( old_tmp_ctrl_p != NULL) { old_tmp_ctrl_p->next_p = ctrl_p->next_p; } else { ogma_global.list_head_p = ctrl_p->next_p; } break; } old_tmp_ctrl_p = tmp_ctrl_p; tmp_ctrl_p = tmp_ctrl_p->next_p; } ogma_internal_terminate( ctrl_p); --ogma_global.list_entry_num; pfdep_free( ctrl_p); return; } ogma_err_t ogma_enable_top_irq ( ogma_handle_t ogma_handle, ogma_uint32 irq_factor ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { return OGMA_ERR_PARAM; } /* set irq_factor*/ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN_SET, irq_factor); return OGMA_ERR_OK; } ogma_err_t ogma_disable_top_irq ( ogma_handle_t ogma_handle, ogma_uint32 irq_factor ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { return OGMA_ERR_PARAM; } /* clear irq_factor*/ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN_CLR, irq_factor); return OGMA_ERR_OK; } ogma_err_t ogma_enable_desc_ring_irq ( ogma_handle_t ogma_handle, ogma_desc_ring_id_t ring_id, ogma_uint32 irq_factor ) { ogma_err_t ogma_err = OGMA_ERR_OK; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; ogma_desc_ring_t *desc_ring_p; pfdep_err_t pfdep_err; pfdep_soft_lock_ctx_t soft_lock_ctx; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_enable_desc_ring_irq.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } if ( ring_id > OGMA_DESC_RING_ID_MAX) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_enable_desc_ring_irq.\n" "Please select ring id number between 0 and %d.\n", OGMA_DESC_RING_ID_MAX); return OGMA_ERR_PARAM; } if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_enable_desc_ring_irq.\n" "Please select valid desc ring.\n"); return OGMA_ERR_NOTAVAIL; } desc_ring_p = &ctrl_p->desc_ring[ring_id]; /* get soft lock */ pfdep_err = pfdep_acquire_soft_lock ( &desc_ring_p->soft_lock, &soft_lock_ctx); if ( pfdep_err != PFDEP_ERR_OK) { return OGMA_ERR_INTERRUPT; } if ( !desc_ring_p->running_flag) { pfdep_release_soft_lock( &desc_ring_p->soft_lock, &soft_lock_ctx); pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_enable_desc_ring_irq.\n" "Please select running desc ring.\n"); return OGMA_ERR_NOTAVAIL; } /* set irq_factor*/ ogma_write_reg( ctrl_p, desc_ring_irq_inten_set_reg_addr[ring_id], irq_factor); /* free soft_lock*/ pfdep_release_soft_lock( &desc_ring_p->soft_lock, &soft_lock_ctx); return ogma_err; } ogma_err_t ogma_disable_desc_ring_irq ( ogma_handle_t ogma_handle, ogma_desc_ring_id_t ring_id, ogma_uint32 irq_factor ) { ogma_err_t ogma_err = OGMA_ERR_OK; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_disable_desc_ring_irq.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } if ( ring_id > OGMA_DESC_RING_ID_MAX) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_disable_desc_ring_irq.\n" "Please select ring id number between 0 and %d.\n", OGMA_DESC_RING_ID_MAX); return OGMA_ERR_PARAM; } if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_disable_desc_ring_irq.\n" "Please select valid desc ring.\n"); return OGMA_ERR_NOTAVAIL; } /* Clear irq factor*/ ogma_write_reg( ctrl_p, desc_ring_irq_inten_clr_reg_addr[ring_id], irq_factor); return ogma_err; } ogma_err_t ogma_enable_pkt_irq ( ogma_handle_t ogma_handle, ogma_uint32 irq_factor ) { ogma_err_t ogma_err = OGMA_ERR_OK; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { return OGMA_ERR_PARAM; } /* set irq_factor*/ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN_SET, ( irq_factor & OGMA_PKT_IRQ_ALL) ); return ogma_err; } ogma_err_t ogma_disable_pkt_irq ( ogma_handle_t ogma_handle, ogma_uint32 irq_factor ) { ogma_err_t ogma_err = OGMA_ERR_OK; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { return OGMA_ERR_PARAM; } /* clear irq_factor*/ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN_CLR, ( irq_factor & OGMA_PKT_IRQ_ALL) ); return ogma_err; } ogma_uint32 ogma_get_top_irq_enable ( ogma_handle_t ogma_handle ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_top_irq_enable.\n" "Please set valid ogma_handle.\n"); return 0; } value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN); return value; } ogma_uint32 ogma_get_top_irq_status ( ogma_handle_t ogma_handle, ogma_bool mask_flag ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_top_irq_status.\n" "Please set valid ogma_handle.\n"); return 0; } value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS); if ( mask_flag) { value &= ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN); } return value; } ogma_err_t ogma_clear_top_irq_status ( ogma_handle_t ogma_handle, ogma_uint32 value ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_clear_top_irq_status.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } /* Write clear irq top status */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS, ( value & OGMA_TOP_IRQ_REG_ME_START) ); return OGMA_ERR_OK; } ogma_uint32 ogma_get_desc_ring_irq_enable ( ogma_handle_t ogma_handle, ogma_desc_ring_id_t ring_id ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_desc_ring_irq_enable.\n" "Please set valid ogma_handle.\n"); return 0; } if ( ring_id > OGMA_DESC_RING_ID_MAX) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_desc_ring_irq_enable.\n" "Please select ring id number between 0 and %d.\n", OGMA_DESC_RING_ID_MAX); return 0; } if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_desc_ring_irq_enable.\n" "Please select valid desc ring.\n"); return 0; } value = ogma_read_reg( ctrl_p, desc_ring_irq_inten_reg_addr[ring_id] ); return value; } ogma_uint32 ogma_get_desc_ring_irq_status ( ogma_handle_t ogma_handle, ogma_desc_ring_id_t ring_id, ogma_bool mask_flag ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_desc_ring_irq_status.\n" "Please set valid ogma_handle.\n"); return 0; } if ( ring_id > OGMA_DESC_RING_ID_MAX) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_desc_ring_irq_status.\n" "Please select ring id number between 0 and %d.\n", OGMA_DESC_RING_ID_MAX); return 0; } if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_desc_ring_irq_status.\n" "Please select valid desc ring.\n"); return 0; } value = ogma_read_reg( ctrl_p, desc_ring_irq_status_reg_addr[ring_id] ); if ( mask_flag) { value &= ogma_read_reg( ctrl_p, desc_ring_irq_inten_reg_addr[ring_id] ); } return value; } ogma_err_t ogma_clear_desc_ring_irq_status ( ogma_handle_t ogma_handle, ogma_desc_ring_id_t ring_id, ogma_uint32 value ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_clear_desc_ring_irq_status.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } if ( ring_id > OGMA_DESC_RING_ID_MAX) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_clear_desc_ring_irq_status.\n" "Please select ring id number between 0 and %d.\n", OGMA_DESC_RING_ID_MAX); return OGMA_ERR_PARAM; } if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_clear_desc_ring_irq_status.\n" "Please select valid desc ring.\n"); return OGMA_ERR_NOTAVAIL; } /* Write clear descring irq status */ ogma_write_reg( ctrl_p, desc_ring_irq_status_reg_addr[ring_id], ( value & ( OGMA_CH_IRQ_REG_EMPTY | OGMA_CH_IRQ_REG_ERR) ) ); return OGMA_ERR_OK; } ogma_uint32 ogma_get_pkt_irq_enable ( ogma_handle_t ogma_handle ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_pkt_irq_enable.\n" "Please set valid ogma_handle.\n"); return 0; } value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN); value &= OGMA_PKT_IRQ_ALL; return value; } ogma_uint32 ogma_get_pkt_irq_status ( ogma_handle_t ogma_handle, ogma_bool mask_flag ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_pkt_irq_statusnon_clear.\n" "Please set valid ogma_handle.\n"); return 0; } value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_STATUS); if ( mask_flag) { value &= ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN); } return value; } ogma_err_t ogma_clear_pkt_irq_status ( ogma_handle_t ogma_handle, ogma_uint32 value ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_clear_pkt_irq_status.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } /* Write clear irq pkt status */ ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_STATUS, ( value & ( ( OGMA_PKT_IRQ_MAC_ER | OGMA_PKT_IRQ_JUMBO_ER | OGMA_PKT_IRQ_CHKSUM_ER | OGMA_PKT_IRQ_HD_INCOMPLETE | OGMA_PKT_IRQ_HD_ER | OGMA_PKT_IRQ_DRP_NO_MATCH) ) ) ); return OGMA_ERR_OK; } #ifdef OGMA_CONFIG_REC_STAT ogma_err_t ogma_get_stat_info ( ogma_handle_t ogma_handle, ogma_stat_info_t *stat_info_p, ogma_bool clear_flag ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ( ctrl_p == NULL) || (stat_info_p == NULL) ) { return OGMA_ERR_PARAM; } pfdep_memcpy( stat_info_p, &ctrl_p->stat_info, sizeof( ogma_stat_info_t) ); if ( clear_flag) { pfdep_memset( &ctrl_p->stat_info, 0, sizeof( ogma_stat_info_t) ); } return OGMA_ERR_OK; } #endif /* OGMA_CONFIG_REC_STAT */ ogma_uint32 ogma_get_hw_ver ( ogma_handle_t ogma_handle ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { return 0; } value = ogma_read_reg( ctrl_p, hw_ver_reg_addr); return value; } ogma_uint32 ogma_get_mcr_ver ( ogma_handle_t ogma_handle ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { return 0; } value = ogma_read_reg( ctrl_p, mc_ver_reg_addr); return value; } ogma_uint32 ogma_get_mac_irq_enable ( ogma_handle_t ogma_handle ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_ogma_get_mac_irq_enable.\n" "Please set valid ogma_handle.\n"); return 0; } value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN); return value; } ogma_uint32 ogma_get_mac_irq_status ( ogma_handle_t ogma_handle, ogma_bool mask_flag ) { ogma_uint32 value; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_get_mac_irq_status.\n" "Please set valid ogma_handle.\n"); return 0; } value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_STATUS); if ( mask_flag) { value &= ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN); } return value; } ogma_err_t ogma_clear_mac_irq_status ( ogma_handle_t ogma_handle, ogma_uint32 value ) { ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_clear_mac_irq_status.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } /* Commented out because no write-clear bit exists now. */ #if 0 ogma_write_reg( ctrl_p, OGMA_REG_ADDR_MAC_STATUS, ( value & /* T.B.D. */) ); #endif return OGMA_ERR_OK; } ogma_err_t ogma_enable_mac_irq ( ogma_handle_t ogma_handle, ogma_uint32 irq_factor ) { ogma_uint32 value; ogma_err_t ogma_err = OGMA_ERR_OK; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; pfdep_hard_lock_ctx_t inten_reg_hard_lock_ctx; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_enable_mac_irq.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } /* get inten_reg_hard_lock */ pfdep_acquire_hard_lock( &ctrl_p->inten_reg_hard_lock, &inten_reg_hard_lock_ctx); value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN); value |= irq_factor; ogma_write_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN, value); /* free inten_reg_hard_lock*/ pfdep_release_hard_lock( &ctrl_p->inten_reg_hard_lock, &inten_reg_hard_lock_ctx); return ogma_err; } ogma_err_t ogma_disable_mac_irq ( ogma_handle_t ogma_handle, ogma_uint32 irq_factor ) { ogma_uint32 value; ogma_err_t ogma_err = OGMA_ERR_OK; ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle; pfdep_hard_lock_ctx_t inten_reg_hard_lock_ctx; if ( ctrl_p == NULL) { pfdep_print( PFDEP_DEBUG_LEVEL_FATAL, "An error occurred at ogma_disable_mac_irq.\n" "Please set valid ogma_handle.\n"); return OGMA_ERR_PARAM; } /* get inten_reg_hard_lock */ pfdep_acquire_hard_lock( &ctrl_p->inten_reg_hard_lock, &inten_reg_hard_lock_ctx); value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN); value &= (~irq_factor); ogma_write_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN, value); /* free inten_reg_hard_lock*/ pfdep_release_hard_lock( &ctrl_p->inten_reg_hard_lock, &inten_reg_hard_lock_ctx); return ogma_err; }