Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: macb: Added PCI wrapper for Platform Driver.

There are hardware PCI implementations of Cadence GEM network
controller. This patch will allow to use such hardware with reuse of
existing Platform Driver.

Signed-off-by: Bartosz Folta <bfolta@cadence.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Bartosz Folta and committed by
David S. Miller
83a77e9e 94acf164

+195 -5
+9
drivers/net/ethernet/cadence/Kconfig
··· 31 31 To compile this driver as a module, choose M here: the module 32 32 will be called macb. 33 33 34 + config MACB_PCI 35 + tristate "Cadence PCI MACB/GEM support" 36 + depends on MACB && PCI && COMMON_CLK 37 + ---help--- 38 + This is PCI wrapper for MACB driver. 39 + 40 + To compile this driver as a module, choose M here: the module 41 + will be called macb_pci. 42 + 34 43 endif # NET_CADENCE
+1
drivers/net/ethernet/cadence/Makefile
··· 3 3 # 4 4 5 5 obj-$(CONFIG_MACB) += macb.o 6 + obj-$(CONFIG_MACB_PCI) += macb_pci.o
+26 -5
drivers/net/ethernet/cadence/macb.c
··· 404 404 phy_irq = gpio_to_irq(pdata->phy_irq_pin); 405 405 phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq; 406 406 } 407 + } else { 408 + phydev->irq = PHY_POLL; 407 409 } 408 410 409 411 /* attach the mac to the phy */ ··· 484 482 goto err_out_unregister_bus; 485 483 } 486 484 } else { 485 + for (i = 0; i < PHY_MAX_ADDR; i++) 486 + bp->mii_bus->irq[i] = PHY_POLL; 487 + 487 488 if (pdata) 488 489 bp->mii_bus->phy_mask = pdata->phy_mask; 489 490 ··· 2528 2523 struct clk **hclk, struct clk **tx_clk, 2529 2524 struct clk **rx_clk) 2530 2525 { 2526 + struct macb_platform_data *pdata; 2531 2527 int err; 2532 2528 2533 - *pclk = devm_clk_get(&pdev->dev, "pclk"); 2529 + pdata = dev_get_platdata(&pdev->dev); 2530 + if (pdata) { 2531 + *pclk = pdata->pclk; 2532 + *hclk = pdata->hclk; 2533 + } else { 2534 + *pclk = devm_clk_get(&pdev->dev, "pclk"); 2535 + *hclk = devm_clk_get(&pdev->dev, "hclk"); 2536 + } 2537 + 2534 2538 if (IS_ERR(*pclk)) { 2535 2539 err = PTR_ERR(*pclk); 2536 2540 dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err); 2537 2541 return err; 2538 2542 } 2539 2543 2540 - *hclk = devm_clk_get(&pdev->dev, "hclk"); 2541 2544 if (IS_ERR(*hclk)) { 2542 2545 err = PTR_ERR(*hclk); 2543 2546 dev_err(&pdev->dev, "failed to get hclk (%u)\n", err); ··· 3120 3107 MODULE_DEVICE_TABLE(of, macb_dt_ids); 3121 3108 #endif /* CONFIG_OF */ 3122 3109 3110 + static const struct macb_config default_gem_config = { 3111 + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO, 3112 + .dma_burst_length = 16, 3113 + .clk_init = macb_clk_init, 3114 + .init = macb_init, 3115 + .jumbo_max_len = 10240, 3116 + }; 3117 + 3123 3118 static int macb_probe(struct platform_device *pdev) 3124 3119 { 3120 + const struct macb_config *macb_config = &default_gem_config; 3125 3121 int (*clk_init)(struct platform_device *, struct clk **, 3126 3122 struct clk **, struct clk **, struct clk **) 3127 - = macb_clk_init; 3128 - int (*init)(struct platform_device *) = macb_init; 3123 + = macb_config->clk_init; 3124 + int (*init)(struct platform_device *) = macb_config->init; 3129 3125 struct device_node *np = pdev->dev.of_node; 3130 3126 struct device_node *phy_node; 3131 - const struct macb_config *macb_config = NULL; 3132 3127 struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL; 3133 3128 unsigned int queue_mask, num_queues; 3134 3129 struct macb_platform_data *pdata;
+153
drivers/net/ethernet/cadence/macb_pci.c
··· 1 + /** 2 + * macb_pci.c - Cadence GEM PCI wrapper. 3 + * 4 + * Copyright (C) 2016 Cadence Design Systems - http://www.cadence.com 5 + * 6 + * Authors: Rafal Ozieblo <rafalo@cadence.com> 7 + * Bartosz Folta <bfolta@cadence.com> 8 + * 9 + * This program is free software: you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 of 11 + * the License as published by the Free Software Foundation. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 + */ 21 + 22 + #include <linux/clk.h> 23 + #include <linux/clk-provider.h> 24 + #include <linux/etherdevice.h> 25 + #include <linux/module.h> 26 + #include <linux/pci.h> 27 + #include <linux/platform_data/macb.h> 28 + #include <linux/platform_device.h> 29 + #include "macb.h" 30 + 31 + #define PCI_DRIVER_NAME "macb_pci" 32 + #define PLAT_DRIVER_NAME "macb" 33 + 34 + #define CDNS_VENDOR_ID 0x17cd 35 + #define CDNS_DEVICE_ID 0xe007 36 + 37 + #define GEM_PCLK_RATE 50000000 38 + #define GEM_HCLK_RATE 50000000 39 + 40 + static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id) 41 + { 42 + int err; 43 + struct platform_device *plat_dev; 44 + struct platform_device_info plat_info; 45 + struct macb_platform_data plat_data; 46 + struct resource res[2]; 47 + 48 + /* sanity check */ 49 + if (!id) 50 + return -EINVAL; 51 + 52 + /* enable pci device */ 53 + err = pci_enable_device(pdev); 54 + if (err < 0) { 55 + dev_err(&pdev->dev, "Enabling PCI device has failed: 0x%04X", 56 + err); 57 + return -EACCES; 58 + } 59 + 60 + pci_set_master(pdev); 61 + 62 + /* set up resources */ 63 + memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); 64 + res[0].start = pdev->resource[0].start; 65 + res[0].end = pdev->resource[0].end; 66 + res[0].name = PCI_DRIVER_NAME; 67 + res[0].flags = IORESOURCE_MEM; 68 + res[1].start = pdev->irq; 69 + res[1].name = PCI_DRIVER_NAME; 70 + res[1].flags = IORESOURCE_IRQ; 71 + 72 + dev_info(&pdev->dev, "EMAC physical base addr = 0x%p\n", 73 + (void *)(uintptr_t)pci_resource_start(pdev, 0)); 74 + 75 + /* set up macb platform data */ 76 + memset(&plat_data, 0, sizeof(plat_data)); 77 + 78 + /* initialize clocks */ 79 + plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0, 80 + GEM_PCLK_RATE); 81 + if (IS_ERR(plat_data.pclk)) { 82 + err = PTR_ERR(plat_data.pclk); 83 + goto err_pclk_register; 84 + } 85 + 86 + plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0, 87 + GEM_HCLK_RATE); 88 + if (IS_ERR(plat_data.hclk)) { 89 + err = PTR_ERR(plat_data.hclk); 90 + goto err_hclk_register; 91 + } 92 + 93 + /* set up platform device info */ 94 + memset(&plat_info, 0, sizeof(plat_info)); 95 + plat_info.parent = &pdev->dev; 96 + plat_info.fwnode = pdev->dev.fwnode; 97 + plat_info.name = PLAT_DRIVER_NAME; 98 + plat_info.id = pdev->devfn; 99 + plat_info.res = res; 100 + plat_info.num_res = ARRAY_SIZE(res); 101 + plat_info.data = &plat_data; 102 + plat_info.size_data = sizeof(plat_data); 103 + plat_info.dma_mask = DMA_BIT_MASK(32); 104 + 105 + /* register platform device */ 106 + plat_dev = platform_device_register_full(&plat_info); 107 + if (IS_ERR(plat_dev)) { 108 + err = PTR_ERR(plat_dev); 109 + goto err_plat_dev_register; 110 + } 111 + 112 + pci_set_drvdata(pdev, plat_dev); 113 + 114 + return 0; 115 + 116 + err_plat_dev_register: 117 + clk_unregister(plat_data.hclk); 118 + 119 + err_hclk_register: 120 + clk_unregister(plat_data.pclk); 121 + 122 + err_pclk_register: 123 + pci_disable_device(pdev); 124 + return err; 125 + } 126 + 127 + static void macb_remove(struct pci_dev *pdev) 128 + { 129 + struct platform_device *plat_dev = pci_get_drvdata(pdev); 130 + struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev); 131 + 132 + platform_device_unregister(plat_dev); 133 + pci_disable_device(pdev); 134 + clk_unregister(plat_data->pclk); 135 + clk_unregister(plat_data->hclk); 136 + } 137 + 138 + static struct pci_device_id dev_id_table[] = { 139 + { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), }, 140 + { 0, } 141 + }; 142 + 143 + static struct pci_driver macb_pci_driver = { 144 + .name = PCI_DRIVER_NAME, 145 + .id_table = dev_id_table, 146 + .probe = macb_probe, 147 + .remove = macb_remove, 148 + }; 149 + 150 + module_pci_driver(macb_pci_driver); 151 + MODULE_DEVICE_TABLE(pci, dev_id_table); 152 + MODULE_LICENSE("GPL"); 153 + MODULE_DESCRIPTION("Cadence NIC PCI wrapper");
+6
include/linux/platform_data/macb.h
··· 8 8 #ifndef __MACB_PDATA_H__ 9 9 #define __MACB_PDATA_H__ 10 10 11 + #include <linux/clk.h> 12 + 11 13 /** 12 14 * struct macb_platform_data - platform data for MACB Ethernet 13 15 * @phy_mask: phy mask passed when register the MDIO bus ··· 17 15 * @phy_irq_pin: PHY IRQ 18 16 * @is_rmii: using RMII interface? 19 17 * @rev_eth_addr: reverse Ethernet address byte order 18 + * @pclk: platform clock 19 + * @hclk: AHB clock 20 20 */ 21 21 struct macb_platform_data { 22 22 u32 phy_mask; 23 23 int phy_irq_pin; 24 24 u8 is_rmii; 25 25 u8 rev_eth_addr; 26 + struct clk *pclk; 27 + struct clk *hclk; 26 28 }; 27 29 28 30 #endif /* __MACB_PDATA_H__ */