Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*******************************************************************************
0003   This contains the functions to handle the pci driver.
0004 
0005   Copyright (C) 2011-2012  Vayavya Labs Pvt Ltd
0006 
0007 
0008   Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
0009   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
0010 *******************************************************************************/
0011 
0012 #include <linux/clk-provider.h>
0013 #include <linux/pci.h>
0014 #include <linux/dmi.h>
0015 
0016 #include "stmmac.h"
0017 
0018 struct stmmac_pci_info {
0019     int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
0020 };
0021 
0022 static void common_default_data(struct plat_stmmacenet_data *plat)
0023 {
0024     plat->clk_csr = 2;  /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
0025     plat->has_gmac = 1;
0026     plat->force_sf_dma_mode = 1;
0027 
0028     plat->mdio_bus_data->needs_reset = true;
0029 
0030     /* Set default value for multicast hash bins */
0031     plat->multicast_filter_bins = HASH_TABLE_SIZE;
0032 
0033     /* Set default value for unicast filter entries */
0034     plat->unicast_filter_entries = 1;
0035 
0036     /* Set the maxmtu to a default of JUMBO_LEN */
0037     plat->maxmtu = JUMBO_LEN;
0038 
0039     /* Set default number of RX and TX queues to use */
0040     plat->tx_queues_to_use = 1;
0041     plat->rx_queues_to_use = 1;
0042 
0043     /* Disable Priority config by default */
0044     plat->tx_queues_cfg[0].use_prio = false;
0045     plat->rx_queues_cfg[0].use_prio = false;
0046 
0047     /* Disable RX queues routing by default */
0048     plat->rx_queues_cfg[0].pkt_route = 0x0;
0049 }
0050 
0051 static int stmmac_default_data(struct pci_dev *pdev,
0052                    struct plat_stmmacenet_data *plat)
0053 {
0054     /* Set common default data first */
0055     common_default_data(plat);
0056 
0057     plat->bus_id = 1;
0058     plat->phy_addr = 0;
0059     plat->phy_interface = PHY_INTERFACE_MODE_GMII;
0060 
0061     plat->dma_cfg->pbl = 32;
0062     plat->dma_cfg->pblx8 = true;
0063     /* TODO: AXI */
0064 
0065     return 0;
0066 }
0067 
0068 static const struct stmmac_pci_info stmmac_pci_info = {
0069     .setup = stmmac_default_data,
0070 };
0071 
0072 static int snps_gmac5_default_data(struct pci_dev *pdev,
0073                    struct plat_stmmacenet_data *plat)
0074 {
0075     int i;
0076 
0077     plat->clk_csr = 5;
0078     plat->has_gmac4 = 1;
0079     plat->force_sf_dma_mode = 1;
0080     plat->tso_en = 1;
0081     plat->pmt = 1;
0082 
0083     /* Set default value for multicast hash bins */
0084     plat->multicast_filter_bins = HASH_TABLE_SIZE;
0085 
0086     /* Set default value for unicast filter entries */
0087     plat->unicast_filter_entries = 1;
0088 
0089     /* Set the maxmtu to a default of JUMBO_LEN */
0090     plat->maxmtu = JUMBO_LEN;
0091 
0092     /* Set default number of RX and TX queues to use */
0093     plat->tx_queues_to_use = 4;
0094     plat->rx_queues_to_use = 4;
0095 
0096     plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR;
0097     for (i = 0; i < plat->tx_queues_to_use; i++) {
0098         plat->tx_queues_cfg[i].use_prio = false;
0099         plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
0100         plat->tx_queues_cfg[i].weight = 25;
0101         if (i > 0)
0102             plat->tx_queues_cfg[i].tbs_en = 1;
0103     }
0104 
0105     plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
0106     for (i = 0; i < plat->rx_queues_to_use; i++) {
0107         plat->rx_queues_cfg[i].use_prio = false;
0108         plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
0109         plat->rx_queues_cfg[i].pkt_route = 0x0;
0110         plat->rx_queues_cfg[i].chan = i;
0111     }
0112 
0113     plat->bus_id = 1;
0114     plat->phy_addr = -1;
0115     plat->phy_interface = PHY_INTERFACE_MODE_GMII;
0116 
0117     plat->dma_cfg->pbl = 32;
0118     plat->dma_cfg->pblx8 = true;
0119 
0120     /* Axi Configuration */
0121     plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi), GFP_KERNEL);
0122     if (!plat->axi)
0123         return -ENOMEM;
0124 
0125     plat->axi->axi_wr_osr_lmt = 31;
0126     plat->axi->axi_rd_osr_lmt = 31;
0127 
0128     plat->axi->axi_fb = false;
0129     plat->axi->axi_blen[0] = 4;
0130     plat->axi->axi_blen[1] = 8;
0131     plat->axi->axi_blen[2] = 16;
0132     plat->axi->axi_blen[3] = 32;
0133 
0134     return 0;
0135 }
0136 
0137 static const struct stmmac_pci_info snps_gmac5_pci_info = {
0138     .setup = snps_gmac5_default_data,
0139 };
0140 
0141 /**
0142  * stmmac_pci_probe
0143  *
0144  * @pdev: pci device pointer
0145  * @id: pointer to table of device id/id's.
0146  *
0147  * Description: This probing function gets called for all PCI devices which
0148  * match the ID table and are not "owned" by other driver yet. This function
0149  * gets passed a "struct pci_dev *" for each device whose entry in the ID table
0150  * matches the device. The probe functions returns zero when the driver choose
0151  * to take "ownership" of the device or an error code(-ve no) otherwise.
0152  */
0153 static int stmmac_pci_probe(struct pci_dev *pdev,
0154                 const struct pci_device_id *id)
0155 {
0156     struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
0157     struct plat_stmmacenet_data *plat;
0158     struct stmmac_resources res;
0159     int i;
0160     int ret;
0161 
0162     plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
0163     if (!plat)
0164         return -ENOMEM;
0165 
0166     plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
0167                        sizeof(*plat->mdio_bus_data),
0168                        GFP_KERNEL);
0169     if (!plat->mdio_bus_data)
0170         return -ENOMEM;
0171 
0172     plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
0173                      GFP_KERNEL);
0174     if (!plat->dma_cfg)
0175         return -ENOMEM;
0176 
0177     plat->safety_feat_cfg = devm_kzalloc(&pdev->dev,
0178                          sizeof(*plat->safety_feat_cfg),
0179                          GFP_KERNEL);
0180     if (!plat->safety_feat_cfg)
0181         return -ENOMEM;
0182 
0183     /* Enable pci device */
0184     ret = pcim_enable_device(pdev);
0185     if (ret) {
0186         dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
0187             __func__);
0188         return ret;
0189     }
0190 
0191     /* Get the base address of device */
0192     for (i = 0; i < PCI_STD_NUM_BARS; i++) {
0193         if (pci_resource_len(pdev, i) == 0)
0194             continue;
0195         ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
0196         if (ret)
0197             return ret;
0198         break;
0199     }
0200 
0201     pci_set_master(pdev);
0202 
0203     ret = info->setup(pdev, plat);
0204     if (ret)
0205         return ret;
0206 
0207     memset(&res, 0, sizeof(res));
0208     res.addr = pcim_iomap_table(pdev)[i];
0209     res.wol_irq = pdev->irq;
0210     res.irq = pdev->irq;
0211 
0212     plat->safety_feat_cfg->tsoee = 1;
0213     plat->safety_feat_cfg->mrxpee = 1;
0214     plat->safety_feat_cfg->mestee = 1;
0215     plat->safety_feat_cfg->mrxee = 1;
0216     plat->safety_feat_cfg->mtxee = 1;
0217     plat->safety_feat_cfg->epsi = 1;
0218     plat->safety_feat_cfg->edpp = 1;
0219     plat->safety_feat_cfg->prtyen = 1;
0220     plat->safety_feat_cfg->tmouten = 1;
0221 
0222     return stmmac_dvr_probe(&pdev->dev, plat, &res);
0223 }
0224 
0225 /**
0226  * stmmac_pci_remove
0227  *
0228  * @pdev: platform device pointer
0229  * Description: this function calls the main to free the net resources
0230  * and releases the PCI resources.
0231  */
0232 static void stmmac_pci_remove(struct pci_dev *pdev)
0233 {
0234     int i;
0235 
0236     stmmac_dvr_remove(&pdev->dev);
0237 
0238     for (i = 0; i < PCI_STD_NUM_BARS; i++) {
0239         if (pci_resource_len(pdev, i) == 0)
0240             continue;
0241         pcim_iounmap_regions(pdev, BIT(i));
0242         break;
0243     }
0244 }
0245 
0246 static int __maybe_unused stmmac_pci_suspend(struct device *dev)
0247 {
0248     struct pci_dev *pdev = to_pci_dev(dev);
0249     int ret;
0250 
0251     ret = stmmac_suspend(dev);
0252     if (ret)
0253         return ret;
0254 
0255     ret = pci_save_state(pdev);
0256     if (ret)
0257         return ret;
0258 
0259     pci_disable_device(pdev);
0260     pci_wake_from_d3(pdev, true);
0261     return 0;
0262 }
0263 
0264 static int __maybe_unused stmmac_pci_resume(struct device *dev)
0265 {
0266     struct pci_dev *pdev = to_pci_dev(dev);
0267     int ret;
0268 
0269     pci_restore_state(pdev);
0270     pci_set_power_state(pdev, PCI_D0);
0271 
0272     ret = pci_enable_device(pdev);
0273     if (ret)
0274         return ret;
0275 
0276     pci_set_master(pdev);
0277 
0278     return stmmac_resume(dev);
0279 }
0280 
0281 static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume);
0282 
0283 /* synthetic ID, no official vendor */
0284 #define PCI_VENDOR_ID_STMMAC        0x0700
0285 
0286 #define PCI_DEVICE_ID_STMMAC_STMMAC     0x1108
0287 #define PCI_DEVICE_ID_SYNOPSYS_GMAC5_ID     0x7102
0288 
0289 static const struct pci_device_id stmmac_id_table[] = {
0290     { PCI_DEVICE_DATA(STMMAC, STMMAC, &stmmac_pci_info) },
0291     { PCI_DEVICE_DATA(STMICRO, MAC, &stmmac_pci_info) },
0292     { PCI_DEVICE_DATA(SYNOPSYS, GMAC5_ID, &snps_gmac5_pci_info) },
0293     {}
0294 };
0295 
0296 MODULE_DEVICE_TABLE(pci, stmmac_id_table);
0297 
0298 static struct pci_driver stmmac_pci_driver = {
0299     .name = STMMAC_RESOURCE_NAME,
0300     .id_table = stmmac_id_table,
0301     .probe = stmmac_pci_probe,
0302     .remove = stmmac_pci_remove,
0303     .driver         = {
0304         .pm     = &stmmac_pm_ops,
0305     },
0306 };
0307 
0308 module_pci_driver(stmmac_pci_driver);
0309 
0310 MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
0311 MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
0312 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
0313 MODULE_LICENSE("GPL");