Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'minnow/net-next' of git://git.infradead.org/users/dvhart/linux-2.6 into minnow

Darren Hart says:

====================
Add support for the MinnowBoard in the pch_gbe driver. This was
originally sent to LKML as part of the MinnowBoard support series. That
is now partially merged and this version of the patch has been isolated
from those changes and is now completely self-contained.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+164 -1
+15
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
··· 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 + */ 591 + struct 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 598 * struct pch_gbe_adapter - board specific private data structure 586 599 * @stats_lock: Spinlock structure for status 587 600 * @ethtool_lock: Spinlock structure for ethtool ··· 617 604 * @rx_buffer_len: Receive buffer length 618 605 * @tx_queue_len: Transmit queue length 619 606 * @have_msi: PCI MSI mode flag 607 + * @pch_gbe_privdata: PCI Device ID driver_data 620 608 */ 621 609 622 610 struct pch_gbe_adapter { ··· 645 631 int hwts_tx_en; 646 632 int hwts_rx_en; 647 633 struct pci_dev *ptp_pdev; 634 + struct pch_gbe_privdata *pdata; 648 635 }; 649 636 650 637 #define pch_gbe_hw_to_adapter(hw) container_of(hw, struct pch_gbe_adapter, hw)
+50 -1
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
··· 23 23 #include <linux/module.h> 24 24 #include <linux/net_tstamp.h> 25 25 #include <linux/ptp_classify.h> 26 + #include <linux/gpio.h> 26 27 27 28 #define DRV_VERSION "1.01" 28 29 const char pch_driver_version[] = DRV_VERSION; ··· 111 110 112 111 #define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81" 113 112 #define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00" 113 + 114 + #define MINNOW_PHY_RESET_GPIO 13 114 115 115 116 static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT; 116 117 ··· 685 682 } 686 683 adapter->hw.phy.addr = adapter->mii.phy_id; 687 684 netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id); 688 - if (addr == 32) 685 + if (addr == PCH_GBE_PHY_REGS_LEN) 689 686 return -EAGAIN; 690 687 /* Selected the phy and isolate the rest */ 691 688 for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) { ··· 2638 2635 adapter->pdev = pdev; 2639 2636 adapter->hw.back = adapter; 2640 2637 adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR]; 2638 + adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data; 2639 + if (adapter->pdata && adapter->pdata->platform_init) 2640 + adapter->pdata->platform_init(pdev); 2641 2641 2642 2642 adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, 2643 2643 PCI_DEVFN(12, 4)); ··· 2716 2710 2717 2711 dev_dbg(&pdev->dev, "PCH Network Connection\n"); 2718 2712 2713 + /* Disable hibernation on certain platforms */ 2714 + if (adapter->pdata && adapter->pdata->phy_disable_hibernate) 2715 + pch_gbe_phy_disable_hibernate(&adapter->hw); 2716 + 2719 2717 device_set_wakeup_enable(&pdev->dev, 1); 2720 2718 return 0; 2721 2719 ··· 2730 2720 return ret; 2731 2721 } 2732 2722 2723 + /* The AR803X PHY on the MinnowBoard requires a physical pin to be toggled to 2724 + * ensure it is awake for probe and init. Request the line and reset the PHY. 2725 + */ 2726 + static int pch_gbe_minnow_platform_init(struct pci_dev *pdev) 2727 + { 2728 + unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT; 2729 + unsigned gpio = MINNOW_PHY_RESET_GPIO; 2730 + int ret; 2731 + 2732 + ret = devm_gpio_request_one(&pdev->dev, gpio, flags, 2733 + "minnow_phy_reset"); 2734 + if (ret) { 2735 + dev_err(&pdev->dev, 2736 + "ERR: Can't request PHY reset GPIO line '%d'\n", gpio); 2737 + return ret; 2738 + } 2739 + 2740 + gpio_set_value(gpio, 0); 2741 + usleep_range(1250, 1500); 2742 + gpio_set_value(gpio, 1); 2743 + usleep_range(1250, 1500); 2744 + 2745 + return ret; 2746 + } 2747 + 2748 + static struct pch_gbe_privdata pch_gbe_minnow_privdata = { 2749 + .phy_tx_clk_delay = true, 2750 + .phy_disable_hibernate = true, 2751 + .platform_init = pch_gbe_minnow_platform_init, 2752 + }; 2753 + 2733 2754 static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { 2755 + {.vendor = PCI_VENDOR_ID_INTEL, 2756 + .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, 2757 + .subvendor = PCI_VENDOR_ID_CIRCUITCO, 2758 + .subdevice = PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD, 2759 + .class = (PCI_CLASS_NETWORK_ETHERNET << 8), 2760 + .class_mask = (0xFFFF00), 2761 + .driver_data = (kernel_ulong_t)&pch_gbe_minnow_privdata 2762 + }, 2734 2763 {.vendor = PCI_VENDOR_ID_INTEL, 2735 2764 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, 2736 2765 .subvendor = PCI_ANY_ID,
+98
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
··· 74 74 #define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ 75 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 86 /* Phy Id Register (word 2) */ 78 87 #define PHY_REVISION_MASK 0x000F 79 88 ··· 258 249 } 259 250 260 251 /** 252 + * pch_gbe_phy_tx_clk_delay - Setup TX clock delay via the PHY 253 + * @hw: Pointer to the HW structure 254 + * Returns 255 + * 0: Successful. 256 + * -EINVAL: Invalid argument. 257 + */ 258 + static int pch_gbe_phy_tx_clk_delay(struct pch_gbe_hw *hw) 259 + { 260 + /* The RGMII interface requires a ~2ns TX clock delay. This is typically 261 + * done in layout with a longer trace or via PHY strapping, but can also 262 + * be done via PHY configuration registers. 263 + */ 264 + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); 265 + u16 mii_reg; 266 + int ret = 0; 267 + 268 + switch (hw->phy.id) { 269 + case PHY_AR803X_ID: 270 + netdev_dbg(adapter->netdev, 271 + "Configuring AR803X PHY for 2ns TX clock delay\n"); 272 + pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_OFF, &mii_reg); 273 + ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF, 274 + PHY_AR8031_SERDES); 275 + if (ret) 276 + break; 277 + 278 + pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg); 279 + mii_reg |= PHY_AR8031_SERDES_TX_CLK_DLY; 280 + ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT, 281 + mii_reg); 282 + break; 283 + default: 284 + netdev_err(adapter->netdev, 285 + "Unknown PHY (%x), could not set TX clock delay\n", 286 + hw->phy.id); 287 + return -EINVAL; 288 + } 289 + 290 + if (ret) 291 + netdev_err(adapter->netdev, 292 + "Could not configure tx clock delay for PHY\n"); 293 + return ret; 294 + } 295 + 296 + /** 261 297 * pch_gbe_phy_init_setting - PHY initial setting 262 298 * @hw: Pointer to the HW structure 263 299 */ ··· 331 277 pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg); 332 278 mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX; 333 279 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg); 280 + 281 + /* Setup a TX clock delay on certain platforms */ 282 + if (adapter->pdata && adapter->pdata->phy_tx_clk_delay) 283 + pch_gbe_phy_tx_clk_delay(hw); 284 + } 285 + 286 + /** 287 + * pch_gbe_phy_disable_hibernate - Disable the PHY low power state 288 + * @hw: Pointer to the HW structure 289 + * Returns 290 + * 0: Successful. 291 + * -EINVAL: Invalid argument. 292 + */ 293 + int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw) 294 + { 295 + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); 296 + u16 mii_reg; 297 + int ret = 0; 298 + 299 + switch (hw->phy.id) { 300 + case PHY_AR803X_ID: 301 + netdev_dbg(adapter->netdev, 302 + "Disabling hibernation for AR803X PHY\n"); 303 + ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF, 304 + PHY_AR8031_HIBERNATE); 305 + if (ret) 306 + break; 307 + 308 + pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg); 309 + mii_reg &= ~PHY_AR8031_PS_HIB_EN; 310 + ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT, 311 + mii_reg); 312 + break; 313 + default: 314 + netdev_err(adapter->netdev, 315 + "Unknown PHY (%x), could not disable hibernation\n", 316 + hw->phy.id); 317 + return -EINVAL; 318 + } 319 + 320 + if (ret) 321 + netdev_err(adapter->netdev, 322 + "Could not disable PHY hibernation\n"); 323 + return ret; 334 324 }
+1
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
··· 33 33 void pch_gbe_phy_power_down(struct pch_gbe_hw *hw); 34 34 void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw); 35 35 void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw); 36 + int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw); 36 37 37 38 #endif /* _PCH_GBE_PHY_H_ */