// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 1999 - 2010 Intel Corporation. * Copyright (C) 2010 - 2012 LAPIS SEMICONDUCTOR CO., LTD. * * This code was derived from the Intel e1000e Linux driver. */ #include "pch_gbe.h" #include "pch_gbe_phy.h" #include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> #include <linux/iopoll.h> #include <linux/module.h> #include <linux/net_tstamp.h> #include <linux/ptp_classify.h> #include <linux/ptp_pch.h> #include <linux/gpio.h> #define PCH_GBE_MAR_ENTRIES … #define PCH_GBE_SHORT_PKT … #define DSC_INIT16 … #define PCH_GBE_DMA_ALIGN … #define PCH_GBE_DMA_PADDING … #define PCH_GBE_WATCHDOG_PERIOD … #define PCH_GBE_PCI_BAR … #define PCH_GBE_RESERVE_MEMORY … #define PCI_DEVICE_ID_INTEL_IOH1_GBE … #define PCI_DEVICE_ID_ROHM_ML7223_GBE … #define PCI_DEVICE_ID_ROHM_ML7831_GBE … #define PCH_GBE_RX_BUFFER_WRITE … /* Initialize the wake-on-LAN settings */ #define PCH_GBE_WL_INIT_SETTING … #define PCH_GBE_MAC_RGMII_CTRL_SETTING … /* Ethertype field values */ #define PCH_GBE_MAX_RX_BUFFER_SIZE … #define PCH_GBE_MAX_JUMBO_FRAME_SIZE … #define PCH_GBE_FRAME_SIZE_2048 … #define PCH_GBE_FRAME_SIZE_4096 … #define PCH_GBE_FRAME_SIZE_8192 … #define PCH_GBE_GET_DESC(R, i, type) … #define PCH_GBE_RX_DESC(R, i) … #define PCH_GBE_TX_DESC(R, i) … #define PCH_GBE_DESC_UNUSED(R) … /* Pause packet value */ #define PCH_GBE_PAUSE_PKT1_VALUE … #define PCH_GBE_PAUSE_PKT2_VALUE … #define PCH_GBE_PAUSE_PKT4_VALUE … #define PCH_GBE_PAUSE_PKT5_VALUE … /* This defines the bits that are set in the Interrupt Mask * Set/Read Register. Each bit is documented below: * o RXT0 = Receiver Timer Interrupt (ring 0) * o TXDW = Transmit Descriptor Written Back * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) * o RXSEQ = Receive Sequence Error * o LSC = Link Status Change */ #define PCH_GBE_INT_ENABLE_MASK … #define PCH_GBE_INT_DISABLE_ALL … /* Macros for ieee1588 */ /* 0x40 Time Synchronization Channel Control Register Bits */ #define MASTER_MODE … #define SLAVE_MODE … #define V2_MODE … #define CAP_MODE0 … #define CAP_MODE2 … /* 0x44 Time Synchronization Channel Event Register Bits */ #define TX_SNAPSHOT_LOCKED … #define RX_SNAPSHOT_LOCKED … #define PTP_L4_MULTICAST_SA … #define PTP_L2_MULTICAST_SA … static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg); static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg, int data); static void pch_gbe_set_multi(struct net_device *netdev); static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) { … } static void pch_rx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb) { … } static void pch_tx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb) { … } static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { … } static inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw) { … } /** * pch_gbe_mac_read_mac_addr - Read MAC address * @hw: Pointer to the HW structure * Returns: * 0: Successful. */ static s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw) { … } /** * pch_gbe_wait_clr_bit - Wait to clear a bit * @reg: Pointer of register * @bit: Busy bit */ static void pch_gbe_wait_clr_bit(void __iomem *reg, u32 bit) { … } /** * pch_gbe_mac_mar_set - Set MAC address register * @hw: Pointer to the HW structure * @addr: Pointer to the MAC address * @index: MAC address array register */ static void pch_gbe_mac_mar_set(struct pch_gbe_hw *hw, u8 * addr, u32 index) { … } /** * pch_gbe_mac_reset_hw - Reset hardware * @hw: Pointer to the HW structure */ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw) { … } static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw) { … } static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw) { … } /** * pch_gbe_mac_init_rx_addrs - Initialize receive address's * @hw: Pointer to the HW structure * @mar_count: Receive address registers */ static void pch_gbe_mac_init_rx_addrs(struct pch_gbe_hw *hw, u16 mar_count) { … } /** * pch_gbe_mac_force_mac_fc - Force the MAC's flow control settings * @hw: Pointer to the HW structure * Returns: * 0: Successful. * Negative value: Failed. */ s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw) { … } /** * pch_gbe_mac_set_wol_event - Set wake-on-lan event * @hw: Pointer to the HW structure * @wu_evt: Wake up event */ static void pch_gbe_mac_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt) { … } /** * pch_gbe_mac_ctrl_miim - Control MIIM interface * @hw: Pointer to the HW structure * @addr: Address of PHY * @dir: Operetion. (Write or Read) * @reg: Access register of PHY * @data: Write data. * * Returns: Read date. */ u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg, u16 data) { … } /** * pch_gbe_mac_set_pause_packet - Set pause packet * @hw: Pointer to the HW structure */ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw) { … } /** * pch_gbe_alloc_queues - Allocate memory for all rings * @adapter: Board private structure to initialize * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_init_stats - Initialize status * @adapter: Board private structure to initialize */ static void pch_gbe_init_stats(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_init_phy - Initialize PHY * @adapter: Board private structure to initialize * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_mdio_read - The read function for mii * @netdev: Network interface device structure * @addr: Phy ID * @reg: Access location * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg) { … } /** * pch_gbe_mdio_write - The write function for mii * @netdev: Network interface device structure * @addr: Phy ID (not used) * @reg: Access location * @data: Write data */ static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg, int data) { … } /** * pch_gbe_reset_task - Reset processing at the time of transmission timeout * @work: Pointer of board private structure */ static void pch_gbe_reset_task(struct work_struct *work) { … } /** * pch_gbe_reinit_locked- Re-initialization * @adapter: Board private structure */ void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_reset - Reset GbE * @adapter: Board private structure */ void pch_gbe_reset(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_free_irq - Free an interrupt * @adapter: Board private structure */ static void pch_gbe_free_irq(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_irq_disable - Mask off interrupt generation on the NIC * @adapter: Board private structure */ static void pch_gbe_irq_disable(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_irq_enable - Enable default interrupt generation settings * @adapter: Board private structure */ static void pch_gbe_irq_enable(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_setup_tctl - configure the Transmit control registers * @adapter: Board private structure */ static void pch_gbe_setup_tctl(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_configure_tx - Configure Transmit Unit after Reset * @adapter: Board private structure */ static void pch_gbe_configure_tx(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_setup_rctl - Configure the receive control registers * @adapter: Board private structure */ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_configure_rx - Configure Receive Unit after Reset * @adapter: Board private structure */ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_unmap_and_free_tx_resource - Unmap and free tx socket buffer * @adapter: Board private structure * @buffer_info: Buffer information structure */ static void pch_gbe_unmap_and_free_tx_resource( struct pch_gbe_adapter *adapter, struct pch_gbe_buffer *buffer_info) { … } /** * pch_gbe_unmap_and_free_rx_resource - Unmap and free rx socket buffer * @adapter: Board private structure * @buffer_info: Buffer information structure */ static void pch_gbe_unmap_and_free_rx_resource( struct pch_gbe_adapter *adapter, struct pch_gbe_buffer *buffer_info) { … } /** * pch_gbe_clean_tx_ring - Free Tx Buffers * @adapter: Board private structure * @tx_ring: Ring to be cleaned */ static void pch_gbe_clean_tx_ring(struct pch_gbe_adapter *adapter, struct pch_gbe_tx_ring *tx_ring) { … } /** * pch_gbe_clean_rx_ring - Free Rx Buffers * @adapter: Board private structure * @rx_ring: Ring to free buffers from */ static void pch_gbe_clean_rx_ring(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring) { … } static void pch_gbe_set_rgmii_ctrl(struct pch_gbe_adapter *adapter, u16 speed, u16 duplex) { … } static void pch_gbe_set_mode(struct pch_gbe_adapter *adapter, u16 speed, u16 duplex) { … } /** * pch_gbe_watchdog - Watchdog process * @t: timer list containing a Board private structure */ static void pch_gbe_watchdog(struct timer_list *t) { … } /** * pch_gbe_tx_queue - Carry out queuing of the transmission data * @adapter: Board private structure * @tx_ring: Tx descriptor ring structure * @skb: Sockt buffer structure */ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, struct pch_gbe_tx_ring *tx_ring, struct sk_buff *skb) { … } /** * pch_gbe_update_stats - Update the board statistics counters * @adapter: Board private structure */ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) { … } static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw) { … } static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw) { … } /** * pch_gbe_intr - Interrupt Handler * @irq: Interrupt number * @data: Pointer to a network interface device structure * Returns: * - IRQ_HANDLED: Our interrupt * - IRQ_NONE: Not our interrupt */ static irqreturn_t pch_gbe_intr(int irq, void *data) { … } /** * pch_gbe_alloc_rx_buffers - Replace used receive buffers; legacy & extended * @adapter: Board private structure * @rx_ring: Rx descriptor ring * @cleaned_count: Cleaned count */ static void pch_gbe_alloc_rx_buffers(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring, int cleaned_count) { … } static int pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring, int cleaned_count) { … } /** * pch_gbe_alloc_tx_buffers - Allocate transmit buffers * @adapter: Board private structure * @tx_ring: Tx descriptor ring */ static void pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter, struct pch_gbe_tx_ring *tx_ring) { … } /** * pch_gbe_clean_tx - Reclaim resources after transmit completes * @adapter: Board private structure * @tx_ring: Tx descriptor ring * Returns: * true: Cleaned the descriptor * false: Not cleaned the descriptor */ static bool pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, struct pch_gbe_tx_ring *tx_ring) { … } /** * pch_gbe_clean_rx - Send received data up the network stack; legacy * @adapter: Board private structure * @rx_ring: Rx descriptor ring * @work_done: Completed count * @work_to_do: Request count * Returns: * true: Cleaned the descriptor * false: Not cleaned the descriptor */ static bool pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring, int *work_done, int work_to_do) { … } /** * pch_gbe_setup_tx_resources - Allocate Tx resources (Descriptors) * @adapter: Board private structure * @tx_ring: Tx descriptor ring (for a specific queue) to setup * Returns: * 0: Successfully * Negative value: Failed */ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, struct pch_gbe_tx_ring *tx_ring) { … } /** * pch_gbe_setup_rx_resources - Allocate Rx resources (Descriptors) * @adapter: Board private structure * @rx_ring: Rx descriptor ring (for a specific queue) to setup * Returns: * 0: Successfully * Negative value: Failed */ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring) { … } /** * pch_gbe_free_tx_resources - Free Tx Resources * @adapter: Board private structure * @tx_ring: Tx descriptor ring for a specific queue */ void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter, struct pch_gbe_tx_ring *tx_ring) { … } /** * pch_gbe_free_rx_resources - Free Rx Resources * @adapter: Board private structure * @rx_ring: Ring to clean the resources from */ void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring) { … } /** * pch_gbe_request_irq - Allocate an interrupt line * @adapter: Board private structure * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_up - Up GbE network device * @adapter: Board private structure * Returns: * 0: Successfully * Negative value: Failed */ int pch_gbe_up(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_down - Down GbE network device * @adapter: Board private structure */ void pch_gbe_down(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_sw_init - Initialize general software structures (struct pch_gbe_adapter) * @adapter: Board private structure to initialize * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter) { … } /** * pch_gbe_open - Called when a network interface is made active * @netdev: Network interface device structure * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_open(struct net_device *netdev) { … } /** * pch_gbe_stop - Disables a network interface * @netdev: Network interface device structure * Returns: * 0: Successfully */ static int pch_gbe_stop(struct net_device *netdev) { … } /** * pch_gbe_xmit_frame - Packet transmitting start * @skb: Socket buffer structure * @netdev: Network interface device structure * Returns: * - NETDEV_TX_OK: Normal end * - NETDEV_TX_BUSY: Error end */ static netdev_tx_t pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { … } /** * pch_gbe_set_multi - Multicast and Promiscuous mode set * @netdev: Network interface device structure */ static void pch_gbe_set_multi(struct net_device *netdev) { … } /** * pch_gbe_set_mac - Change the Ethernet Address of the NIC * @netdev: Network interface device structure * @addr: Pointer to an address structure * Returns: * 0: Successfully * -EADDRNOTAVAIL: Failed */ static int pch_gbe_set_mac(struct net_device *netdev, void *addr) { … } /** * pch_gbe_change_mtu - Change the Maximum Transfer Unit * @netdev: Network interface device structure * @new_mtu: New value for maximum frame size * Returns: * 0: Successfully * -EINVAL: Failed */ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) { … } /** * pch_gbe_set_features - Reset device after features changed * @netdev: Network interface device structure * @features: New features * Returns: * 0: HW state updated successfully */ static int pch_gbe_set_features(struct net_device *netdev, netdev_features_t features) { … } /** * pch_gbe_ioctl - Controls register through a MII interface * @netdev: Network interface device structure * @ifr: Pointer to ifr structure * @cmd: Control command * Returns: * 0: Successfully * Negative value: Failed */ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { … } /** * pch_gbe_tx_timeout - Respond to a Tx Hang * @netdev: Network interface device structure * @txqueue: index of hanging queue */ static void pch_gbe_tx_timeout(struct net_device *netdev, unsigned int txqueue) { … } /** * pch_gbe_napi_poll - NAPI receive and transfer polling callback * @napi: Pointer of polling device struct * @budget: The maximum number of a packet * Returns: * false: Exit the polling mode * true: Continue the polling mode */ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) { … } #ifdef CONFIG_NET_POLL_CONTROLLER /** * pch_gbe_netpoll - Used by things like netconsole to send skbs * @netdev: Network interface device structure */ static void pch_gbe_netpoll(struct net_device *netdev) { … } #endif static const struct net_device_ops pch_gbe_netdev_ops = …; static pci_ers_result_t pch_gbe_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { … } static pci_ers_result_t pch_gbe_io_slot_reset(struct pci_dev *pdev) { … } static void pch_gbe_io_resume(struct pci_dev *pdev) { … } static int __pch_gbe_suspend(struct pci_dev *pdev) { … } #ifdef CONFIG_PM static int pch_gbe_suspend(struct device *device) { … } static int pch_gbe_resume(struct device *device) { … } #endif /* CONFIG_PM */ static void pch_gbe_shutdown(struct pci_dev *pdev) { … } static void pch_gbe_remove(struct pci_dev *pdev) { … } static int pch_gbe_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { … } static void pch_gbe_gpio_remove_table(void *table) { … } static int pch_gbe_gpio_add_table(struct device *dev, void *table) { … } static struct gpiod_lookup_table pch_gbe_minnow_gpio_table = …; /* 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) { … } static struct pch_gbe_privdata pch_gbe_minnow_privdata = …; static const struct pci_device_id pch_gbe_pcidev_id[] = …; #ifdef CONFIG_PM static const struct dev_pm_ops pch_gbe_pm_ops = …; #endif static const struct pci_error_handlers pch_gbe_err_handler = …; static struct pci_driver pch_gbe_driver = …; module_pci_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …; MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id); /* pch_gbe_main.c */