Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 1 | Driver name: Qualcomm FSM9xxx Ethernet Driver |
| 2 | |
| 3 | Supported hardware: FSM9xxx Ethernet Controller |
| 4 | |
| 5 | Maintainer(s): |
| 6 | Author(s): |
| 7 | |
| 8 | |
| 9 | Introduction: |
| 10 | ============= |
| 11 | |
| 12 | The FSM9xxx Ethernet controller is register based with separate TX and RX DMA |
| 13 | engines supporting scatter/gather and support 1EEE-1588 timestamping. |
| 14 | MII, RevMII and RgMII interfaces are support. RgMII support 1G. |
| 15 | |
| 16 | The driver supports gather but not scatter, uses the controller DMA engines, |
| 17 | and timestamping. |
| 18 | |
| 19 | |
| 20 | Hardware description: |
| 21 | ===================== |
| 22 | |
| 23 | The Ethernet Controller is a memory mapped register device with two |
| 24 | internal DMA engines for TX and RX path processing using separate |
| 25 | buffer-descriptors (BD) allocated from non-cached main memory for the TX |
| 26 | and RX paths. These BDs support scatter-gather but are only used to |
| 27 | transfer single max sized Ethernet frames. The BDs are sequentially |
| 28 | accessed as a ring, with an end-of-ring bit set in the last BD. Ownership |
| 29 | bits control access by hardware and software to individual BDs. |
| 30 | |
| 31 | An additional 4 words of space can be configured and is allocated between |
| 32 | each BD to store additional information about the sk_buff associated with it. |
| 33 | The driver software uses 2 ring structures and local functions to manage |
| 34 | them to keep in sync with the hardware the BDs . The number of BDs is |
| 35 | determined from the space allocated for them (PAGE_SIZE). The ratio of RX |
| 36 | to TX BD is set by a #define. |
| 37 | |
| 38 | Interrupts are used to service and replenish pre-allocated sk_buff for each |
| 39 | RX BD. TX frames are allocated to a TX BD and transmitted frames are |
| 40 | freed within the xmit() invoked to send the frame. No TX interrupts are |
| 41 | processed since sk_buffs are freed in the xmit(). |
| 42 | |
| 43 | Three PHY interfaces are supported: MII, RevMII and RgMII. The selected |
| 44 | interface is determined from the resource structure (to be completed) and |
| 45 | programmed into a register prior to resetting the Ethernet controller. |
| 46 | |
| 47 | Separate PLLs are managed to provide MAC/PHY clocks in RevMii and RgMii |
| 48 | modes, and a 25mHz clock timestamping. |
| 49 | |
| 50 | |
| 51 | |
| 52 | Software description |
| 53 | ==================== |
| 54 | |
| 55 | Structures |
| 56 | |
| 57 | struct qfec_buf_desc { |
| 58 | uint32_t status; |
| 59 | uint32_t ctl; |
| 60 | void *p_buf; |
| 61 | void *next; |
| 62 | }; |
| 63 | |
| 64 | struct buf_desc { |
| 65 | struct qfec_buf_desc desc; /* must be first */ |
| 66 | |
| 67 | struct sk_buff *skb; |
| 68 | void *buf_virt_addr; |
| 69 | void *buf_phys_addr; |
| 70 | uint32_t last_bd_flag; |
| 71 | }; |
| 72 | |
| 73 | struct ring { |
| 74 | int head; |
| 75 | int tail; |
| 76 | int n_free; |
| 77 | int len; |
| 78 | }; |
| 79 | |
| 80 | struct qfec_priv { |
| 81 | struct net_device *net_dev; |
| 82 | struct net_device_stats stats; /* req statistics */ |
| 83 | |
| 84 | struct device dev; |
| 85 | |
| 86 | spinlock_t hw_lock; |
| 87 | |
| 88 | unsigned int state; /* driver state */ |
| 89 | |
| 90 | void *bd_base; /* addr buf-desc */ |
| 91 | dma_addr_t tbd_dma; /* dma/phy-addr buf-desc */ |
| 92 | dma_addr_t rbd_dma; /* dma/phy-addr buf-desc */ |
| 93 | |
| 94 | struct resource *mac_res; |
| 95 | void *mac_base; /* mac (virt) base address */ |
| 96 | |
| 97 | struct resource *clk_res; |
| 98 | void *clk_base; /* clk (virt) base address */ |
| 99 | |
| 100 | unsigned int n_tbd; /* # of TX buf-desc */ |
| 101 | struct ring ring_tbd; /* TX ring */ |
| 102 | struct buf_desc *p_tbd; /* # TX buf-desc */ |
| 103 | |
| 104 | unsigned int n_rbd; /* # of RX buf-desc */ |
| 105 | struct ring ring_rbd; /* RX ring */ |
| 106 | struct buf_desc *p_rbd; /* # RX buf-desc */ |
| 107 | |
| 108 | unsigned long cntr[cntr_last]; /* activity counters */ |
| 109 | |
| 110 | struct mii_if_info mii; |
| 111 | |
| 112 | int mdio_clk; /* phy mdio clock rate */ |
| 113 | int phy_id; /* default PHY addr (0) */ |
| 114 | struct timer_list phy_tmr; /* monitor PHY state */ |
| 115 | }; |
| 116 | |
| 117 | |
| 118 | |
| 119 | Initialization is divided between probe() and open() such that the |
| 120 | net_device is allocated, the address space is mapped for register access, |
| 121 | and procfs files created in probe(). BD memory is allocated and |
| 122 | initialized along with interrupts and timers in open(). BD is not |
| 123 | de-allocated in close() allowing it to be debugged after the interface is |
| 124 | ifconfig down'd. This approach is intended to aid with debugging by |
| 125 | allowing configuring the interface down and up may clear some early usage |
| 126 | problems |
| 127 | |
| 128 | Phy link state changes are monitored using a timer using some existing |
| 129 | functions from the mii library, but also with local functions intended to |
| 130 | support RGMII in the future. |
| 131 | |
| 132 | A variety of information is accessible through procFs. Counters are used |
| 133 | to track various driver events, these include abnormal and error |
| 134 | interrupts. Hardware counters of various frame statistics (e.g. types and |
| 135 | sizes of TX and RX frames) are available. Hardware registers and up to the |
| 136 | 50 TX and RX BDs can be can be displayed. A table of procfs filenames and |
| 137 | functions are used to create and delete the procfs entries as needed. |
| 138 | |
| 139 | Probe() |
| 140 | |
| 141 | Allocate and initialize the net_device structure with resource information |
| 142 | specifying the Ethernet controller, clock control and MAC address memory |
| 143 | regions. Set netdev_ops to a statically defined sub-structure supporting |
| 144 | the device. |
| 145 | |
| 146 | Open() |
| 147 | |
| 148 | Use qfec_mem_alloc() to allocate space for the buffer-descriptors (BD). |
| 149 | TX BDs are initialized by clearing the ownership bit of each. Each RX BD |
| 150 | is initialized using qfec_rbd_init(). Qfec_rbd_init() pre-allocates an |
| 151 | sk_buff, saving the addresses of both the sk_buff and its data buffer in the |
| 152 | additional BD space, setting the BD buf pointer to the physical address of |
| 153 | the sk_buff data, and finally setting the ownership bit. |
| 154 | |
| 155 | Once the BDs are initialized, interface selected register is set to the |
| 156 | appropriate PHY interface configuration, and the Ethernet controller is |
| 157 | reset and its registers initialized, including the starting addresses of |
| 158 | the TX and RX BDs. |
| 159 | |
| 160 | The PHY monitor state is initialized and the timer initialized and started. |
| 161 | |
| 162 | Finally, the interrupt for the Ethernet controller is initialized. |
| 163 | |
| 164 | Note - Interrupts from both from the external PHY and internal RevMii |
| 165 | PHY, are available, but neither is used in preference to the |
| 166 | timer. |
| 167 | |
| 168 | |
| 169 | Interrupt Processing |
| 170 | |
| 171 | Besides recognizing abnormal error interrupts, RX, TX and GMAC interrupts |
| 172 | are recognized, although TX and GMAC interrupts are ignored but cleared and |
| 173 | counted. (The gmac interrupt can be ignored but must be disabled). |
| 174 | |
| 175 | RX interrupts invoke a handler to process the received frame, send it |
| 176 | to the stack and re-allocate a replacement sk_bufff for the buffer- |
| 177 | descriptor. |
| 178 | |
| 179 | |
| 180 | Receive Processing |
| 181 | |
| 182 | The RX buffer descriptors are initialized by _open() using qfec_rbd_init() |
| 183 | which pre-allocated an sk_buff, saving its address and the physical address |
| 184 | of its data in the additional BD space, as well as writing the physical |
| 185 | address to the BD pbuf entry read by HW. The size of the buffer and |
| 186 | other control information are written to the BD, as well as setting the |
| 187 | ownership bit. |
| 188 | |
| 189 | A received frame generates an interrupt invoking qfec_rx_int(). It |
| 190 | repeatedly checks the ownership the next available BD, and passing the |
| 191 | sk_buff containing the received frame to the stack via netif_rx(). |
| 192 | |
| 193 | Once all received frames are processed, it repeatedly calls qfec_rbd_init() |
| 194 | to allocate a new sk_buff with each available BD. |
| 195 | |
| 196 | |
| 197 | Transmit Processing |
| 198 | |
| 199 | Frames are transmitted through the start_xmit callback function. |
| 200 | qfec_tx_replenish() is immediately called to free sk_buffs from BD |
| 201 | that have been transmitted, before checking is a BD is available. |
| 202 | The sk_buff address is stored in the additional BD space and the |
| 203 | physical address of its data is store in the pbuf BD entry used |
| 204 | by the HW. The TX poll-demand register is accessed, causing the |
| 205 | HW to recheck the current BD and process it. |
| 206 | |
| 207 | While the TX interrupt could be processed to free sk_buffs as BD |
| 208 | are processed, they are ignored since the sk_buffs will be freed |
| 209 | with each call to _xmit(). |
| 210 | |
| 211 | procfs |
| 212 | |
| 213 | debug files are available to display the controller registers, |
| 214 | frame counters from the controller, driver activity counters, and |
| 215 | the first 50 entries of the RX and TX buffer descriptors. |
| 216 | |
| 217 | |
| 218 | Callbacks |
| 219 | |
| 220 | In addition to the functions described above, the following functions |
| 221 | are used to support their correspondingly named device operations: |
| 222 | |
| 223 | qfec_stop |
| 224 | qfec_do_ioctl |
| 225 | qfec_tx_timeout |
| 226 | qfec_set_mac_address |
| 227 | qfec_get_stats |
| 228 | qfec_set_config |
| 229 | |
| 230 | eth_change_mtu |
| 231 | eth_validate_addr |
| 232 | |
| 233 | |
| 234 | Power Management |
| 235 | ================ |
| 236 | None |
| 237 | |
| 238 | |
| 239 | Interface: |
| 240 | ========== |
| 241 | |
| 242 | - Module-init/exit |
| 243 | - standard network interface functions |
| 244 | |
| 245 | |
| 246 | Module parameters: |
| 247 | ================== |
| 248 | |
| 249 | static struct resource qfec_resources [] = { |
| 250 | [0] = { |
| 251 | .start = QFEC_MAC_BASE, |
| 252 | .end = QFEC_MAC_BASE + QFEC_MAC_SIZE, |
| 253 | .flags = IORESOURCE_MEM, |
| 254 | }, |
| 255 | [1] = { |
| 256 | .start = QFEC_MAC_IRQ, |
| 257 | .end = QFEC_MAC_IRQ, |
| 258 | .flags = IORESOURCE_IRQ, |
| 259 | }, |
| 260 | [2] = { |
| 261 | .start = QFEC_CLK_BASE, |
| 262 | .end = QFEC_CLK_BASE + QFEC_CLK_SIZE, |
| 263 | .flags = IORESOURCE_IO, |
| 264 | }, |
| 265 | [3] = { |
| 266 | .start = QFEC_MAC_FUSE_BASE, |
| 267 | .end = QFEC_MAC_FUSE_BASE + QFEC_MAC_FUSE_SIZE, |
| 268 | .flags = IORESOURCE_DMA, |
| 269 | }, |
| 270 | }; |
| 271 | |
| 272 | static struct platform_device qfec_device = { |
| 273 | .name = "qfec", |
| 274 | .id = 0, |
| 275 | .num_resources = ARRAY_SIZE(qfec_resources), |
| 276 | .resource = qfec_resources, |
| 277 | }; |
| 278 | |
| 279 | |
| 280 | Resource entries exist for three address regions and one interrupt. The |
| 281 | interrupt is identified as IORESOURCE_IRQ, the controller registers as |
| 282 | OPRESOURCE_MEM, the clock control registers as IORESOURCE_IO, and the |
| 283 | MAC address fuses as IORESOURCE_DMA. |
| 284 | |
| 285 | |
| 286 | Dependencies: |
| 287 | ============= |
| 288 | None |
| 289 | |
| 290 | |
| 291 | User space utilities: |
| 292 | ===================== |
| 293 | |
| 294 | See procfs descriptions |
| 295 | |
| 296 | |
| 297 | Known issues: |
| 298 | ============= |
| 299 | |
| 300 | - replace procfs w/ debugfs |
| 301 | |
| 302 | |
| 303 | To do: |
| 304 | ====== |
| 305 | |
| 306 | - specify interface (MII/RevMII/RgMii) in resource structure |
| 307 | - RevMii support untested |
| 308 | - RgMii (10/100/1000) |
| 309 | - generic timestamp support |