aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h15
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c51
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c98
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h1
4 files changed, 164 insertions, 1 deletions
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index 7779036690cc..6797b1075874 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -582,6 +582,19 @@ struct pch_gbe_hw_stats {
582}; 582};
583 583
584/** 584/**
585 * struct pch_gbe_privdata - PCI Device ID driver data
586 * @phy_tx_clk_delay: Bool, configure the PHY TX delay in software
587 * @phy_disable_hibernate: Bool, disable PHY hibernation
588 * @platform_init: Platform initialization callback, called from
589 * probe, prior to PHY initialization.
590 */
591struct pch_gbe_privdata {
592 bool phy_tx_clk_delay;
593 bool phy_disable_hibernate;
594 int (*platform_init)(struct pci_dev *pdev);
595};
596
597/**
585 * struct pch_gbe_adapter - board specific private data structure 598 * struct pch_gbe_adapter - board specific private data structure
586 * @stats_lock: Spinlock structure for status 599 * @stats_lock: Spinlock structure for status
587 * @ethtool_lock: Spinlock structure for ethtool 600 * @ethtool_lock: Spinlock structure for ethtool
@@ -604,6 +617,7 @@ struct pch_gbe_hw_stats {
604 * @rx_buffer_len: Receive buffer length 617 * @rx_buffer_len: Receive buffer length
605 * @tx_queue_len: Transmit queue length 618 * @tx_queue_len: Transmit queue length
606 * @have_msi: PCI MSI mode flag 619 * @have_msi: PCI MSI mode flag
620 * @pch_gbe_privdata: PCI Device ID driver_data
607 */ 621 */
608 622
609struct pch_gbe_adapter { 623struct pch_gbe_adapter {
@@ -631,6 +645,7 @@ struct pch_gbe_adapter {
631 int hwts_tx_en; 645 int hwts_tx_en;
632 int hwts_rx_en; 646 int hwts_rx_en;
633 struct pci_dev *ptp_pdev; 647 struct pci_dev *ptp_pdev;
648 struct pch_gbe_privdata *pdata;
634}; 649};
635 650
636#define pch_gbe_hw_to_adapter(hw) container_of(hw, struct pch_gbe_adapter, hw) 651#define pch_gbe_hw_to_adapter(hw) container_of(hw, struct pch_gbe_adapter, hw)
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..e19f1be60d5e 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 @@
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/net_tstamp.h> 24#include <linux/net_tstamp.h>
25#include <linux/ptp_classify.h> 25#include <linux/ptp_classify.h>
26#include <linux/gpio.h>
26 27
27#define DRV_VERSION "1.01" 28#define DRV_VERSION "1.01"
28const char pch_driver_version[] = DRV_VERSION; 29const char pch_driver_version[] = DRV_VERSION;
@@ -111,6 +112,8 @@ const char pch_driver_version[] = DRV_VERSION;
111#define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81" 112#define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81"
112#define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00" 113#define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00"
113 114
115#define MINNOW_PHY_RESET_GPIO 13
116
114static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT; 117static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
115 118
116static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg); 119static 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)
682 } 685 }
683 adapter->hw.phy.addr = adapter->mii.phy_id; 686 adapter->hw.phy.addr = adapter->mii.phy_id;
684 netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id); 687 netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id);
685 if (addr == 32) 688 if (addr == PCH_GBE_PHY_REGS_LEN)
686 return -EAGAIN; 689 return -EAGAIN;
687 /* Selected the phy and isolate the rest */ 690 /* Selected the phy and isolate the rest */
688 for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) { 691 for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
@@ -2635,6 +2638,9 @@ static int pch_gbe_probe(struct pci_dev *pdev,
2635 adapter->pdev = pdev; 2638 adapter->pdev = pdev;
2636 adapter->hw.back = adapter; 2639 adapter->hw.back = adapter;
2637 adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR]; 2640 adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR];
2641 adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data;
2642 if (adapter->pdata && adapter->pdata->platform_init)
2643 adapter->pdata->platform_init(pdev);
2638 2644
2639 adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, 2645 adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number,
2640 PCI_DEVFN(12, 4)); 2646 PCI_DEVFN(12, 4));
@@ -2710,6 +2716,10 @@ static int pch_gbe_probe(struct pci_dev *pdev,
2710 2716
2711 dev_dbg(&pdev->dev, "PCH Network Connection\n"); 2717 dev_dbg(&pdev->dev, "PCH Network Connection\n");
2712 2718
2719 /* Disable hibernation on certain platforms */
2720 if (adapter->pdata && adapter->pdata->phy_disable_hibernate)
2721 pch_gbe_phy_disable_hibernate(&adapter->hw);
2722
2713 device_set_wakeup_enable(&pdev->dev, 1); 2723 device_set_wakeup_enable(&pdev->dev, 1);
2714 return 0; 2724 return 0;
2715 2725
@@ -2720,9 +2730,48 @@ err_free_netdev:
2720 return ret; 2730 return ret;
2721} 2731}
2722 2732
2733/* The AR803X PHY on the MinnowBoard requires a physical pin to be toggled to
2734 * ensure it is awake for probe and init. Request the line and reset the PHY.
2735 */
2736static int pch_gbe_minnow_platform_init(struct pci_dev *pdev)
2737{
2738 unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT;
2739 unsigned gpio = MINNOW_PHY_RESET_GPIO;
2740 int ret;
2741
2742 ret = devm_gpio_request_one(&pdev->dev, gpio, flags,
2743 "minnow_phy_reset");
2744 if (ret) {
2745 dev_err(&pdev->dev,
2746 "ERR: Can't request PHY reset GPIO line '%d'\n", gpio);
2747 return ret;
2748 }
2749
2750 gpio_set_value(gpio, 0);
2751 usleep_range(1250, 1500);
2752 gpio_set_value(gpio, 1);
2753 usleep_range(1250, 1500);
2754
2755 return ret;
2756}
2757
2758static struct pch_gbe_privdata pch_gbe_minnow_privdata = {
2759 .phy_tx_clk_delay = true,
2760 .phy_disable_hibernate = true,
2761 .platform_init = pch_gbe_minnow_platform_init,
2762};
2763
2723static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { 2764static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
2724 {.vendor = PCI_VENDOR_ID_INTEL, 2765 {.vendor = PCI_VENDOR_ID_INTEL,
2725 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, 2766 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
2767 .subvendor = PCI_VENDOR_ID_CIRCUITCO,
2768 .subdevice = PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD,
2769 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
2770 .class_mask = (0xFFFF00),
2771 .driver_data = (kernel_ulong_t)&pch_gbe_minnow_privdata
2772 },
2773 {.vendor = PCI_VENDOR_ID_INTEL,
2774 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
2726 .subvendor = PCI_ANY_ID, 2775 .subvendor = PCI_ANY_ID,
2727 .subdevice = PCI_ANY_ID, 2776 .subdevice = PCI_ANY_ID,
2728 .class = (PCI_CLASS_NETWORK_ETHERNET << 8), 2777 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
index da079073a6c6..8b7ff75fc8e0 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
@@ -74,6 +74,15 @@
74#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ 74#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
75#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ 75#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
76 76
77/* AR8031 PHY Debug Registers */
78#define PHY_AR803X_ID 0x00001374
79#define PHY_AR8031_DBG_OFF 0x1D
80#define PHY_AR8031_DBG_DAT 0x1E
81#define PHY_AR8031_SERDES 0x05
82#define PHY_AR8031_HIBERNATE 0x0B
83#define PHY_AR8031_SERDES_TX_CLK_DLY 0x0100 /* TX clock delay of 2.0ns */
84#define PHY_AR8031_PS_HIB_EN 0x8000 /* Hibernate enable */
85
77/* Phy Id Register (word 2) */ 86/* Phy Id Register (word 2) */
78#define PHY_REVISION_MASK 0x000F 87#define PHY_REVISION_MASK 0x000F
79 88
@@ -249,6 +258,51 @@ void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
249} 258}
250 259
251/** 260/**
261 * pch_gbe_phy_tx_clk_delay - Setup TX clock delay via the PHY
262 * @hw: Pointer to the HW structure
263 * Returns
264 * 0: Successful.
265 * -EINVAL: Invalid argument.
266 */
267static int pch_gbe_phy_tx_clk_delay(struct pch_gbe_hw *hw)
268{
269 /* The RGMII interface requires a ~2ns TX clock delay. This is typically
270 * done in layout with a longer trace or via PHY strapping, but can also
271 * be done via PHY configuration registers.
272 */
273 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
274 u16 mii_reg;
275 int ret = 0;
276
277 switch (hw->phy.id) {
278 case PHY_AR803X_ID:
279 netdev_dbg(adapter->netdev,
280 "Configuring AR803X PHY for 2ns TX clock delay\n");
281 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_OFF, &mii_reg);
282 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
283 PHY_AR8031_SERDES);
284 if (ret)
285 break;
286
287 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
288 mii_reg |= PHY_AR8031_SERDES_TX_CLK_DLY;
289 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
290 mii_reg);
291 break;
292 default:
293 netdev_err(adapter->netdev,
294 "Unknown PHY (%x), could not set TX clock delay\n",
295 hw->phy.id);
296 return -EINVAL;
297 }
298
299 if (ret)
300 netdev_err(adapter->netdev,
301 "Could not configure tx clock delay for PHY\n");
302 return ret;
303}
304
305/**
252 * pch_gbe_phy_init_setting - PHY initial setting 306 * pch_gbe_phy_init_setting - PHY initial setting
253 * @hw: Pointer to the HW structure 307 * @hw: Pointer to the HW structure
254 */ 308 */
@@ -277,4 +331,48 @@ void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
277 pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg); 331 pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
278 mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX; 332 mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
279 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg); 333 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
334
335 /* Setup a TX clock delay on certain platforms */
336 if (adapter->pdata && adapter->pdata->phy_tx_clk_delay)
337 pch_gbe_phy_tx_clk_delay(hw);
338}
339
340/**
341 * pch_gbe_phy_disable_hibernate - Disable the PHY low power state
342 * @hw: Pointer to the HW structure
343 * Returns
344 * 0: Successful.
345 * -EINVAL: Invalid argument.
346 */
347int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw)
348{
349 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
350 u16 mii_reg;
351 int ret = 0;
352
353 switch (hw->phy.id) {
354 case PHY_AR803X_ID:
355 netdev_dbg(adapter->netdev,
356 "Disabling hibernation for AR803X PHY\n");
357 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
358 PHY_AR8031_HIBERNATE);
359 if (ret)
360 break;
361
362 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
363 mii_reg &= ~PHY_AR8031_PS_HIB_EN;
364 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
365 mii_reg);
366 break;
367 default:
368 netdev_err(adapter->netdev,
369 "Unknown PHY (%x), could not disable hibernation\n",
370 hw->phy.id);
371 return -EINVAL;
372 }
373
374 if (ret)
375 netdev_err(adapter->netdev,
376 "Could not disable PHY hibernation\n");
377 return ret;
280} 378}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
index 03264dc7b5ec..0cbe69206e04 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
@@ -33,5 +33,6 @@ void pch_gbe_phy_power_up(struct pch_gbe_hw *hw);
33void pch_gbe_phy_power_down(struct pch_gbe_hw *hw); 33void pch_gbe_phy_power_down(struct pch_gbe_hw *hw);
34void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw); 34void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw);
35void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw); 35void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw);
36int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw);
36 37
37#endif /* _PCH_GBE_PHY_H_ */ 38#endif /* _PCH_GBE_PHY_H_ */