The driver manages network objects discovered on the Freescale
MC bus.
+config FSL_DPAA2_MAC
+ tristate "Freescale DPAA2 MAC driver"
+ depends on FSL_MC_BUS
+ select FSL_XGMAC_MDIO
+ select PHYLINK
+ select PCS_LYNX
+ help
+ This is the DPAA2 MAC independent driver which aims to support dpmac
+ fsl_mc devices which are not connected to other objects found in the
+ root dprc.
+
+config FSL_DPAA2_MAC_NETDEVS
+ bool "Expose net interfaces for MAC devices"
+ default n
+ depends on FSL_DPAA2_MAC
+ help
+ Exposes macX net interfaces for MAC devices which are not connected to
+ a host managed DPNI. This allows direct control over those MACs and
+ their corresponding PHYs.
+ Leave disabled if unsure.
+
if FSL_DPAA2_ETH
config FSL_DPAA2_ETH_DCB
bool "Data Center Bridging (DCB) Support"
obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
obj-$(CONFIG_FSL_DPAA2_PTP_CLOCK) += fsl-dpaa2-ptp.o
+obj-$(CONFIG_FSL_DPAA2_MAC) += fsl-dpaa2-mac.o
fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o dpaa2-mac.o dpmac.o dpaa2-eth-devlink.o
fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DCB} += dpaa2-eth-dcb.o
fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_CEETM} += dpaa2-eth-ceetm.o
fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o
+fsl-dpaa2-mac-objs := dpaa2-mac.o dpmac.o
# Needed by the tracing framework
CFLAGS_dpaa2-eth.o := -I$(src)
#include <linux/bpf_trace.h>
#include <linux/fsl/ptp_qoriq.h>
#include <linux/ptp_classify.h>
+#include <linux/device/driver.h>
#include <net/pkt_cls.h>
#include <net/sock.h>
+/* Hack: only here in order to use device_driver_detach.
+ * To be replaced with the use of MC _ENDPOINT_CHANGED interrupts on all
+ * connectable objects
+ */
+#include "../../../../base/base.h"
#include "dpaa2-eth.h"
#include "dpaa2-eth-ceetm.h"
return 0;
}
+static void dpaa2_eth_dpmac_driver_attach(struct fsl_mc_device *dpmac_dev)
+{
+ struct device_driver *drv = driver_find("fsl_dpaa2_mac", &fsl_mc_bus_type);
+ struct device *dev = &dpmac_dev->dev;
+
+ if (dev && dev->driver == NULL && driver_match_device(drv, dev))
+ device_driver_attach(drv, dev);
+}
+
+static void dpaa2_eth_dpmac_driver_detach(struct fsl_mc_device *dpmac_dev)
+{
+ struct device_driver *drv = driver_find("fsl_dpaa2_mac", &fsl_mc_bus_type);
+ struct device *dev = &dpmac_dev->dev;
+
+ if (dev && dev->driver == drv)
+ device_driver_detach(dev);
+}
+
static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv)
{
struct fsl_mc_device *dpni_dev, *dpmac_dev;
if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
return 0;
+ dpaa2_eth_dpmac_driver_detach(dpmac_dev);
+
mac = kzalloc(sizeof(struct dpaa2_mac), GFP_KERNEL);
if (!mac)
return -ENOMEM;
return;
dpaa2_mac_close(priv->mac);
+ dpaa2_eth_dpmac_driver_attach(priv->mac->mc_dev);
kfree(priv->mac);
priv->mac = NULL;
}
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/* Copyright 2019 NXP */
+#include <linux/fsl/mc.h>
+#include <linux/msi.h>
#include "dpaa2-eth.h"
#include "dpaa2-mac.h"
return 0;
}
+static bool dpaa2_mac_is_type_phy(struct dpaa2_mac *mac)
+{
+ if (mac &&
+ (mac->attr.link_type == DPMAC_LINK_TYPE_PHY ||
+ mac->attr.link_type == DPMAC_LINK_TYPE_BACKPLANE))
+ return true;
+
+ return false;
+}
+
/* Caller must call of_node_put on the returned value */
static struct device_node *dpaa2_mac_get_node(u16 dpmac_id)
{
*(data + i) = value;
}
}
+
+struct dpaa2_mac_link_mode_map {
+ u64 dpmac_lm;
+ enum ethtool_link_mode_bit_indices ethtool_lm;
+};
+
+static const struct dpaa2_mac_link_mode_map dpaa2_mac_lm_map[] = {
+ {DPMAC_ADVERTISED_10BASET_FULL, ETHTOOL_LINK_MODE_10baseT_Full_BIT},
+ {DPMAC_ADVERTISED_100BASET_FULL, ETHTOOL_LINK_MODE_100baseT_Full_BIT},
+ {DPMAC_ADVERTISED_1000BASET_FULL, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
+ {DPMAC_ADVERTISED_10000BASET_FULL, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
+ {DPMAC_ADVERTISED_AUTONEG, ETHTOOL_LINK_MODE_Autoneg_BIT},
+};
+
+static void dpaa2_mac_ksettings_change(struct dpaa2_mac *priv)
+{
+ struct fsl_mc_device *mc_dev = priv->mc_dev;
+ struct dpmac_link_cfg link_cfg = { 0 };
+ int err, i;
+
+ err = dpmac_get_link_cfg(priv->mc_io, 0,
+ mc_dev->mc_handle,
+ &link_cfg);
+ if (err) {
+ dev_err(&mc_dev->dev, "dpmac_get_link_cfg() = %d\n", err);
+ return;
+ }
+
+ phylink_ethtool_ksettings_get(priv->phylink, &priv->kset);
+
+ priv->kset.base.speed = link_cfg.rate;
+ priv->kset.base.duplex = !!(link_cfg.options & DPMAC_LINK_OPT_HALF_DUPLEX);
+
+ ethtool_link_ksettings_zero_link_mode(&priv->kset, advertising);
+ for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
+ if (link_cfg.advertising & dpaa2_mac_lm_map[i].dpmac_lm)
+ __set_bit(dpaa2_mac_lm_map[i].ethtool_lm,
+ priv->kset.link_modes.advertising);
+ }
+
+ if (link_cfg.options & DPMAC_LINK_OPT_AUTONEG) {
+ priv->kset.base.autoneg = AUTONEG_ENABLE;
+ __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+ priv->kset.link_modes.advertising);
+ } else {
+ priv->kset.base.autoneg = AUTONEG_DISABLE;
+ __clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+ priv->kset.link_modes.advertising);
+ }
+
+ phylink_ethtool_ksettings_set(priv->phylink, &priv->kset);
+}
+
+static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
+{
+ struct device *dev = (struct device *)arg;
+ struct fsl_mc_device *dpmac_dev;
+ struct net_device *net_dev;
+ struct dpaa2_mac *priv;
+ u32 status = ~0;
+ int err;
+
+ dpmac_dev = to_fsl_mc_device(dev);
+ net_dev = dev_get_drvdata(dev);
+ priv = netdev_priv(net_dev);
+
+ err = dpmac_get_irq_status(priv->mc_io, 0, dpmac_dev->mc_handle,
+ DPMAC_IRQ_INDEX, &status);
+ if (err) {
+ netdev_err(net_dev, "dpmac_get_irq_status() = %d\n", err);
+ return IRQ_HANDLED;
+ }
+
+ rtnl_lock();
+ if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ)
+ dpaa2_mac_ksettings_change(priv);
+
+ if (status & DPMAC_IRQ_EVENT_LINK_DOWN_REQ)
+ phylink_stop(priv->phylink);
+
+ if (status & DPMAC_IRQ_EVENT_LINK_UP_REQ)
+ phylink_start(priv->phylink);
+ rtnl_unlock();
+
+ dpmac_clear_irq_status(priv->mc_io, 0, dpmac_dev->mc_handle,
+ DPMAC_IRQ_INDEX, status);
+
+ return IRQ_HANDLED;
+}
+
+static int dpaa2_mac_setup_irqs(struct fsl_mc_device *mc_dev)
+{
+ struct fsl_mc_device_irq *irq;
+ int err = 0;
+
+ err = fsl_mc_allocate_irqs(mc_dev);
+ if (err) {
+ dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
+ return err;
+ }
+
+ irq = mc_dev->irqs[0];
+ err = devm_request_threaded_irq(&mc_dev->dev, irq->msi_desc->irq,
+ NULL, &dpaa2_mac_irq_handler,
+ IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ dev_name(&mc_dev->dev), &mc_dev->dev);
+ if (err) {
+ dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
+ err);
+ goto free_irq;
+ }
+
+ err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
+ DPMAC_IRQ_INDEX, DPMAC_IRQ_EVENT_LINK_CFG_REQ |
+ DPMAC_IRQ_EVENT_LINK_UP_REQ |
+ DPMAC_IRQ_EVENT_LINK_DOWN_REQ);
+ if (err) {
+ dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
+ goto free_irq;
+ }
+ err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
+ DPMAC_IRQ_INDEX, 1);
+ if (err) {
+ dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
+ goto free_irq;
+ }
+
+ return 0;
+
+free_irq:
+ fsl_mc_free_irqs(mc_dev);
+
+ return err;
+}
+
+static void dpaa2_mac_teardown_irqs(struct fsl_mc_device *mc_dev)
+{
+ int err;
+
+ err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
+ DPMAC_IRQ_INDEX, 0);
+ if (err)
+ dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
+
+ fsl_mc_free_irqs(mc_dev);
+}
+
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+
+static int dpaa2_mac_netdev_open(struct net_device *net_dev)
+{
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ if (dpaa2_mac_is_type_phy(priv))
+ phylink_start(priv->phylink);
+
+ return 0;
+}
+
+static int dpaa2_mac_netdev_stop(struct net_device *net_dev)
+{
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ if (!dpaa2_mac_is_type_phy(priv))
+ return 0;
+
+ phylink_stop(priv->phylink);
+
+ return 0;
+}
+
+static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
+ struct net_device *net_dev)
+{
+ /* These interfaces don't support I/O, they are only
+ * for control and debu
+ */
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static void dpaa2_mac_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
+ sizeof(drvinfo->bus_info));
+}
+
+static int dpaa2_mac_get_link_ksettings(struct net_device *net_dev,
+ struct ethtool_link_ksettings *ks)
+{
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ if (dpaa2_mac_is_type_phy(priv))
+ return phylink_ethtool_ksettings_get(priv->phylink, ks);
+
+ return -EOPNOTSUPP;
+}
+
+static int dpaa2_mac_set_link_ksettings(struct net_device *net_dev,
+ const struct ethtool_link_ksettings *ks)
+{
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ if (!dpaa2_mac_is_type_phy(priv))
+ return -EOPNOTSUPP;
+
+ return phylink_ethtool_ksettings_set(priv->phylink, ks);
+}
+
+static int dpaa2_mac_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
+{
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ if (!dpaa2_mac_is_type_phy(priv))
+ return -EOPNOTSUPP;
+
+ return phylink_mii_ioctl(priv->phylink, rq, cmd);
+}
+
+static void dpaa2_mac_ethtool_get_strings(struct net_device *net_dev,
+ u32 stringset, u8 *data)
+{
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ dpaa2_mac_get_strings(data);
+}
+
+static void dpaa2_mac_ethtool_get_stats(struct net_device *net_dev,
+ struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ dpaa2_mac_get_ethtool_stats(priv, data);
+}
+
+static int dpaa2_mac_ethtool_get_sset_count(struct net_device *dev, int sset)
+{
+ if (sset != ETH_SS_STATS)
+ return -EOPNOTSUPP;
+
+ return dpaa2_mac_get_sset_count();
+}
+
+static const struct net_device_ops dpaa2_mac_ndo_ops = {
+ .ndo_open = &dpaa2_mac_netdev_open,
+ .ndo_stop = &dpaa2_mac_netdev_stop,
+ .ndo_start_xmit = &dpaa2_mac_drop_frame,
+ .ndo_do_ioctl = &dpaa2_mac_ioctl,
+};
+
+static const struct ethtool_ops dpaa2_mac_ethtool_ops = {
+ .get_drvinfo = &dpaa2_mac_get_drvinfo,
+ .get_link_ksettings = &dpaa2_mac_get_link_ksettings,
+ .set_link_ksettings = &dpaa2_mac_set_link_ksettings,
+ .get_strings = &dpaa2_mac_ethtool_get_strings,
+ .get_ethtool_stats = &dpaa2_mac_ethtool_get_stats,
+ .get_sset_count = &dpaa2_mac_ethtool_get_sset_count,
+};
+#endif
+
+static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
+{
+ struct device *dev = &mc_dev->dev;
+ struct fsl_mc_device *peer_dev;
+ struct net_device *net_dev;
+ struct dpaa2_mac *priv;
+ int err;
+
+ /* If the DPMAC is connected to a DPNI from the currect DPRC, then
+ * there is no need for this standalone MAC driver, the dpaa2-eth will
+ * take care of anything related to MAC/PHY
+ */
+ peer_dev = fsl_mc_get_endpoint(mc_dev);
+ if (!IS_ERR_OR_NULL(peer_dev) && peer_dev->dev.type == &fsl_mc_bus_dpni_type)
+ return -EPROBE_DEFER;
+
+ net_dev = alloc_etherdev(sizeof(*priv));
+ if (!net_dev) {
+ dev_err(dev, "alloc_etherdev error\n");
+ return -ENOMEM;
+ }
+
+ priv = netdev_priv(net_dev);
+ priv->mc_dev = mc_dev;
+ priv->net_dev = net_dev;
+
+ SET_NETDEV_DEV(net_dev, dev);
+
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+ snprintf(net_dev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
+
+ /* register netdev just to make it visible to the user */
+ net_dev->netdev_ops = &dpaa2_mac_ndo_ops;
+ net_dev->ethtool_ops = &dpaa2_mac_ethtool_ops;
+
+ err = register_netdev(net_dev);
+ if (err) {
+ dev_err(dev, "register_netdev error %d\n", err);
+ goto free_netdev;
+ }
+#endif
+
+ dev_set_drvdata(dev, net_dev);
+
+ err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
+ if (err) {
+ if (err == -ENXIO)
+ err = -EPROBE_DEFER;
+ else
+ dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
+ goto unregister_netdev;
+ }
+ priv->mc_io = mc_dev->mc_io;
+
+ err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
+ &mc_dev->mc_handle);
+ if (err || !mc_dev->mc_handle) {
+ dev_err(dev, "dpmac_open error: %d\n", err);
+ err = -ENODEV;
+ goto free_portal;
+ }
+
+ err = dpmac_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, &priv->attr);
+ if (err) {
+ dev_err(dev, "dpmac_get_attributes() = %d\n", err);
+ goto free_portal;
+ }
+
+ err = dpaa2_mac_setup_irqs(mc_dev);
+ if (err) {
+ err = -EFAULT;
+ goto free_portal;
+ }
+
+ err = dpaa2_mac_open(priv);
+ if (err)
+ goto free_portal;
+
+ if (dpaa2_mac_is_type_phy(priv)) {
+ err = dpaa2_mac_connect(priv);
+ if (err) {
+ dev_err(dev, "Error connecting to the MAC endpoint\n");
+ goto free_portal;
+ }
+ }
+
+ return 0;
+free_portal:
+ fsl_mc_portal_free(mc_dev->mc_io);
+unregister_netdev:
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+ unregister_netdev(net_dev);
+#endif
+free_netdev:
+ free_netdev(net_dev);
+
+ return err;
+}
+
+static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
+{
+ struct device *dev = &mc_dev->dev;
+ struct net_device *net_dev = dev_get_drvdata(dev);
+ struct dpaa2_mac *priv = netdev_priv(net_dev);
+
+ dpaa2_mac_teardown_irqs(mc_dev);
+
+ if (dpaa2_mac_is_type_phy(priv)) {
+ dpaa2_mac_close(priv);
+ dpaa2_mac_disconnect(priv);
+ }
+
+ fsl_mc_portal_free(mc_dev->mc_io);
+ dev_set_drvdata(dev, NULL);
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+ unregister_netdev(net_dev);
+#endif
+ free_netdev(net_dev);
+
+ return 0;
+}
+
+static const struct fsl_mc_device_id dpaa2_mac_match_id_table[] = {
+ {
+ .vendor = FSL_MC_VENDOR_FREESCALE,
+ .obj_type = "dpmac",
+ },
+ { .vendor = 0x0 }
+};
+MODULE_DEVICE_TABLE(fslmc, dpaa2_mac_match_id_table);
+
+static struct fsl_mc_driver dpaa2_mac_driver = {
+ .driver = {
+ .name = "fsl_dpaa2_mac",
+ .owner = THIS_MODULE,
+ },
+ .probe = dpaa2_mac_probe,
+ .remove = dpaa2_mac_remove,
+ .match_id_table = dpaa2_mac_match_id_table
+};
+
+module_fsl_mc_driver(dpaa2_mac_driver);
struct phylink_config phylink_config;
struct phylink *phylink;
+ struct ethtool_link_ksettings kset;
phy_interface_t if_mode;
enum dpmac_link_type if_link_type;
struct lynx_pcs *pcs;
#define DPMAC_CMDID_OPEN DPMAC_CMD(0x80c)
#define DPMAC_CMDID_GET_ATTR DPMAC_CMD(0x004)
+
+#define DPMAC_CMDID_SET_IRQ_ENABLE DPMAC_CMD(0x012)
+#define DPMAC_CMDID_GET_IRQ_ENABLE DPMAC_CMD(0x013)
+#define DPMAC_CMDID_SET_IRQ_MASK DPMAC_CMD(0x014)
+#define DPMAC_CMDID_GET_IRQ_MASK DPMAC_CMD(0x015)
+#define DPMAC_CMDID_GET_IRQ_STATUS DPMAC_CMD(0x016)
+#define DPMAC_CMDID_CLEAR_IRQ_STATUS DPMAC_CMD(0x017)
+
+#define DPMAC_CMDID_GET_LINK_CFG DPMAC_CMD_V2(0x0c2)
#define DPMAC_CMDID_SET_LINK_STATE DPMAC_CMD_V2(0x0c3)
#define DPMAC_CMDID_GET_COUNTER DPMAC_CMD(0x0c4)
-
/* Macros for accessing command fields smaller than 1byte */
#define DPMAC_MASK(field) \
GENMASK(DPMAC_##field##_SHIFT + DPMAC_##field##_SIZE - 1, \
__le64 counter;
};
+struct dpmac_cmd_set_irq_enable {
+ u8 enable;
+ u8 pad[3];
+ u8 irq_index;
+};
+
+struct dpmac_cmd_get_irq_enable {
+ u32 pad;
+ u8 irq_index;
+};
+
+struct dpmac_rsp_get_irq_enable {
+ u8 enabled;
+};
+
+struct dpmac_cmd_set_irq_mask {
+ u32 mask;
+ u8 irq_index;
+};
+
+struct dpmac_cmd_get_irq_mask {
+ u32 pad;
+ u8 irq_index;
+};
+
+struct dpmac_rsp_get_irq_mask {
+ u32 mask;
+};
+
+struct dpmac_cmd_get_irq_status {
+ u32 status;
+ u8 irq_index;
+};
+
+struct dpmac_rsp_get_irq_status {
+ u32 status;
+};
+
+struct dpmac_cmd_clear_irq_status {
+ u32 status;
+ u8 irq_index;
+};
+
+struct dpmac_rsp_get_link_cfg {
+ u64 options;
+ u32 rate;
+ u32 pad;
+ u64 advertising;
+};
+
#endif /* _FSL_DPMAC_CMD_H */
return 0;
}
+
+/**
+ * dpmac_set_irq_enable() - Set overall interrupt state.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @irq_index: The interrupt index to configure
+ * @en: Interrupt state - enable = 1, disable = 0
+ *
+ * Allows GPP software to control when interrupts are generated.
+ * Each interrupt can have up to 32 causes. The enable/disable control's the
+ * overall interrupt state. if the interrupt is disabled no causes will cause
+ * an interrupt.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u8 en)
+{
+ struct dpmac_cmd_set_irq_enable *cmd_params;
+ struct fsl_mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpmac_cmd_set_irq_enable *)cmd.params;
+ cmd_params->irq_index = irq_index;
+ cmd_params->enable = en;
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpmac_get_irq_enable() - Get overall interrupt state
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @irq_index: The interrupt index to configure
+ * @en: Returned interrupt state - enable = 1, disable = 0
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u8 *en)
+{
+ struct dpmac_cmd_get_irq_enable *cmd_params;
+ struct dpmac_rsp_get_irq_enable *rsp_params;
+ struct fsl_mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpmac_cmd_get_irq_enable *)cmd.params;
+ cmd_params->irq_index = irq_index;
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ rsp_params = (struct dpmac_rsp_get_irq_enable *)cmd.params;
+ *en = rsp_params->enabled;
+
+ return 0;
+}
+
+/**
+ * dpmac_set_irq_mask() - Set interrupt mask.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @irq_index: The interrupt index to configure
+ * @mask: Event mask to trigger interrupt;
+ * each bit:
+ * 0 = ignore event
+ * 1 = consider event for asserting IRQ
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 mask)
+{
+ struct dpmac_cmd_set_irq_mask *cmd_params;
+ struct fsl_mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpmac_cmd_set_irq_mask *)cmd.params;
+ cmd_params->mask = cpu_to_le32(mask);
+ cmd_params->irq_index = irq_index;
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpmac_get_irq_mask() - Get interrupt mask.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @irq_index: The interrupt index to configure
+ * @mask: Returned event mask to trigger interrupt
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 *mask)
+{
+ struct dpmac_cmd_get_irq_mask *cmd_params;
+ struct dpmac_rsp_get_irq_mask *rsp_params;
+ struct fsl_mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpmac_cmd_get_irq_mask *)cmd.params;
+ cmd_params->irq_index = irq_index;
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ rsp_params = (struct dpmac_rsp_get_irq_mask *)cmd.params;
+ *mask = le32_to_cpu(rsp_params->mask);
+
+ return 0;
+}
+
+/**
+ * dpmac_get_irq_status() - Get the current status of any pending interrupts.
+ *
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @irq_index: The interrupt index to configure
+ * @status: Returned interrupts status - one bit per cause:
+ * 0 = no interrupt pending
+ * 1 = interrupt pending
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 *status)
+{
+ struct dpmac_cmd_get_irq_status *cmd_params;
+ struct dpmac_rsp_get_irq_status *rsp_params;
+ struct fsl_mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpmac_cmd_get_irq_status *)cmd.params;
+ cmd_params->status = cpu_to_le32(*status);
+ cmd_params->irq_index = irq_index;
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ rsp_params = (struct dpmac_rsp_get_irq_status *)cmd.params;
+ *status = le32_to_cpu(rsp_params->status);
+
+ return 0;
+}
+
+/**
+ * dpmac_clear_irq_status() - Clear a pending interrupt's status
+ *
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @irq_index: The interrupt index to configure
+ * @status: Bits to clear (W1C) - one bit per cause:
+ * 0 = don't change
+ * 1 = clear status bit
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 status)
+{
+ struct dpmac_cmd_clear_irq_status *cmd_params;
+ struct fsl_mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpmac_cmd_clear_irq_status *)cmd.params;
+ cmd_params->status = cpu_to_le32(status);
+ cmd_params->irq_index = irq_index;
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpmac_get_link_cfg() - Get Ethernet link configuration
+ * @mc_io: Pointer to opaque I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPMAC object
+ * @cfg: Returned structure with the link configuration
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ struct dpmac_link_cfg *cfg)
+{
+ struct dpmac_rsp_get_link_cfg *rsp_params;
+ struct fsl_mc_command cmd = { 0 };
+ int err = 0;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
+ cmd_flags,
+ token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ rsp_params = (struct dpmac_rsp_get_link_cfg *)cmd.params;
+ cfg->options = le64_to_cpu(rsp_params->options);
+ cfg->rate = le32_to_cpu(rsp_params->rate);
+ cfg->advertising = le64_to_cpu(rsp_params->advertising);
+
+ return 0;
+}
*/
#define DPMAC_ADVERTISED_AUTONEG BIT_ULL(3)
+/**
+ * struct dpmac_link_cfg - Structure representing DPMAC link configuration
+ * @rate: Link's rate - in Mbps
+ * @options: Enable/Disable DPMAC link cfg features (bitmap)
+ * @advertising: Speeds that are advertised for autoneg (bitmap)
+ */
+struct dpmac_link_cfg {
+ u32 rate;
+ u64 options;
+ u64 advertising;
+};
+
+int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ struct dpmac_link_cfg *cfg);
+
/**
* struct dpmac_link_state - DPMAC link configuration request
* @rate: Rate in Mbps
int dpmac_get_counter(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
enum dpmac_counter_id id, u64 *value);
+/**
+ * DPMAC IRQ Index and Events
+ */
+
+/**
+ * IRQ index
+ */
+#define DPMAC_IRQ_INDEX 0
+/**
+ * IRQ event - indicates a change in link state
+ */
+#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001
+/**
+ * IRQ event - Indicates that the link state changed
+ */
+#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002
+/**
+ * IRQ event - Indicate if the phy needs to suspend or resume
+ */
+#define DPMAC_IRQ_EVENT_LINK_UP_REQ 0x00000004
+#define DPMAC_IRQ_EVENT_LINK_DOWN_REQ 0x00000008
+
+int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u8 en);
+
+int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u8 *en);
+
+int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 mask);
+
+int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 *mask);
+
+int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 *status);
+
+int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u8 irq_index,
+ u32 status);
+
#endif /* __FSL_DPMAC_H */
--- /dev/null
+/home/ioana/work/nxp/git/dash-lts/drivers/staging/fsl-dpaa2/mac/
\ No newline at end of file