Path: blob/main/sys/contrib/ncsw/Peripherals/FM/MAC/fman_memac.c
48524 views
/*1* Copyright 2008-2012 Freescale Semiconductor Inc.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions are met:5* * Redistributions of source code must retain the above copyright6* notice, this list of conditions and the following disclaimer.7* * Redistributions in binary form must reproduce the above copyright8* notice, this list of conditions and the following disclaimer in the9* documentation and/or other materials provided with the distribution.10* * Neither the name of Freescale Semiconductor nor the11* names of its contributors may be used to endorse or promote products12* derived from this software without specific prior written permission.13*14*15* ALTERNATIVELY, this software may be distributed under the terms of the16* GNU General Public License ("GPL") as published by the Free Software17* Foundation, either version 2 of that License or (at your option) any18* later version.19*20* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY21* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED22* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE23* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY24* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES25* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;26* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND27* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT28* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/313233#include "fsl_fman_memac.h"343536uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask)37{38return ioread32be(®s->ievent) & ev_mask;39}4041uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs)42{43return ioread32be(®s->imask);44}4546void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask)47{48iowrite32be(ev_mask, ®s->ievent);49}5051void fman_memac_set_promiscuous(struct memac_regs *regs, bool val)52{53uint32_t tmp;5455tmp = ioread32be(®s->command_config);5657if (val)58tmp |= CMD_CFG_PROMIS_EN;59else60tmp &= ~CMD_CFG_PROMIS_EN;6162iowrite32be(tmp, ®s->command_config);63}6465void fman_memac_clear_addr_in_paddr(struct memac_regs *regs,66uint8_t paddr_num)67{68if (paddr_num == 0) {69iowrite32be(0, ®s->mac_addr0.mac_addr_l);70iowrite32be(0, ®s->mac_addr0.mac_addr_u);71} else {72iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_l);73iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_u);74}75}7677void fman_memac_add_addr_in_paddr(struct memac_regs *regs,78uint8_t *adr,79uint8_t paddr_num)80{81uint32_t tmp0, tmp1;8283tmp0 = (uint32_t)(adr[0] |84adr[1] << 8 |85adr[2] << 16 |86adr[3] << 24);87tmp1 = (uint32_t)(adr[4] | adr[5] << 8);8889if (paddr_num == 0) {90iowrite32be(tmp0, ®s->mac_addr0.mac_addr_l);91iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u);92} else {93iowrite32be(tmp0, ®s->mac_addr[paddr_num-1].mac_addr_l);94iowrite32be(tmp1, ®s->mac_addr[paddr_num-1].mac_addr_u);95}96}9798void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx)99{100uint32_t tmp;101102tmp = ioread32be(®s->command_config);103104if (apply_rx)105tmp |= CMD_CFG_RX_EN;106107if (apply_tx)108tmp |= CMD_CFG_TX_EN;109110iowrite32be(tmp, ®s->command_config);111}112113void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx)114{115uint32_t tmp;116117tmp = ioread32be(®s->command_config);118119if (apply_rx)120tmp &= ~CMD_CFG_RX_EN;121122if (apply_tx)123tmp &= ~CMD_CFG_TX_EN;124125iowrite32be(tmp, ®s->command_config);126}127128void fman_memac_reset_stat(struct memac_regs *regs)129{130uint32_t tmp;131132tmp = ioread32be(®s->statn_config);133134tmp |= STATS_CFG_CLR;135136iowrite32be(tmp, ®s->statn_config);137138while (ioread32be(®s->statn_config) & STATS_CFG_CLR);139}140141void fman_memac_reset(struct memac_regs *regs)142{143uint32_t tmp;144145tmp = ioread32be(®s->command_config);146147tmp |= CMD_CFG_SW_RESET;148149iowrite32be(tmp, ®s->command_config);150151while (ioread32be(®s->command_config) & CMD_CFG_SW_RESET);152}153154int fman_memac_init(struct memac_regs *regs,155struct memac_cfg *cfg,156enum enet_interface enet_interface,157enum enet_speed enet_speed,158bool slow_10g_if,159uint32_t exceptions)160{161uint32_t tmp;162163/* Config */164tmp = 0;165if (cfg->wan_mode_enable)166tmp |= CMD_CFG_WAN_MODE;167if (cfg->promiscuous_mode_enable)168tmp |= CMD_CFG_PROMIS_EN;169if (cfg->pause_forward_enable)170tmp |= CMD_CFG_PAUSE_FWD;171if (cfg->pause_ignore)172tmp |= CMD_CFG_PAUSE_IGNORE;173if (cfg->tx_addr_ins_enable)174tmp |= CMD_CFG_TX_ADDR_INS;175if (cfg->loopback_enable)176tmp |= CMD_CFG_LOOPBACK_EN;177if (cfg->cmd_frame_enable)178tmp |= CMD_CFG_CNT_FRM_EN;179if (cfg->send_idle_enable)180tmp |= CMD_CFG_SEND_IDLE;181if (cfg->no_length_check_enable)182tmp |= CMD_CFG_NO_LEN_CHK;183if (cfg->rx_sfd_any)184tmp |= CMD_CFG_SFD_ANY;185if (cfg->pad_enable)186tmp |= CMD_CFG_TX_PAD_EN;187if (cfg->wake_on_lan)188tmp |= CMD_CFG_MG;189190tmp |= CMD_CFG_CRC_FWD;191192iowrite32be(tmp, ®s->command_config);193194/* Max Frame Length */195iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm);196197/* Pause Time */198iowrite32be((uint32_t)cfg->pause_quanta, ®s->pause_quanta[0]);199iowrite32be((uint32_t)0, ®s->pause_thresh[0]);200201/* IF_MODE */202tmp = 0;203switch (enet_interface) {204case E_ENET_IF_XGMII:205case E_ENET_IF_XFI:206tmp |= IF_MODE_XGMII;207break;208default:209tmp |= IF_MODE_GMII;210if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable)211tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;212}213iowrite32be(tmp, ®s->if_mode);214215/* TX_FIFO_SECTIONS */216tmp = 0;217if (enet_interface == E_ENET_IF_XGMII ||218enet_interface == E_ENET_IF_XFI) {219if(slow_10g_if) {220tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G |221TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);222} else {223tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G |224TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);225}226} else {227tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G |228TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G);229}230iowrite32be(tmp, ®s->tx_fifo_sections);231232/* clear all pending events and set-up interrupts */233fman_memac_ack_event(regs, 0xffffffff);234fman_memac_set_exception(regs, exceptions, TRUE);235236return 0;237}238239void fman_memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable)240{241uint32_t tmp;242243tmp = ioread32be(®s->imask);244if (enable)245tmp |= val;246else247tmp &= ~val;248249iowrite32be(tmp, ®s->imask);250}251252void fman_memac_reset_filter_table(struct memac_regs *regs)253{254uint32_t i;255for (i = 0; i < 64; i++)256iowrite32be(i & ~HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl);257}258259void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc)260{261iowrite32be(crc | HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl);262}263264void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val)265{266iowrite32be(val, ®s->hashtable_ctrl);267}268269uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs)270{271uint32_t tmp;272273tmp = ioread32be(®s->maxfrm);274275return(uint16_t)tmp;276}277278279void fman_memac_set_tx_pause_frames(struct memac_regs *regs,280uint8_t priority,281uint16_t pause_time,282uint16_t thresh_time)283{284uint32_t tmp;285286tmp = ioread32be(®s->tx_fifo_sections);287288if (priority == 0xff) {289GET_TX_EMPTY_DEFAULT_VALUE(tmp);290iowrite32be(tmp, ®s->tx_fifo_sections);291292tmp = ioread32be(®s->command_config);293tmp &= ~CMD_CFG_PFC_MODE;294priority = 0;295} else {296GET_TX_EMPTY_PFC_VALUE(tmp);297iowrite32be(tmp, ®s->tx_fifo_sections);298299tmp = ioread32be(®s->command_config);300tmp |= CMD_CFG_PFC_MODE;301}302303iowrite32be(tmp, ®s->command_config);304305tmp = ioread32be(®s->pause_quanta[priority / 2]);306if (priority % 2)307tmp &= 0x0000FFFF;308else309tmp &= 0xFFFF0000;310tmp |= ((uint32_t)pause_time << (16 * (priority % 2)));311iowrite32be(tmp, ®s->pause_quanta[priority / 2]);312313tmp = ioread32be(®s->pause_thresh[priority / 2]);314if (priority % 2)315tmp &= 0x0000FFFF;316else317tmp &= 0xFFFF0000;318tmp |= ((uint32_t)thresh_time<<(16 * (priority % 2)));319iowrite32be(tmp, ®s->pause_thresh[priority / 2]);320}321322void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable)323{324uint32_t tmp;325326tmp = ioread32be(®s->command_config);327if (enable)328tmp |= CMD_CFG_PAUSE_IGNORE;329else330tmp &= ~CMD_CFG_PAUSE_IGNORE;331332iowrite32be(tmp, ®s->command_config);333}334335void fman_memac_set_wol(struct memac_regs *regs, bool enable)336{337uint32_t tmp;338339tmp = ioread32be(®s->command_config);340341if (enable)342tmp |= CMD_CFG_MG;343else344tmp &= ~CMD_CFG_MG;345346iowrite32be(tmp, ®s->command_config);347}348349#define GET_MEMAC_CNTR_64(bn) \350(ioread32be(®s->bn ## _l) | \351((uint64_t)ioread32be(®s->bn ## _u) << 32))352353uint64_t fman_memac_get_counter(struct memac_regs *regs,354enum memac_counters reg_name)355{356uint64_t ret_val;357358switch (reg_name) {359case E_MEMAC_COUNTER_R64:360ret_val = GET_MEMAC_CNTR_64(r64);361break;362case E_MEMAC_COUNTER_R127:363ret_val = GET_MEMAC_CNTR_64(r127);364break;365case E_MEMAC_COUNTER_R255:366ret_val = GET_MEMAC_CNTR_64(r255);367break;368case E_MEMAC_COUNTER_R511:369ret_val = GET_MEMAC_CNTR_64(r511);370break;371case E_MEMAC_COUNTER_R1023:372ret_val = GET_MEMAC_CNTR_64(r1023);373break;374case E_MEMAC_COUNTER_R1518:375ret_val = GET_MEMAC_CNTR_64(r1518);376break;377case E_MEMAC_COUNTER_R1519X:378ret_val = GET_MEMAC_CNTR_64(r1519x);379break;380case E_MEMAC_COUNTER_RFRG:381ret_val = GET_MEMAC_CNTR_64(rfrg);382break;383case E_MEMAC_COUNTER_RJBR:384ret_val = GET_MEMAC_CNTR_64(rjbr);385break;386case E_MEMAC_COUNTER_RDRP:387ret_val = GET_MEMAC_CNTR_64(rdrp);388break;389case E_MEMAC_COUNTER_RALN:390ret_val = GET_MEMAC_CNTR_64(raln);391break;392case E_MEMAC_COUNTER_TUND:393ret_val = GET_MEMAC_CNTR_64(tund);394break;395case E_MEMAC_COUNTER_ROVR:396ret_val = GET_MEMAC_CNTR_64(rovr);397break;398case E_MEMAC_COUNTER_RXPF:399ret_val = GET_MEMAC_CNTR_64(rxpf);400break;401case E_MEMAC_COUNTER_TXPF:402ret_val = GET_MEMAC_CNTR_64(txpf);403break;404case E_MEMAC_COUNTER_ROCT:405ret_val = GET_MEMAC_CNTR_64(roct);406break;407case E_MEMAC_COUNTER_RMCA:408ret_val = GET_MEMAC_CNTR_64(rmca);409break;410case E_MEMAC_COUNTER_RBCA:411ret_val = GET_MEMAC_CNTR_64(rbca);412break;413case E_MEMAC_COUNTER_RPKT:414ret_val = GET_MEMAC_CNTR_64(rpkt);415break;416case E_MEMAC_COUNTER_RUCA:417ret_val = GET_MEMAC_CNTR_64(ruca);418break;419case E_MEMAC_COUNTER_RERR:420ret_val = GET_MEMAC_CNTR_64(rerr);421break;422case E_MEMAC_COUNTER_TOCT:423ret_val = GET_MEMAC_CNTR_64(toct);424break;425case E_MEMAC_COUNTER_TMCA:426ret_val = GET_MEMAC_CNTR_64(tmca);427break;428case E_MEMAC_COUNTER_TBCA:429ret_val = GET_MEMAC_CNTR_64(tbca);430break;431case E_MEMAC_COUNTER_TUCA:432ret_val = GET_MEMAC_CNTR_64(tuca);433break;434case E_MEMAC_COUNTER_TERR:435ret_val = GET_MEMAC_CNTR_64(terr);436break;437default:438ret_val = 0;439}440441return ret_val;442}443444void fman_memac_adjust_link(struct memac_regs *regs,445enum enet_interface iface_mode,446enum enet_speed speed, bool full_dx)447{448uint32_t tmp;449450tmp = ioread32be(®s->if_mode);451452if (full_dx)453tmp &= ~IF_MODE_HD;454else455tmp |= IF_MODE_HD;456457if (iface_mode == E_ENET_IF_RGMII) {458/* Configure RGMII in manual mode */459tmp &= ~IF_MODE_RGMII_AUTO;460tmp &= ~IF_MODE_RGMII_SP_MASK;461462if (full_dx)463tmp |= IF_MODE_RGMII_FD;464else465tmp &= ~IF_MODE_RGMII_FD;466467switch (speed) {468case E_ENET_SPEED_1000:469tmp |= IF_MODE_RGMII_1000;470break;471case E_ENET_SPEED_100:472tmp |= IF_MODE_RGMII_100;473break;474case E_ENET_SPEED_10:475tmp |= IF_MODE_RGMII_10;476break;477default:478break;479}480}481482iowrite32be(tmp, ®s->if_mode);483}484485void fman_memac_defconfig(struct memac_cfg *cfg)486{487cfg->reset_on_init = FALSE;488cfg->wan_mode_enable = FALSE;489cfg->promiscuous_mode_enable = FALSE;490cfg->pause_forward_enable = FALSE;491cfg->pause_ignore = FALSE;492cfg->tx_addr_ins_enable = FALSE;493cfg->loopback_enable = FALSE;494cfg->cmd_frame_enable = FALSE;495cfg->rx_error_discard = FALSE;496cfg->send_idle_enable = FALSE;497cfg->no_length_check_enable = TRUE;498cfg->lgth_check_nostdr = FALSE;499cfg->time_stamp_enable = FALSE;500cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;501cfg->max_frame_length = DEFAULT_FRAME_LENGTH;502cfg->pause_quanta = DEFAULT_PAUSE_QUANTA;503cfg->pad_enable = TRUE;504cfg->phy_tx_ena_on = FALSE;505cfg->rx_sfd_any = FALSE;506cfg->rx_pbl_fwd = FALSE;507cfg->tx_pbl_fwd = FALSE;508cfg->debug_mode = FALSE;509cfg->wake_on_lan = FALSE;510}511512513