123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- Driver name: Qualcomm FSM9xxx Ethernet Driver
- Supported hardware: FSM9xxx Ethernet Controller
- Maintainer(s):
- Author(s):
- Introduction:
- =============
- The FSM9xxx Ethernet controller is register based with separate TX and RX DMA
- engines supporting scatter/gather and support 1EEE-1588 timestamping.
- MII, RevMII and RgMII interfaces are support. RgMII support 1G.
- The driver supports gather but not scatter, uses the controller DMA engines,
- and timestamping.
- Hardware description:
- =====================
- The Ethernet Controller is a memory mapped register device with two
- internal DMA engines for TX and RX path processing using separate
- buffer-descriptors (BD) allocated from non-cached main memory for the TX
- and RX paths. These BDs support scatter-gather but are only used to
- transfer single max sized Ethernet frames. The BDs are sequentially
- accessed as a ring, with an end-of-ring bit set in the last BD. Ownership
- bits control access by hardware and software to individual BDs.
- An additional 4 words of space can be configured and is allocated between
- each BD to store additional information about the sk_buff associated with it.
- The driver software uses 2 ring structures and local functions to manage
- them to keep in sync with the hardware the BDs . The number of BDs is
- determined from the space allocated for them (PAGE_SIZE). The ratio of RX
- to TX BD is set by a #define.
- Interrupts are used to service and replenish pre-allocated sk_buff for each
- RX BD. TX frames are allocated to a TX BD and transmitted frames are
- freed within the xmit() invoked to send the frame. No TX interrupts are
- processed since sk_buffs are freed in the xmit().
- Three PHY interfaces are supported: MII, RevMII and RgMII. The selected
- interface is determined from the resource structure (to be completed) and
- programmed into a register prior to resetting the Ethernet controller.
- Separate PLLs are managed to provide MAC/PHY clocks in RevMii and RgMii
- modes, and a 25mHz clock timestamping.
- Software description
- ====================
- Structures
- struct qfec_buf_desc {
- uint32_t status;
- uint32_t ctl;
- void *p_buf;
- void *next;
- };
- struct buf_desc {
- struct qfec_buf_desc desc; /* must be first */
- struct sk_buff *skb;
- void *buf_virt_addr;
- void *buf_phys_addr;
- uint32_t last_bd_flag;
- };
- struct ring {
- int head;
- int tail;
- int n_free;
- int len;
- };
- struct qfec_priv {
- struct net_device *net_dev;
- struct net_device_stats stats; /* req statistics */
- struct device dev;
- spinlock_t hw_lock;
- unsigned int state; /* driver state */
- void *bd_base; /* addr buf-desc */
- dma_addr_t tbd_dma; /* dma/phy-addr buf-desc */
- dma_addr_t rbd_dma; /* dma/phy-addr buf-desc */
- struct resource *mac_res;
- void *mac_base; /* mac (virt) base address */
- struct resource *clk_res;
- void *clk_base; /* clk (virt) base address */
- unsigned int n_tbd; /* # of TX buf-desc */
- struct ring ring_tbd; /* TX ring */
- struct buf_desc *p_tbd; /* # TX buf-desc */
- unsigned int n_rbd; /* # of RX buf-desc */
- struct ring ring_rbd; /* RX ring */
- struct buf_desc *p_rbd; /* # RX buf-desc */
- unsigned long cntr[cntr_last]; /* activity counters */
- struct mii_if_info mii;
- int mdio_clk; /* phy mdio clock rate */
- int phy_id; /* default PHY addr (0) */
- struct timer_list phy_tmr; /* monitor PHY state */
- };
- Initialization is divided between probe() and open() such that the
- net_device is allocated, the address space is mapped for register access,
- and procfs files created in probe(). BD memory is allocated and
- initialized along with interrupts and timers in open(). BD is not
- de-allocated in close() allowing it to be debugged after the interface is
- ifconfig down'd. This approach is intended to aid with debugging by
- allowing configuring the interface down and up may clear some early usage
- problems
- Phy link state changes are monitored using a timer using some existing
- functions from the mii library, but also with local functions intended to
- support RGMII in the future.
- A variety of information is accessible through procFs. Counters are used
- to track various driver events, these include abnormal and error
- interrupts. Hardware counters of various frame statistics (e.g. types and
- sizes of TX and RX frames) are available. Hardware registers and up to the
- 50 TX and RX BDs can be can be displayed. A table of procfs filenames and
- functions are used to create and delete the procfs entries as needed.
- Probe()
- Allocate and initialize the net_device structure with resource information
- specifying the Ethernet controller, clock control and MAC address memory
- regions. Set netdev_ops to a statically defined sub-structure supporting
- the device.
- Open()
- Use qfec_mem_alloc() to allocate space for the buffer-descriptors (BD).
- TX BDs are initialized by clearing the ownership bit of each. Each RX BD
- is initialized using qfec_rbd_init(). Qfec_rbd_init() pre-allocates an
- sk_buff, saving the addresses of both the sk_buff and its data buffer in the
- additional BD space, setting the BD buf pointer to the physical address of
- the sk_buff data, and finally setting the ownership bit.
- Once the BDs are initialized, interface selected register is set to the
- appropriate PHY interface configuration, and the Ethernet controller is
- reset and its registers initialized, including the starting addresses of
- the TX and RX BDs.
- The PHY monitor state is initialized and the timer initialized and started.
- Finally, the interrupt for the Ethernet controller is initialized.
- Note - Interrupts from both from the external PHY and internal RevMii
- PHY, are available, but neither is used in preference to the
- timer.
- Interrupt Processing
- Besides recognizing abnormal error interrupts, RX, TX and GMAC interrupts
- are recognized, although TX and GMAC interrupts are ignored but cleared and
- counted. (The gmac interrupt can be ignored but must be disabled).
- RX interrupts invoke a handler to process the received frame, send it
- to the stack and re-allocate a replacement sk_bufff for the buffer-
- descriptor.
- Receive Processing
- The RX buffer descriptors are initialized by _open() using qfec_rbd_init()
- which pre-allocated an sk_buff, saving its address and the physical address
- of its data in the additional BD space, as well as writing the physical
- address to the BD pbuf entry read by HW. The size of the buffer and
- other control information are written to the BD, as well as setting the
- ownership bit.
- A received frame generates an interrupt invoking qfec_rx_int(). It
- repeatedly checks the ownership the next available BD, and passing the
- sk_buff containing the received frame to the stack via netif_rx().
- Once all received frames are processed, it repeatedly calls qfec_rbd_init()
- to allocate a new sk_buff with each available BD.
- Transmit Processing
- Frames are transmitted through the start_xmit callback function.
- qfec_tx_replenish() is immediately called to free sk_buffs from BD
- that have been transmitted, before checking is a BD is available.
- The sk_buff address is stored in the additional BD space and the
- physical address of its data is store in the pbuf BD entry used
- by the HW. The TX poll-demand register is accessed, causing the
- HW to recheck the current BD and process it.
- While the TX interrupt could be processed to free sk_buffs as BD
- are processed, they are ignored since the sk_buffs will be freed
- with each call to _xmit().
- procfs
- debug files are available to display the controller registers,
- frame counters from the controller, driver activity counters, and
- the first 50 entries of the RX and TX buffer descriptors.
- Callbacks
- In addition to the functions described above, the following functions
- are used to support their correspondingly named device operations:
- qfec_stop
- qfec_do_ioctl
- qfec_tx_timeout
- qfec_set_mac_address
- qfec_get_stats
- qfec_set_config
- eth_change_mtu
- eth_validate_addr
- Power Management
- ================
- None
- Interface:
- ==========
- - Module-init/exit
- - standard network interface functions
- Module parameters:
- ==================
- static struct resource qfec_resources [] = {
- [0] = {
- .start = QFEC_MAC_BASE,
- .end = QFEC_MAC_BASE + QFEC_MAC_SIZE,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = QFEC_MAC_IRQ,
- .end = QFEC_MAC_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = QFEC_CLK_BASE,
- .end = QFEC_CLK_BASE + QFEC_CLK_SIZE,
- .flags = IORESOURCE_IO,
- },
- [3] = {
- .start = QFEC_MAC_FUSE_BASE,
- .end = QFEC_MAC_FUSE_BASE + QFEC_MAC_FUSE_SIZE,
- .flags = IORESOURCE_DMA,
- },
- };
- static struct platform_device qfec_device = {
- .name = "qfec",
- .id = 0,
- .num_resources = ARRAY_SIZE(qfec_resources),
- .resource = qfec_resources,
- };
- Resource entries exist for three address regions and one interrupt. The
- interrupt is identified as IORESOURCE_IRQ, the controller registers as
- OPRESOURCE_MEM, the clock control registers as IORESOURCE_IO, and the
- MAC address fuses as IORESOURCE_DMA.
- Dependencies:
- =============
- None
- User space utilities:
- =====================
- See procfs descriptions
- Known issues:
- =============
- - replace procfs w/ debugfs
- To do:
- ======
- - specify interface (MII/RevMII/RgMii) in resource structure
- - RevMii support untested
- - RgMii (10/100/1000)
- - generic timestamp support
|