diff options
Diffstat (limited to 'drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c')
-rw-r--r-- | drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index ab1039a..5a0f04c 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/net_tstamp.h> #include <linux/ptp_classify.h> +#include <linux/gpio.h> #define DRV_VERSION "1.01" const char pch_driver_version[] = DRV_VERSION; @@ -111,6 +112,8 @@ const char pch_driver_version[] = DRV_VERSION; #define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81" #define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00" +#define MINNOW_PHY_RESET_GPIO 13 + static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT; static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg); @@ -682,7 +685,7 @@ static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter) } adapter->hw.phy.addr = adapter->mii.phy_id; netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id); - if (addr == 32) + if (addr == PCH_GBE_PHY_REGS_LEN) return -EAGAIN; /* Selected the phy and isolate the rest */ for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) { @@ -1488,9 +1491,9 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter, bufsz = adapter->rx_buffer_len; size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY; - rx_ring->rx_buff_pool = dma_alloc_coherent(&pdev->dev, size, - &rx_ring->rx_buff_pool_logic, - GFP_KERNEL | __GFP_ZERO); + rx_ring->rx_buff_pool = + dma_zalloc_coherent(&pdev->dev, size, + &rx_ring->rx_buff_pool_logic, GFP_KERNEL); if (!rx_ring->rx_buff_pool) return -ENOMEM; @@ -1804,9 +1807,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc); - tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, - &tx_ring->dma, - GFP_KERNEL | __GFP_ZERO); + tx_ring->desc = dma_zalloc_coherent(&pdev->dev, tx_ring->size, + &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) { vfree(tx_ring->buffer_info); return -ENOMEM; @@ -1849,9 +1851,8 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter, return -ENOMEM; rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc); - rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, - &rx_ring->dma, - GFP_KERNEL | __GFP_ZERO); + rx_ring->desc = dma_zalloc_coherent(&pdev->dev, rx_ring->size, + &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) { vfree(rx_ring->buffer_info); return -ENOMEM; @@ -2635,6 +2636,9 @@ static int pch_gbe_probe(struct pci_dev *pdev, adapter->pdev = pdev; adapter->hw.back = adapter; adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR]; + adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data; + if (adapter->pdata && adapter->pdata->platform_init) + adapter->pdata->platform_init(pdev); adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, PCI_DEVFN(12, 4)); @@ -2710,6 +2714,10 @@ static int pch_gbe_probe(struct pci_dev *pdev, dev_dbg(&pdev->dev, "PCH Network Connection\n"); + /* Disable hibernation on certain platforms */ + if (adapter->pdata && adapter->pdata->phy_disable_hibernate) + pch_gbe_phy_disable_hibernate(&adapter->hw); + device_set_wakeup_enable(&pdev->dev, 1); return 0; @@ -2720,9 +2728,48 @@ err_free_netdev: return ret; } +/* The AR803X PHY on the MinnowBoard requires a physical pin to be toggled to + * ensure it is awake for probe and init. Request the line and reset the PHY. + */ +static int pch_gbe_minnow_platform_init(struct pci_dev *pdev) +{ + unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT; + unsigned gpio = MINNOW_PHY_RESET_GPIO; + int ret; + + ret = devm_gpio_request_one(&pdev->dev, gpio, flags, + "minnow_phy_reset"); + if (ret) { + dev_err(&pdev->dev, + "ERR: Can't request PHY reset GPIO line '%d'\n", gpio); + return ret; + } + + gpio_set_value(gpio, 0); + usleep_range(1250, 1500); + gpio_set_value(gpio, 1); + usleep_range(1250, 1500); + + return ret; +} + +static struct pch_gbe_privdata pch_gbe_minnow_privdata = { + .phy_tx_clk_delay = true, + .phy_disable_hibernate = true, + .platform_init = pch_gbe_minnow_platform_init, +}; + static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { {.vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, + .subvendor = PCI_VENDOR_ID_CIRCUITCO, + .subdevice = PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD, + .class = (PCI_CLASS_NETWORK_ETHERNET << 8), + .class_mask = (0xFFFF00), + .driver_data = (kernel_ulong_t)&pch_gbe_minnow_privdata + }, + {.vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .class = (PCI_CLASS_NETWORK_ETHERNET << 8), |