diff options
author | Bogdan Hamciuc <bogdan.hamciuc@freescale.com> | 2013-02-08 16:45:07 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-04-08 23:08:44 (GMT) |
commit | 61aefeeb94ac9c313ec3374165814be3e9eb1dc4 (patch) | |
tree | 23bda8755d563f42ea4ede6c857e9f9fd4810195 /drivers/net/ethernet/freescale/dpa/mac-api.c | |
parent | b4e54fde5bab3e795b36566c199624f64a3c2fae (diff) | |
download | linux-fsl-qoriq-61aefeeb94ac9c313ec3374165814be3e9eb1dc4.tar.xz |
dpaa_eth: DPAA Ethernet driver from SDK-v1.3.1
Raw move of the DPAA-Ethernet driver as of SDK-v1.3.1.
Also squashed compile fixes on the 3.8 codebase and a number of newer
commits necessary for a clean compilation.
Squashed commits:
- fmd,dpaa_eth: Reorganize port param structures in wrapper API
- dpaa_eth: Cleanup sysfs interface
- dpaa_eth: Minor sysfs change
- dpaa_eth: Move all sysfs code to a separate file
- dpaa_eth: Port FSL-specific netdev features
Change-Id: I51b65ae719b154f55302016f4e8bd943d8a062cb
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-on: http://git.am.freescale.net:8181/1031
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/dpa/mac-api.c')
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/mac-api.c | 839 |
1 files changed, 839 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/mac-api.c b/drivers/net/ethernet/freescale/dpa/mac-api.c new file mode 100644 index 0000000..beb33b1 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpa/mac-api.c @@ -0,0 +1,839 @@ +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/of_mdio.h> +#include <linux/phy.h> +#include <linux/netdevice.h> + +#include "dpaa_eth-common.h" +#include "dpaa_eth.h" +#include "mac.h" + +#include "error_ext.h" /* GET_ERROR_TYPE, E_OK */ +#include "fm_mac_ext.h" +#include "fm_rtc_ext.h" + +#define MAC_DESCRIPTION "FSL FMan MAC API based driver" + +MODULE_LICENSE("Dual BSD/GPL"); + +MODULE_AUTHOR("Emil Medve <Emilian.Medve@Freescale.com>"); + +MODULE_DESCRIPTION(MAC_DESCRIPTION); + +struct mac_priv_s { + t_Handle mac; +}; + +const char *mac_driver_description __initconst = MAC_DESCRIPTION; +const size_t mac_sizeof_priv[] __devinitconst = { + [DTSEC] = sizeof(struct mac_priv_s), + [XGMAC] = sizeof(struct mac_priv_s), + [MEMAC] = sizeof(struct mac_priv_s) +}; + +static const e_EnetMode _100[] __devinitconst = +{ + [PHY_INTERFACE_MODE_MII] = e_ENET_MODE_MII_100, + [PHY_INTERFACE_MODE_RMII] = e_ENET_MODE_RMII_100 +}; + +static const e_EnetMode _1000[] __devinitconst = +{ + [PHY_INTERFACE_MODE_GMII] = e_ENET_MODE_GMII_1000, + [PHY_INTERFACE_MODE_SGMII] = e_ENET_MODE_SGMII_1000, + [PHY_INTERFACE_MODE_TBI] = e_ENET_MODE_TBI_1000, + [PHY_INTERFACE_MODE_RGMII] = e_ENET_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_ID] = e_ENET_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_RXID] = e_ENET_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_TXID] = e_ENET_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RTBI] = e_ENET_MODE_RTBI_1000 +}; + +static e_EnetMode __devinit __cold __attribute__((nonnull)) +macdev2enetinterface(const struct mac_device *mac_dev) +{ + switch (mac_dev->max_speed) { + case SPEED_100: + return _100[mac_dev->phy_if]; + case SPEED_1000: + return _1000[mac_dev->phy_if]; + case SPEED_10000: + return e_ENET_MODE_XGMII_10000; + default: + return e_ENET_MODE_MII_100; + } +} + +static void mac_exception(t_Handle _mac_dev, e_FmMacExceptions exception) +{ + struct mac_device *mac_dev; + + mac_dev = (struct mac_device *)_mac_dev; + + if (e_FM_MAC_EX_10G_RX_FIFO_OVFL == exception) { + /* don't flag RX FIFO after the first */ + FM_MAC_SetException( + ((struct mac_priv_s *)macdev_priv(_mac_dev))->mac, + e_FM_MAC_EX_10G_RX_FIFO_OVFL, false); + printk(KERN_ERR "10G MAC got RX FIFO Error = %x\n", exception); + } + + cpu_dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", __file__, __func__, + exception); +} + +static int __devinit __cold init(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + struct mac_priv_s *priv; + t_FmMacParams param; + uint32_t version; + + priv = macdev_priv(mac_dev); + + param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap( + mac_dev->dev, mac_dev->res->start, 0x2000); + param.enetMode = macdev2enetinterface(mac_dev); + memcpy(¶m.addr, mac_dev->addr, min(sizeof(param.addr), + sizeof(mac_dev->addr))); + param.macId = mac_dev->cell_index; + param.h_Fm = (t_Handle)mac_dev->fm; + param.mdioIrq = NO_IRQ; + param.f_Exception = mac_exception; + param.f_Event = mac_exception; + param.h_App = mac_dev; + + priv->mac = FM_MAC_Config(¶m); + if (unlikely(priv->mac == NULL)) { + dpaa_eth_err(mac_dev->dev, "FM_MAC_Config() failed\n"); + _errno = -EINVAL; + goto _return; + } + + fm_mac_set_handle(mac_dev->fm_dev, priv->mac, + (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? + param.macId : param.macId + FM_MAX_NUM_OF_1G_MACS); + + err = FM_MAC_ConfigMaxFrameLength(priv->mac, + fm_get_max_frm()); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + + if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) { + /* 10G always works with pad and CRC */ + err = FM_MAC_ConfigPadAndCrc(priv->mac, true); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_ConfigPadAndCrc() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + + err = FM_MAC_ConfigHalfDuplex(priv->mac, mac_dev->half_duplex); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_ConfigHalfDuplex() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + } + else { + err = FM_MAC_ConfigResetOnInit(priv->mac, true); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_ConfigResetOnInit() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + } + + err = FM_MAC_Init(priv->mac); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, "FM_MAC_Init() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + +#ifndef CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN + /* For 1G MAC, disable by default the MIB counters overflow interrupt */ + if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) { + err = FM_MAC_SetException(priv->mac, + e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, FALSE); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_SetException() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + } +#endif /* !CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN */ + + /* For 10G MAC, disable Tx ECC exception */ + if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) { + err = FM_MAC_SetException(priv->mac, + e_FM_MAC_EX_10G_1TX_ECC_ER, FALSE); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_SetException() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + } + + err = FM_MAC_GetVesrion(priv->mac, &version); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dpaa_eth_err(mac_dev->dev, "FM_MAC_GetVesrion() = 0x%08x\n", + err); + goto _return_fm_mac_free; + } + cpu_dev_info(mac_dev->dev, "FMan %s version: 0x%08x\n", + ((macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? + "dTSEC" : "XGEC"), version); + + goto _return; + + +_return_fm_mac_free: + err = FM_MAC_Free(priv->mac); + if (unlikely(-GET_ERROR_TYPE(err) < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_Free() = 0x%08x\n", err); +_return: + return _errno; +} + +static int __devinit __cold memac_init(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + struct mac_priv_s *priv; + t_FmMacParams param; + + priv = macdev_priv(mac_dev); + + param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap( + mac_dev->dev, mac_dev->res->start, 0x2000); + param.enetMode = macdev2enetinterface(mac_dev); + memcpy(¶m.addr, mac_dev->addr, sizeof(mac_dev->addr)); + param.macId = mac_dev->cell_index; + param.h_Fm = (t_Handle)mac_dev->fm; + param.mdioIrq = NO_IRQ; + param.f_Exception = mac_exception; + param.f_Event = mac_exception; + param.h_App = mac_dev; + + priv->mac = FM_MAC_Config(¶m); + if (unlikely(priv->mac == NULL)) { + dev_err(mac_dev->dev, "FM_MAC_Config() failed\n"); + _errno = -EINVAL; + goto _return; + } + + err = FM_MAC_ConfigMaxFrameLength(priv->mac, fm_get_max_frm()); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dev_err(mac_dev->dev, + "FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + + err = FM_MAC_ConfigResetOnInit(priv->mac, true); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dev_err(mac_dev->dev, + "FM_MAC_ConfigResetOnInit() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + + err = FM_MAC_Init(priv->mac); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) { + dev_err(mac_dev->dev, "FM_MAC_Init() = 0x%08x\n", err); + goto _return_fm_mac_free; + } + + dev_info(mac_dev->dev, "FMan MEMAC\n"); + + goto _return; + +_return_fm_mac_free: + err = FM_MAC_Free(priv->mac); + if (unlikely(-GET_ERROR_TYPE(err) < 0)) + dev_err(mac_dev->dev, "FM_MAC_Free() = 0x%08x\n", err); +_return: + return _errno; +} + +static int __cold start(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + struct phy_device *phy_dev = mac_dev->phy_dev; + + err = FM_MAC_Enable(((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + e_COMM_MODE_RX_AND_TX); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_Enable() = 0x%08x\n", err); + + if (phy_dev) { + if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) + phy_start(phy_dev); + else if (phy_dev->drv->read_status) + phy_dev->drv->read_status(phy_dev); + } + + return _errno; +} + +static int __cold stop(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + + if (mac_dev->phy_dev && + (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000)) + phy_stop(mac_dev->phy_dev); + + err = FM_MAC_Disable(((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + e_COMM_MODE_RX_AND_TX); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_Disable() = 0x%08x\n", err); + + return _errno; +} + +static int __cold change_promisc(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + + err = FM_MAC_SetPromiscuous( + ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + mac_dev->promisc = !mac_dev->promisc); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, + "FM_MAC_SetPromiscuous() = 0x%08x\n", err); + + return _errno; +} + +static int __cold set_multi(struct net_device *net_dev) +{ + struct dpa_priv_s *priv; + struct mac_device *mac_dev; + struct mac_priv_s *mac_priv; + struct mac_address *old_addr, *tmp; + struct netdev_hw_addr *ha; + int _errno; + t_Error err; + + priv = netdev_priv(net_dev); + mac_dev = priv->mac_dev; + mac_priv = macdev_priv(mac_dev); + + /* Clear previous address list */ + list_for_each_entry_safe(old_addr, tmp, &mac_dev->mc_addr_list, list) { + err = FM_MAC_RemoveHashMacAddr(mac_priv->mac, + (t_EnetAddr *)old_addr->addr); + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_RemoveHashMacAddr() = 0x%08x\n", err); + return _errno; + } + list_del(&old_addr->list); + kfree(old_addr); + } + + /* Add all the addresses from the new list */ + netdev_for_each_mc_addr(ha, net_dev) { + err = FM_MAC_AddHashMacAddr(mac_priv->mac, + (t_EnetAddr *)ha->addr); + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) { + dpaa_eth_err(mac_dev->dev, + "FM_MAC_AddHashMacAddr() = 0x%08x\n", err); + return _errno; + } + tmp = kmalloc(sizeof(struct mac_address), GFP_ATOMIC); + if (!tmp) { + dpaa_eth_err(mac_dev->dev, "Out of memory\n"); + return -ENOMEM; + } + memcpy(tmp->addr, ha->addr, ETH_ALEN); + list_add(&tmp->list, &mac_dev->mc_addr_list); + } + return 0; +} + +static int __cold change_addr(struct mac_device *mac_dev, uint8_t *addr) +{ + int _errno; + t_Error err; + + err = FM_MAC_ModifyMacAddr( + ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + (t_EnetAddr *)addr); + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) + dpaa_eth_err(mac_dev->dev, + "FM_MAC_ModifyMacAddr() = 0x%08x\n", err); + + return _errno; +} + +static void adjust_link(struct net_device *net_dev) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + struct phy_device *phy_dev = mac_dev->phy_dev; +#if (DPAA_VERSION < 11) + struct mac_priv_s *mac_priv; +#endif + int _errno; + t_Error err; + + if (!phy_dev->link) { +#if (DPAA_VERSION < 11) +#warning fsl_pq_mdio_lock() no longer supported +/* + fsl_pq_mdio_lock(NULL); +*/ + + mac_priv = (struct mac_priv_s *)macdev_priv(mac_dev); + DtsecRestartTbiAN(mac_priv->mac); + +#warning fsl_pq_mdio_unlock() no longer supported +/* + fsl_pq_mdio_unlock(NULL); +*/ +#endif + return; + } + + err = FM_MAC_AdjustLink( + ((struct mac_priv_s *)macdev_priv(mac_dev))->mac, + phy_dev->speed, phy_dev->duplex); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_AdjustLink() = 0x%08x\n", + err); + + return; +} + +/* Initializes driver's PHY state, and attaches to the PHY. + * Returns 0 on success. + */ +static int dtsec_init_phy(struct net_device *net_dev) +{ + struct dpa_priv_s *priv; + struct mac_device *mac_dev; + struct phy_device *phy_dev; + + priv = netdev_priv(net_dev); + mac_dev = priv->mac_dev; + + if (!mac_dev->phy_node) + phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, + &adjust_link, 0, mac_dev->phy_if); + else + phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, + &adjust_link, 0, mac_dev->phy_if); + if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { + cpu_netdev_err(net_dev, "Could not connect to PHY %s\n", + mac_dev->phy_node ? + mac_dev->phy_node->full_name : + mac_dev->fixed_bus_id); + return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); + } + + /* Remove any features not supported by the controller */ + phy_dev->supported &= priv->mac_dev->if_support; + phy_dev->advertising = phy_dev->supported; + + priv->mac_dev->phy_dev = phy_dev; + + return 0; +} + +static int xgmac_init_phy(struct net_device *net_dev) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + struct phy_device *phy_dev; + + if (!mac_dev->phy_node) + phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id, 0, + mac_dev->phy_if); + else + phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0, + mac_dev->phy_if); + if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { + cpu_netdev_err(net_dev, "Could not attach to PHY %s\n", + mac_dev->phy_node ? + mac_dev->phy_node->full_name : + mac_dev->fixed_bus_id); + return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); + } + + phy_dev->supported &= priv->mac_dev->if_support; + phy_dev->advertising = phy_dev->supported; + + mac_dev->phy_dev = phy_dev; + + return 0; +} + +static int memac_init_phy(struct net_device *net_dev) +{ + struct dpa_priv_s *priv; + struct mac_device *mac_dev; + struct phy_device *phy_dev; + + priv = netdev_priv(net_dev); + mac_dev = priv->mac_dev; + + if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) { + if (!mac_dev->phy_node) + phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id, 0, + mac_dev->phy_if); + else + phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0, + mac_dev->phy_if); + } else { + if (!mac_dev->phy_node) + phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, + &adjust_link, 0, mac_dev->phy_if); + else + phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, + &adjust_link, 0, mac_dev->phy_if); + } + + if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { + netdev_err(net_dev, "Could not connect to PHY %s\n", + mac_dev->phy_node ? + mac_dev->phy_node->full_name : + mac_dev->fixed_bus_id); + return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); + } + + /* Remove any features not supported by the controller */ + phy_dev->supported &= priv->mac_dev->if_support; + phy_dev->advertising = phy_dev->supported; + + mac_dev->phy_dev = phy_dev; + + return 0; +} + +static int __cold uninit(struct mac_device *mac_dev) +{ + int _errno, __errno; + t_Error err; + const struct mac_priv_s *priv; + + priv = macdev_priv(mac_dev); + + err = FM_MAC_Disable(priv->mac, e_COMM_MODE_RX_AND_TX); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_Disable() = 0x%08x\n", err); + + err = FM_MAC_Free(priv->mac); + __errno = -GET_ERROR_TYPE(err); + if (unlikely(__errno < 0)) { + dpaa_eth_err(mac_dev->dev, "FM_MAC_Free() = 0x%08x\n", err); + if (_errno < 0) + _errno = __errno; + } + + return _errno; +} + +static int __cold ptp_enable(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + const struct mac_priv_s *priv; + + priv = macdev_priv(mac_dev); + + err = FM_MAC_Enable1588TimeStamp(priv->mac); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_Enable1588TimeStamp()" + "= 0x%08x\n", err); + return _errno; +} + +static int __cold ptp_disable(struct mac_device *mac_dev) +{ + int _errno; + t_Error err; + const struct mac_priv_s *priv; + + priv = macdev_priv(mac_dev); + + err = FM_MAC_Disable1588TimeStamp(priv->mac); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_MAC_Disable1588TimeStamp()" + "= 0x%08x\n", err); + return _errno; +} + +static void *get_mac_handle(struct mac_device *mac_dev) +{ + const struct mac_priv_s *priv; + priv = macdev_priv(mac_dev); + return (void*)priv->mac; +} + +static int __cold fm_rtc_enable(struct net_device *net_dev) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + int _errno; + t_Error err; + + err = FM_RTC_Enable(fm_get_rtc_handle(mac_dev->fm_dev), 0); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_Enable = 0x%08x\n", err); + + return _errno; +} + +static int __cold fm_rtc_disable(struct net_device *net_dev) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + int _errno; + t_Error err; + + err = FM_RTC_Disable(fm_get_rtc_handle(mac_dev->fm_dev)); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_Disable = 0x%08x\n", err); + + return _errno; +} + +static int __cold fm_rtc_get_cnt(struct net_device *net_dev, uint64_t *ts) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + int _errno; + t_Error err; + + err = FM_RTC_GetCurrentTime(fm_get_rtc_handle(mac_dev->fm_dev), ts); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_GetCurrentTime = 0x%08x\n", + err); + + return _errno; +} + +static int __cold fm_rtc_set_cnt(struct net_device *net_dev, uint64_t ts) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + int _errno; + t_Error err; + + err = FM_RTC_SetCurrentTime(fm_get_rtc_handle(mac_dev->fm_dev), ts); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_SetCurrentTime = 0x%08x\n", + err); + + return _errno; +} + +static int __cold fm_rtc_get_drift(struct net_device *net_dev, uint32_t *drift) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + int _errno; + t_Error err; + + err = FM_RTC_GetFreqCompensation(fm_get_rtc_handle(mac_dev->fm_dev), + drift); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_GetFreqCompensation =" + "0x%08x\n", err); + + return _errno; +} + +static int __cold fm_rtc_set_drift(struct net_device *net_dev, uint32_t drift) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + int _errno; + t_Error err; + + err = FM_RTC_SetFreqCompensation(fm_get_rtc_handle(mac_dev->fm_dev), + drift); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_SetFreqCompensation =" + "0x%08x\n", err); + + return _errno; +} + +static int __cold fm_rtc_set_alarm(struct net_device *net_dev, uint32_t id, + uint64_t time) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + t_FmRtcAlarmParams alarm; + int _errno; + t_Error err; + + alarm.alarmId = id; + alarm.alarmTime = time; + alarm.f_AlarmCallback = NULL; + err = FM_RTC_SetAlarm(fm_get_rtc_handle(mac_dev->fm_dev), + &alarm); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_SetAlarm =" + "0x%08x\n", err); + + return _errno; +} + +static int __cold fm_rtc_set_fiper(struct net_device *net_dev, uint32_t id, + uint64_t fiper) +{ + struct dpa_priv_s *priv = netdev_priv(net_dev); + struct mac_device *mac_dev = priv->mac_dev; + t_FmRtcPeriodicPulseParams pp; + int _errno; + t_Error err; + + pp.periodicPulseId = id; + pp.periodicPulsePeriod = fiper; + pp.f_PeriodicPulseCallback = NULL; + err = FM_RTC_SetPeriodicPulse(fm_get_rtc_handle(mac_dev->fm_dev), &pp); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + dpaa_eth_err(mac_dev->dev, "FM_RTC_SetPeriodicPulse =" + "0x%08x\n", err); + + return _errno; +} + + +void fm_mac_dump_regs(struct mac_device *mac_dev) +{ + struct mac_priv_s *mac_priv = macdev_priv(mac_dev); + + FM_MAC_DumpRegs(mac_priv->mac); +} + +static void __devinit __cold setup_dtsec(struct mac_device *mac_dev) +{ + mac_dev->init_phy = dtsec_init_phy; + mac_dev->init = init; + mac_dev->start = start; + mac_dev->stop = stop; + mac_dev->change_promisc = change_promisc; + mac_dev->change_addr = change_addr; + mac_dev->set_multi = set_multi; + mac_dev->uninit = uninit; + mac_dev->ptp_enable = ptp_enable; + mac_dev->ptp_disable = ptp_disable; + mac_dev->get_mac_handle = get_mac_handle; + mac_dev->fm_rtc_enable = fm_rtc_enable; + mac_dev->fm_rtc_disable = fm_rtc_disable; + mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; + mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt; + mac_dev->fm_rtc_get_drift = fm_rtc_get_drift; + mac_dev->fm_rtc_set_drift = fm_rtc_set_drift; + mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm; + mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper; +} + +static void __devinit __cold setup_xgmac(struct mac_device *mac_dev) +{ + mac_dev->init_phy = xgmac_init_phy; + mac_dev->init = init; + mac_dev->start = start; + mac_dev->stop = stop; + mac_dev->change_promisc = change_promisc; + mac_dev->change_addr = change_addr; + mac_dev->set_multi = set_multi; + mac_dev->uninit = uninit; +} + +static void __devinit __cold setup_memac(struct mac_device *mac_dev) +{ + mac_dev->init_phy = memac_init_phy; + mac_dev->init = memac_init; + mac_dev->start = start; + mac_dev->stop = stop; + mac_dev->change_promisc = change_promisc; + mac_dev->change_addr = change_addr; + mac_dev->set_multi = set_multi; + mac_dev->uninit = uninit; + mac_dev->fm_rtc_enable = fm_rtc_enable; + mac_dev->fm_rtc_disable = fm_rtc_disable; + mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; + mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt; + mac_dev->fm_rtc_get_drift = fm_rtc_get_drift; + mac_dev->fm_rtc_set_drift = fm_rtc_set_drift; + mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm; + mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper; +} + +void (*const mac_setup[])(struct mac_device *mac_dev) __devinitconst = { + [DTSEC] = setup_dtsec, + [XGMAC] = setup_xgmac, + [MEMAC] = setup_memac +}; |