summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
diff options
context:
space:
mode:
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.c67
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 ab1039a95bf9..5a0f04c2c813 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),