diff options
| author | David S. Miller <davem@davemloft.net> | 2015-01-28 00:08:13 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-01-28 00:08:13 -0500 |
| commit | ff660f75be36e6db75d45dc742a4a468c5a9c20d (patch) | |
| tree | 36c2647d695b08324f11336e29cb52fc98578b04 | |
| parent | 488327c6ef2a2f39adc6d9f017745921c8b747e5 (diff) | |
| parent | d2a029bde37b4c2e2d8b26e7457bb2c58afbbadd (diff) | |
Merge branch 'stmmac-pci'
Andy Shevchenko says:
====================
stmmac: Enable Intel Quark SoC X1000 Ethernet support
This is third version of the patch series [1] to bring network card support to
Intel Quark SoC.
The series has been tested on Intel Galileo board.
Changelog v3:
- rebase on top of recent net-next
- rework an approach to get the custom configuration
- rework an approach how to get unique bus_id
- improve DMI lookup function
[1] http://www.spinics.net/lists/netdev/msg296010.html
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 054520d67de4..3bca908716e2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | |||
| @@ -24,8 +24,50 @@ | |||
| 24 | *******************************************************************************/ | 24 | *******************************************************************************/ |
| 25 | 25 | ||
| 26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
| 27 | #include <linux/dmi.h> | ||
| 28 | |||
| 27 | #include "stmmac.h" | 29 | #include "stmmac.h" |
| 28 | 30 | ||
| 31 | /* | ||
| 32 | * This struct is used to associate PCI Function of MAC controller on a board, | ||
| 33 | * discovered via DMI, with the address of PHY connected to the MAC. The | ||
| 34 | * negative value of the address means that MAC controller is not connected | ||
| 35 | * with PHY. | ||
| 36 | */ | ||
| 37 | struct stmmac_pci_dmi_data { | ||
| 38 | const char *name; | ||
| 39 | unsigned int func; | ||
| 40 | int phy_addr; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct stmmac_pci_info { | ||
| 44 | struct pci_dev *pdev; | ||
| 45 | int (*setup)(struct plat_stmmacenet_data *plat, | ||
| 46 | struct stmmac_pci_info *info); | ||
| 47 | struct stmmac_pci_dmi_data *dmi; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info) | ||
| 51 | { | ||
| 52 | const char *name = dmi_get_system_info(DMI_BOARD_NAME); | ||
| 53 | unsigned int func = PCI_FUNC(info->pdev->devfn); | ||
| 54 | struct stmmac_pci_dmi_data *dmi; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Galileo boards with old firmware don't support DMI. We always return | ||
| 58 | * 1 here, so at least first found MAC controller would be probed. | ||
| 59 | */ | ||
| 60 | if (!name) | ||
| 61 | return 1; | ||
| 62 | |||
| 63 | for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) { | ||
| 64 | if (!strcmp(dmi->name, name) && dmi->func == func) | ||
| 65 | return dmi->phy_addr; | ||
| 66 | } | ||
| 67 | |||
| 68 | return -ENODEV; | ||
| 69 | } | ||
| 70 | |||
| 29 | static void stmmac_default_data(struct plat_stmmacenet_data *plat) | 71 | static void stmmac_default_data(struct plat_stmmacenet_data *plat) |
| 30 | { | 72 | { |
| 31 | plat->bus_id = 1; | 73 | plat->bus_id = 1; |
| @@ -48,6 +90,62 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat) | |||
| 48 | plat->unicast_filter_entries = 1; | 90 | plat->unicast_filter_entries = 1; |
| 49 | } | 91 | } |
| 50 | 92 | ||
| 93 | static int quark_default_data(struct plat_stmmacenet_data *plat, | ||
| 94 | struct stmmac_pci_info *info) | ||
| 95 | { | ||
| 96 | struct pci_dev *pdev = info->pdev; | ||
| 97 | int ret; | ||
| 98 | |||
| 99 | /* | ||
| 100 | * Refuse to load the driver and register net device if MAC controller | ||
| 101 | * does not connect to any PHY interface. | ||
| 102 | */ | ||
| 103 | ret = stmmac_pci_find_phy_addr(info); | ||
| 104 | if (ret < 0) | ||
| 105 | return ret; | ||
| 106 | |||
| 107 | plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn); | ||
| 108 | plat->phy_addr = ret; | ||
| 109 | plat->interface = PHY_INTERFACE_MODE_RMII; | ||
| 110 | plat->clk_csr = 2; | ||
| 111 | plat->has_gmac = 1; | ||
| 112 | plat->force_sf_dma_mode = 1; | ||
| 113 | |||
| 114 | plat->mdio_bus_data->phy_reset = NULL; | ||
| 115 | plat->mdio_bus_data->phy_mask = 0; | ||
| 116 | |||
| 117 | plat->dma_cfg->pbl = 16; | ||
| 118 | plat->dma_cfg->burst_len = DMA_AXI_BLEN_256; | ||
| 119 | plat->dma_cfg->fixed_burst = 1; | ||
| 120 | |||
| 121 | /* Set default value for multicast hash bins */ | ||
| 122 | plat->multicast_filter_bins = HASH_TABLE_SIZE; | ||
| 123 | |||
| 124 | /* Set default value for unicast filter entries */ | ||
| 125 | plat->unicast_filter_entries = 1; | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = { | ||
| 131 | { | ||
| 132 | .name = "Galileo", | ||
| 133 | .func = 6, | ||
| 134 | .phy_addr = 1, | ||
| 135 | }, | ||
| 136 | { | ||
| 137 | .name = "GalileoGen2", | ||
| 138 | .func = 6, | ||
| 139 | .phy_addr = 1, | ||
| 140 | }, | ||
| 141 | {} | ||
| 142 | }; | ||
| 143 | |||
| 144 | static struct stmmac_pci_info quark_pci_info = { | ||
| 145 | .setup = quark_default_data, | ||
| 146 | .dmi = quark_pci_dmi_data, | ||
| 147 | }; | ||
| 148 | |||
| 51 | /** | 149 | /** |
| 52 | * stmmac_pci_probe | 150 | * stmmac_pci_probe |
| 53 | * | 151 | * |
| @@ -63,6 +161,7 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat) | |||
| 63 | static int stmmac_pci_probe(struct pci_dev *pdev, | 161 | static int stmmac_pci_probe(struct pci_dev *pdev, |
| 64 | const struct pci_device_id *id) | 162 | const struct pci_device_id *id) |
| 65 | { | 163 | { |
| 164 | struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data; | ||
| 66 | struct plat_stmmacenet_data *plat; | 165 | struct plat_stmmacenet_data *plat; |
| 67 | struct stmmac_priv *priv; | 166 | struct stmmac_priv *priv; |
| 68 | int i; | 167 | int i; |
| @@ -103,7 +202,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev, | |||
| 103 | 202 | ||
| 104 | pci_set_master(pdev); | 203 | pci_set_master(pdev); |
| 105 | 204 | ||
| 106 | stmmac_default_data(plat); | 205 | if (info) { |
| 206 | info->pdev = pdev; | ||
| 207 | if (info->setup) { | ||
| 208 | ret = info->setup(plat, info); | ||
| 209 | if (ret) | ||
| 210 | return ret; | ||
| 211 | } | ||
| 212 | } else | ||
| 213 | stmmac_default_data(plat); | ||
| 214 | |||
| 215 | pci_enable_msi(pdev); | ||
| 107 | 216 | ||
| 108 | priv = stmmac_dvr_probe(&pdev->dev, plat, pcim_iomap_table(pdev)[i]); | 217 | priv = stmmac_dvr_probe(&pdev->dev, plat, pcim_iomap_table(pdev)[i]); |
| 109 | if (IS_ERR(priv)) { | 218 | if (IS_ERR(priv)) { |
| @@ -155,11 +264,13 @@ static int stmmac_pci_resume(struct device *dev) | |||
| 155 | static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); | 264 | static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); |
| 156 | 265 | ||
| 157 | #define STMMAC_VENDOR_ID 0x700 | 266 | #define STMMAC_VENDOR_ID 0x700 |
| 267 | #define STMMAC_QUARK_ID 0x0937 | ||
| 158 | #define STMMAC_DEVICE_ID 0x1108 | 268 | #define STMMAC_DEVICE_ID 0x1108 |
| 159 | 269 | ||
| 160 | static const struct pci_device_id stmmac_id_table[] = { | 270 | static const struct pci_device_id stmmac_id_table[] = { |
| 161 | {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, | 271 | {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, |
| 162 | {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)}, | 272 | {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)}, |
| 273 | {PCI_VDEVICE(INTEL, STMMAC_QUARK_ID), (kernel_ulong_t)&quark_pci_info}, | ||
| 163 | {} | 274 | {} |
| 164 | }; | 275 | }; |
| 165 | 276 | ||
