linux/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*******************************************************************************
   3  This contains the functions to handle the pci driver.
   4
   5  Copyright (C) 2011-2012  Vayavya Labs Pvt Ltd
   6
   7
   8  Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
   9  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
  10*******************************************************************************/
  11
  12#include <linux/clk-provider.h>
  13#include <linux/pci.h>
  14#include <linux/dmi.h>
  15
  16#include "stmmac.h"
  17
  18struct stmmac_pci_info {
  19        int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
  20};
  21
  22static void common_default_data(struct plat_stmmacenet_data *plat)
  23{
  24        plat->clk_csr = 2;      /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
  25        plat->has_gmac = 1;
  26        plat->force_sf_dma_mode = 1;
  27
  28        plat->mdio_bus_data->needs_reset = true;
  29
  30        /* Set default value for multicast hash bins */
  31        plat->multicast_filter_bins = HASH_TABLE_SIZE;
  32
  33        /* Set default value for unicast filter entries */
  34        plat->unicast_filter_entries = 1;
  35
  36        /* Set the maxmtu to a default of JUMBO_LEN */
  37        plat->maxmtu = JUMBO_LEN;
  38
  39        /* Set default number of RX and TX queues to use */
  40        plat->tx_queues_to_use = 1;
  41        plat->rx_queues_to_use = 1;
  42
  43        /* Disable Priority config by default */
  44        plat->tx_queues_cfg[0].use_prio = false;
  45        plat->rx_queues_cfg[0].use_prio = false;
  46
  47        /* Disable RX queues routing by default */
  48        plat->rx_queues_cfg[0].pkt_route = 0x0;
  49}
  50
  51static int stmmac_default_data(struct pci_dev *pdev,
  52                               struct plat_stmmacenet_data *plat)
  53{
  54        /* Set common default data first */
  55        common_default_data(plat);
  56
  57        plat->bus_id = 1;
  58        plat->phy_addr = 0;
  59        plat->phy_interface = PHY_INTERFACE_MODE_GMII;
  60
  61        plat->dma_cfg->pbl = 32;
  62        plat->dma_cfg->pblx8 = true;
  63        /* TODO: AXI */
  64
  65        return 0;
  66}
  67
  68static const struct stmmac_pci_info stmmac_pci_info = {
  69        .setup = stmmac_default_data,
  70};
  71
  72static int snps_gmac5_default_data(struct pci_dev *pdev,
  73                                   struct plat_stmmacenet_data *plat)
  74{
  75        int i;
  76
  77        plat->clk_csr = 5;
  78        plat->has_gmac4 = 1;
  79        plat->force_sf_dma_mode = 1;
  80        plat->tso_en = 1;
  81        plat->pmt = 1;
  82
  83        /* Set default value for multicast hash bins */
  84        plat->multicast_filter_bins = HASH_TABLE_SIZE;
  85
  86        /* Set default value for unicast filter entries */
  87        plat->unicast_filter_entries = 1;
  88
  89        /* Set the maxmtu to a default of JUMBO_LEN */
  90        plat->maxmtu = JUMBO_LEN;
  91
  92        /* Set default number of RX and TX queues to use */
  93        plat->tx_queues_to_use = 4;
  94        plat->rx_queues_to_use = 4;
  95
  96        plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR;
  97        for (i = 0; i < plat->tx_queues_to_use; i++) {
  98                plat->tx_queues_cfg[i].use_prio = false;
  99                plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
 100                plat->tx_queues_cfg[i].weight = 25;
 101                if (i > 0)
 102                        plat->tx_queues_cfg[i].tbs_en = 1;
 103        }
 104
 105        plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
 106        for (i = 0; i < plat->rx_queues_to_use; i++) {
 107                plat->rx_queues_cfg[i].use_prio = false;
 108                plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
 109                plat->rx_queues_cfg[i].pkt_route = 0x0;
 110                plat->rx_queues_cfg[i].chan = i;
 111        }
 112
 113        plat->bus_id = 1;
 114        plat->phy_addr = -1;
 115        plat->phy_interface = PHY_INTERFACE_MODE_GMII;
 116
 117        plat->dma_cfg->pbl = 32;
 118        plat->dma_cfg->pblx8 = true;
 119
 120        /* Axi Configuration */
 121        plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi), GFP_KERNEL);
 122        if (!plat->axi)
 123                return -ENOMEM;
 124
 125        plat->axi->axi_wr_osr_lmt = 31;
 126        plat->axi->axi_rd_osr_lmt = 31;
 127
 128        plat->axi->axi_fb = false;
 129        plat->axi->axi_blen[0] = 4;
 130        plat->axi->axi_blen[1] = 8;
 131        plat->axi->axi_blen[2] = 16;
 132        plat->axi->axi_blen[3] = 32;
 133
 134        return 0;
 135}
 136
 137static const struct stmmac_pci_info snps_gmac5_pci_info = {
 138        .setup = snps_gmac5_default_data,
 139};
 140
 141/**
 142 * stmmac_pci_probe
 143 *
 144 * @pdev: pci device pointer
 145 * @id: pointer to table of device id/id's.
 146 *
 147 * Description: This probing function gets called for all PCI devices which
 148 * match the ID table and are not "owned" by other driver yet. This function
 149 * gets passed a "struct pci_dev *" for each device whose entry in the ID table
 150 * matches the device. The probe functions returns zero when the driver choose
 151 * to take "ownership" of the device or an error code(-ve no) otherwise.
 152 */
 153static int stmmac_pci_probe(struct pci_dev *pdev,
 154                            const struct pci_device_id *id)
 155{
 156        struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
 157        struct plat_stmmacenet_data *plat;
 158        struct stmmac_resources res;
 159        int i;
 160        int ret;
 161
 162        plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 163        if (!plat)
 164                return -ENOMEM;
 165
 166        plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
 167                                           sizeof(*plat->mdio_bus_data),
 168                                           GFP_KERNEL);
 169        if (!plat->mdio_bus_data)
 170                return -ENOMEM;
 171
 172        plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
 173                                     GFP_KERNEL);
 174        if (!plat->dma_cfg)
 175                return -ENOMEM;
 176
 177        plat->safety_feat_cfg = devm_kzalloc(&pdev->dev,
 178                                             sizeof(*plat->safety_feat_cfg),
 179                                             GFP_KERNEL);
 180        if (!plat->safety_feat_cfg)
 181                return -ENOMEM;
 182
 183        /* Enable pci device */
 184        ret = pci_enable_device(pdev);
 185        if (ret) {
 186                dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
 187                        __func__);
 188                return ret;
 189        }
 190
 191        /* Get the base address of device */
 192        for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 193                if (pci_resource_len(pdev, i) == 0)
 194                        continue;
 195                ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
 196                if (ret)
 197                        return ret;
 198                break;
 199        }
 200
 201        pci_set_master(pdev);
 202
 203        ret = info->setup(pdev, plat);
 204        if (ret)
 205                return ret;
 206
 207        memset(&res, 0, sizeof(res));
 208        res.addr = pcim_iomap_table(pdev)[i];
 209        res.wol_irq = pdev->irq;
 210        res.irq = pdev->irq;
 211
 212        plat->safety_feat_cfg->tsoee = 1;
 213        plat->safety_feat_cfg->mrxpee = 1;
 214        plat->safety_feat_cfg->mestee = 1;
 215        plat->safety_feat_cfg->mrxee = 1;
 216        plat->safety_feat_cfg->mtxee = 1;
 217        plat->safety_feat_cfg->epsi = 1;
 218        plat->safety_feat_cfg->edpp = 1;
 219        plat->safety_feat_cfg->prtyen = 1;
 220        plat->safety_feat_cfg->tmouten = 1;
 221
 222        return stmmac_dvr_probe(&pdev->dev, plat, &res);
 223}
 224
 225/**
 226 * stmmac_pci_remove
 227 *
 228 * @pdev: platform device pointer
 229 * Description: this function calls the main to free the net resources
 230 * and releases the PCI resources.
 231 */
 232static void stmmac_pci_remove(struct pci_dev *pdev)
 233{
 234        int i;
 235
 236        stmmac_dvr_remove(&pdev->dev);
 237
 238        for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 239                if (pci_resource_len(pdev, i) == 0)
 240                        continue;
 241                pcim_iounmap_regions(pdev, BIT(i));
 242                break;
 243        }
 244
 245        pci_disable_device(pdev);
 246}
 247
 248static int __maybe_unused stmmac_pci_suspend(struct device *dev)
 249{
 250        struct pci_dev *pdev = to_pci_dev(dev);
 251        int ret;
 252
 253        ret = stmmac_suspend(dev);
 254        if (ret)
 255                return ret;
 256
 257        ret = pci_save_state(pdev);
 258        if (ret)
 259                return ret;
 260
 261        pci_disable_device(pdev);
 262        pci_wake_from_d3(pdev, true);
 263        return 0;
 264}
 265
 266static int __maybe_unused stmmac_pci_resume(struct device *dev)
 267{
 268        struct pci_dev *pdev = to_pci_dev(dev);
 269        int ret;
 270
 271        pci_restore_state(pdev);
 272        pci_set_power_state(pdev, PCI_D0);
 273
 274        ret = pci_enable_device(pdev);
 275        if (ret)
 276                return ret;
 277
 278        pci_set_master(pdev);
 279
 280        return stmmac_resume(dev);
 281}
 282
 283static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume);
 284
 285/* synthetic ID, no official vendor */
 286#define PCI_VENDOR_ID_STMMAC            0x0700
 287
 288#define PCI_DEVICE_ID_STMMAC_STMMAC             0x1108
 289#define PCI_DEVICE_ID_SYNOPSYS_GMAC5_ID         0x7102
 290
 291static const struct pci_device_id stmmac_id_table[] = {
 292        { PCI_DEVICE_DATA(STMMAC, STMMAC, &stmmac_pci_info) },
 293        { PCI_DEVICE_DATA(STMICRO, MAC, &stmmac_pci_info) },
 294        { PCI_DEVICE_DATA(SYNOPSYS, GMAC5_ID, &snps_gmac5_pci_info) },
 295        {}
 296};
 297
 298MODULE_DEVICE_TABLE(pci, stmmac_id_table);
 299
 300static struct pci_driver stmmac_pci_driver = {
 301        .name = STMMAC_RESOURCE_NAME,
 302        .id_table = stmmac_id_table,
 303        .probe = stmmac_pci_probe,
 304        .remove = stmmac_pci_remove,
 305        .driver         = {
 306                .pm     = &stmmac_pm_ops,
 307        },
 308};
 309
 310module_pci_driver(stmmac_pci_driver);
 311
 312MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
 313MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
 314MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
 315MODULE_LICENSE("GPL");
 316