@@ -24,16 +24,19 @@
*******************************************************************************/
#include <linux/pci.h>
+#include <linux/dmi.h>
#include "stmmac.h"
static int instance_id = 1;
+static void quark_run_time_config(int chip_id, struct pci_dev *pdev);
enum chip {
CHIP_STMICRO = 0,
+ CHIP_QUARK_X1000,
};
-/* A struct for platform specific information which will be
- * used in stmmac_default_data function for initialization
+/* A struct for platform specific information which is used
+ * in stmmac_default_data function for initialization
*/
struct platform_data {
int phy_addr;
@@ -46,7 +49,9 @@ struct platform_data {
int (*phy_reset)(void *priv);
unsigned int phy_mask;
int pbl;
+ int fixed_burst;
int burst_len;
+ void (*rt_config)(int chip_id, struct pci_dev *pdev);
};
static struct platform_data platform_info[] = {
@@ -61,15 +66,76 @@ static struct platform_data platform_info[] = {
.phy_reset = NULL,
.phy_mask = 0,
.pbl = 32,
+ .fixed_burst = 0,
.burst_len = DMA_AXI_BLEN_256,
+ .rt_config = NULL,
},
+ [CHIP_QUARK_X1000] = {
+ .phy_addr = 1,
+ .interface = PHY_INTERFACE_MODE_RMII,
+ .clk_csr = 2,
+ .has_gmac = 1,
+ .force_sf_dma_mode = 1,
+ .multicast_filter_bins = HASH_TABLE_SIZE,
+ .unicast_filter_entries = 1,
+ .phy_reset = NULL,
+ .phy_mask = 0,
+ .pbl = 16,
+ .fixed_burst = 1,
+ .burst_len = DMA_AXI_BLEN_256,
+ .rt_config = &quark_run_time_config,
+ },
+};
+
+/* This struct is used to associate PCI Function ID of MAC controller
+ * on a board, discovered via DMI, with phy_address. It is also used
+ * to describe if that MAC controller is connected with PHY.
+ */
+struct intel_quark_platform {
+ int pci_func_num;
+ const char *board_name;
+ int phy_address;
};
-static void stmmac_default_data(struct plat_stmmacenet_data *plat,
- int chip_id)
+static struct intel_quark_platform quark_x1000_phy_info[] = {
+ {
+ .pci_func_num = 7,
+ .board_name = "Galileo",
+ /* Galileo ethernet port 2 does not connect to any PHY */
+ .phy_address = -1,
+ },
+ {
+ .pci_func_num = 7,
+ .board_name = "GalileoGen2",
+ /* Galileo Gen2 ethernet port 2 does not connect to any PHY */
+ .phy_address = -1,
+ },
+};
+
+static void quark_run_time_config(int chip_id, struct pci_dev *pdev)
+{
+ const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
+ int i;
+ int func_num = PCI_FUNC(pdev->devfn);
+
+ if (!board_name)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(quark_x1000_phy_info); i++) {
+ if ((!strcmp(quark_x1000_phy_info[i].board_name, board_name)) &&
+ quark_x1000_phy_info[i].pci_func_num == func_num)
+ platform_info[chip_id].phy_addr =
+ quark_x1000_phy_info[i].phy_address;
+ }
+}
+
+static int stmmac_default_data(struct plat_stmmacenet_data *plat,
+ int chip_id, struct pci_dev *pdev)
{
struct platform_data *chip_plat_dat = &platform_info[chip_id];
+ if (chip_plat_dat->rt_config)
+ chip_plat_dat->rt_config(chip_id, pdev);
plat->bus_id = instance_id++;
plat->phy_addr = chip_plat_dat->phy_addr;
plat->interface = chip_plat_dat->interface;
@@ -84,7 +150,13 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat,
plat->mdio_bus_data->phy_mask = chip_plat_dat->phy_mask;
plat->dma_cfg->pbl = chip_plat_dat->pbl;
+ plat->dma_cfg->fixed_burst = chip_plat_dat->fixed_burst;
plat->dma_cfg->burst_len = chip_plat_dat->burst_len;
+
+ /* Refuse to load the driver and register net device
+ * if MAC controller does not connect to any PHY interface
+ */
+ return (plat->phy_addr != -1) ? 0 : -ENODEV;
}
/**
@@ -158,7 +230,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
goto err_out;
}
- stmmac_default_data(plat_dat, id->driver_data);
+ ret = stmmac_default_data(plat_dat, id->driver_data, pdev);
+ if (ret)
+ goto err_out;
priv = stmmac_dvr_probe(&pdev->dev, plat_dat, addr);
if (IS_ERR(priv)) {
@@ -230,11 +304,13 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
#define STMMAC_VENDOR_ID 0x700
#define STMMAC_DEVICE_ID 0x1108
+#define STMMAC_QUARK_X1000_ID 0x0937
static const struct pci_device_id stmmac_id_table[] = {
{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID), PCI_ANY_ID,
PCI_ANY_ID, CHIP_STMICRO},
{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC), CHIP_STMICRO},
+ {PCI_VDEVICE(INTEL, STMMAC_QUARK_X1000_ID), CHIP_QUARK_X1000},
{}
};