linux/drivers/net/ethernet/xilinx/xilinx_tsn_ep.c
<<
>>
Prefs
   1/*
   2 * Xilinx FPGA Xilinx TSN End point driver.
   3 *
   4 * Copyright (c) 2017 Xilinx Pvt., Ltd
   5 *
   6 * Author: Saurabh Sengar <saurabhs@xilinx.com>
   7 *
   8 * This software is licensed under the terms of the GNU General Public
   9 * License version 2, as published by the Free Software Foundation, and
  10 * may be copied, distributed, and modified under those terms.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#include <linux/etherdevice.h>
  19#include <linux/module.h>
  20#include <linux/netdevice.h>
  21#include <linux/of_platform.h>
  22#include <linux/of_address.h>
  23#include <linux/skbuff.h>
  24
  25#include "xilinx_axienet.h"
  26
  27/**
  28 * tsn_ep_ioctl - TSN endpoint ioctl interface.
  29 * @dev: Pointer to the net_device structure
  30 * @rq: Socket ioctl interface request structure
  31 * @cmd: Ioctl case
  32 *
  33 * Return: 0 on success, Non-zero error value on failure.
  34 *
  35 * This is the ioctl interface for TSN end point. Currently this
  36 * supports only gate programming.
  37 */
  38static int tsn_ep_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  39{
  40        switch (cmd) {
  41#ifdef CONFIG_XILINX_TSN_QBV
  42        case SIOCCHIOCTL:
  43                return axienet_set_schedule(dev, rq->ifr_data);
  44        case SIOC_GET_SCHED:
  45                return axienet_get_schedule(dev, rq->ifr_data);
  46#endif
  47        default:
  48                return -EOPNOTSUPP;
  49        }
  50}
  51
  52/**
  53 * tsn_ep_xmit - TSN endpoint xmit routine.
  54 * @skb: Packet data
  55 * @dev: Pointer to the net_device structure
  56 *
  57 * Return: Always returns NETDEV_TX_OK.
  58 *
  59 * This is dummy xmit function for endpoint as all the data path is assumed to
  60 * be connected by TEMAC1 as per linux view
  61 */
  62static int tsn_ep_xmit(struct sk_buff *skb, struct net_device *dev)
  63{
  64        kfree_skb(skb);
  65        return NETDEV_TX_OK;
  66}
  67
  68static const struct net_device_ops ep_netdev_ops = {
  69        .ndo_do_ioctl = tsn_ep_ioctl,
  70        .ndo_start_xmit = tsn_ep_xmit,
  71};
  72
  73static const struct of_device_id tsn_ep_of_match[] = {
  74        { .compatible = "xlnx,tsn-ep"},
  75        {},
  76};
  77
  78MODULE_DEVICE_TABLE(of, tsn_ep_of_match);
  79
  80/**
  81 * tsn_ep_probe - TSN ep pointer probe function.
  82 * @pdev:       Pointer to platform device structure.
  83 *
  84 * Return: 0, on success
  85 *          Non-zero error value on failure.
  86 *
  87 * This is the probe routine for TSN endpoint driver.
  88 */
  89static int tsn_ep_probe(struct platform_device *pdev)
  90{
  91        int ret = 0;
  92        struct axienet_local *lp;
  93        struct net_device *ndev;
  94        struct resource *ethres;
  95        u16 num_tc = 0;
  96
  97        ndev = alloc_netdev(0, "ep", NET_NAME_UNKNOWN, ether_setup);
  98        if (!ndev)
  99                return -ENOMEM;
 100
 101        platform_set_drvdata(pdev, ndev);
 102
 103        SET_NETDEV_DEV(ndev, &pdev->dev);
 104        ndev->netdev_ops = &ep_netdev_ops;
 105
 106        lp = netdev_priv(ndev);
 107        lp->ndev = ndev;
 108        lp->dev = &pdev->dev;
 109        lp->options = XAE_OPTION_DEFAULTS;
 110
 111        ret = of_property_read_u16(
 112                pdev->dev.of_node, "xlnx,num-tc", &num_tc);
 113        if (ret || (num_tc != 2 && num_tc != 3))
 114                lp->num_tc = XAE_MAX_TSN_TC;
 115        else
 116                lp->num_tc = num_tc;
 117        /* Map device registers */
 118        ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 119        lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
 120        if (IS_ERR(lp->regs)) {
 121                ret = PTR_ERR(lp->regs);
 122                goto free_netdev;
 123        }
 124
 125        ret = register_netdev(lp->ndev);
 126        if (ret)
 127                dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
 128
 129        return ret;
 130
 131free_netdev:
 132        free_netdev(ndev);
 133
 134        return ret;
 135}
 136
 137static int tsn_ep_remove(struct platform_device *pdev)
 138{
 139        struct net_device *ndev = platform_get_drvdata(pdev);
 140
 141        unregister_netdev(ndev);
 142
 143        free_netdev(ndev);
 144
 145        return 0;
 146}
 147
 148static struct platform_driver tsn_ep_driver = {
 149        .probe = tsn_ep_probe,
 150        .remove = tsn_ep_remove,
 151        .driver = {
 152                 .name = "tsn_ep_axienet",
 153                 .of_match_table = tsn_ep_of_match,
 154        },
 155};
 156
 157module_platform_driver(tsn_ep_driver);
 158
 159MODULE_DESCRIPTION("Xilinx Axi Ethernet driver");
 160MODULE_AUTHOR("Xilinx");
 161MODULE_LICENSE("GPL v2");
 162