1 /*
2  * Copyright (c) 2016-2019 Arm Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /**
19  * \file smsc9220_drv.h
20  * \brief Generic driver for SMSC9220 Ethernet controller
21  */
22 
23 #ifndef __SMSC9220_ETH_H__
24     #define __SMSC9220_ETH_H__
25 
26     #include <stdbool.h>
27     #include <stdint.h>
28 
29     #ifdef __cplusplus
30         extern "C" {
31     #endif
32 
33 /** SMSC9220 device configuration structure */
34     struct smsc9220_eth_dev_cfg_t
35     {
36         const uint32_t base; /*!< SMSC9220 base address */
37     };
38 
39 /** SMSC9220 device data structure */
40     struct smsc9220_eth_dev_data_t
41     {
42         uint32_t state;                      /*!< Indicates if the SMSC9220 driver
43                                               *   is initialized and enabled */
44         void (* wait_ms) ( uint32_t );       /*!< function pointer to system's millisec delay
45                                               * function, will be used for delays */
46         uint32_t ongoing_packet_length;      /*!< size in bytes of the packet
47                                               *       is being sent */
48         uint32_t ongoing_packet_length_sent; /*!< size in bytes of the packet
49                                               *       has been sent */
50         uint32_t current_rx_size_words;      /*!< Data length in words,
51                                               *        currently is being read */
52     };
53 
54 /** SMSC9220 device structure */
55     struct smsc9220_eth_dev_t
56     {
57         const struct smsc9220_eth_dev_cfg_t * const cfg; /*!< configuration */
58         struct smsc9220_eth_dev_data_t * const data;     /*!< data */
59     };
60 
61 /**
62  * \brief Error code definitions
63  *
64  */
65     enum smsc9220_error_t
66     {
67         SMSC9220_ERROR_NONE = 0U,    /*!< no error */
68         SMSC9220_ERROR_TIMEOUT = 1U, /*!< timeout */
69         SMSC9220_ERROR_BUSY = 2U,    /*!< no error */
70         SMSC9220_ERROR_PARAM = 3U,   /*!< invalid parameter */
71         SMSC9220_ERROR_INTERNAL = 4U /*!< internal error */
72     };
73 
74 /**
75  * \brief Interrupt source definitions
76  *
77  */
78     enum smsc9220_interrupt_source
79     {
80         SMSC9220_INTERRUPT_GPIO0 = 0U,
81         SMSC9220_INTERRUPT_GPIO1 = 1U,
82         SMSC9220_INTERRUPT_GPIO2 = 2U,
83         SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL = 3U,
84         SMSC9220_INTERRUPT_RX_STATUS_FIFO_FULL = 4U,
85         /* 5 Reserved according to Datasheet */
86         SMSC9220_INTERRUPT_RX_DROPPED_FRAME = 6U,
87         SMSC9220_INTERRUPT_TX_STATUS_FIFO_LEVEL = 7U,
88         SMSC9220_INTERRUPT_TX_STATUS_FIFO_FULL = 8U,
89         SMSC9220_INTERRUPT_TX_DATA_FIFO_AVAILABLE = 9U,
90         SMSC9220_INTERRUPT_TX_DATA_FIFO_OVERRUN = 10U,
91         /* 11, 12 Reserved according to Datasheet */
92         SMSC9220_INTERRUPT_TX_ERROR = 13U,
93         SMSC9220_INTERRUPT_RX_ERROR = 14U,
94         SMSC9220_INTERRUPT_RX_WATCHDOG_TIMEOUT = 15U,
95         SMSC9220_INTERRUPT_TX_STATUS_OVERFLOW = 16U,
96         SMSC9220_INTERRUPT_TX_POWER_MANAGEMENT = 17U,
97         SMSC9220_INTERRUPT_PHY = 18U,
98         SMSC9220_INTERRUPT_GP_TIMER = 19U,
99         SMSC9220_INTERRUPT_RX_DMA = 20U,
100         SMSC9220_INTERRUPT_TX_IOC = 21U,
101         /* 22 Reserved according to Datasheet*/
102         SMSC9220_INTERRUPT_RX_DROPPED_FRAME_HALF = 23U,
103         SMSC9220_INTERRUPT_RX_STOPPED = 24U,
104         SMSC9220_INTERRUPT_TX_STOPPED = 25U,
105         /* 26 - 30 Reserved according to Datasheet*/
106         SMSC9220_INTERRUPT_SW = 31U
107     };
108 
109 /**
110  * \brief MAC register offset definitions
111  *
112  */
113     enum smsc9220_mac_reg_offsets_t
114     {
115         SMSC9220_MAC_REG_OFFSET_CR = 0x1U,
116         SMSC9220_MAC_REG_OFFSET_ADDRH = 0x2U,
117         SMSC9220_MAC_REG_OFFSET_ADDRL = 0x3U,
118         SMSC9220_MAC_REG_OFFSET_HASHH = 0x4U,
119         SMSC9220_MAC_REG_OFFSET_HASHL = 0x5U,
120         SMSC9220_MAC_REG_OFFSET_MII_ACC = 0x6U,
121         SMSC9220_MAC_REG_OFFSET_MII_DATA = 0x7U,
122         SMSC9220_MAC_REG_OFFSET_FLOW = 0x8U,
123         SMSC9220_MAC_REG_OFFSET_VLAN1 = 0x9U,
124         SMSC9220_MAC_REG_OFFSET_VLAN2 = 0xAU,
125         SMSC9220_MAC_REG_OFFSET_WUFF = 0xBU,
126         SMSC9220_MAC_REG_OFFSET_WUCSR = 0xCU,
127         SMSC9220_MAC_REG_OFFSET_COE_CR = 0xDU
128     };
129 
130 /**
131  * \brief PHY register offset definitions
132  *
133  */
134     enum phy_reg_offsets_t
135     {
136         SMSC9220_PHY_REG_OFFSET_BCTRL = 0U,
137         SMSC9220_PHY_REG_OFFSET_BSTATUS = 1U,
138         SMSC9220_PHY_REG_OFFSET_ID1 = 2U,
139         SMSC9220_PHY_REG_OFFSET_ID2 = 3U,
140         SMSC9220_PHY_REG_OFFSET_ANEG_ADV = 4U,
141         SMSC9220_PHY_REG_OFFSET_ANEG_LPA = 5U,
142         SMSC9220_PHY_REG_OFFSET_ANEG_EXP = 6U,
143         SMSC9220_PHY_REG_OFFSET_MCONTROL = 17U,
144         SMSC9220_PHY_REG_OFFSET_MSTATUS = 18U,
145         SMSC9220_PHY_REG_OFFSET_CSINDICATE = 27U,
146         SMSC9220_PHY_REG_OFFSET_INTSRC = 29U,
147         SMSC9220_PHY_REG_OFFSET_INTMASK = 30U,
148         SMSC9220_PHY_REG_OFFSET_CS = 31U
149     };
150 
151 /* Bit definitions for PHY Basic Status Register */
152     #define PHY_REG_BSTATUS_EXTENDED_CAPABILITIES_INDEX     0U
153     #define PHY_REG_BSTATUS_JABBER_DETECT_INDEX             1U
154     #define PHY_REG_BSTATUS_LINK_STATUS_INDEX               2U
155     #define PHY_REG_BSTATUS_AUTO_NEG_ABILITY_INDEX          3U
156     #define PHY_REG_BSTATUS_REMOTE_FAULT_INDEX              4U
157     #define PHY_REG_BSTATUS_AUTO_NEG_COMPLETE_INDEX         5U
158     #define PHY_REG_BSTATUS_10BASE_T_HALF_DUPLEX_INDEX      11U
159     #define PHY_REG_BSTATUS_10BASE_T_FULL_DUPLEX_INDEX      12U
160     #define PHY_REG_BSTATUS_100BASE_TX_HALF_DUPLEX_INDEX    13U
161     #define PHY_REG_BSTATUS_100BASE_TX_FULL_DUPLEX_INDEX    14U
162     #define PHY_REG_BSTATUS_100BASE_T4_INDEX                15U
163 
164 /**
165  * \brief FIFO Level Interrupt bit definitions
166  *
167  */
168     enum smsc9220_fifo_level_irq_pos_t
169     {
170         SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS = 0U,
171         SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS = 16U,
172         SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS = 24U
173     };
174 
175 /**
176  * \brief FIFO Level Interrupt limits
177  *
178  */
179     #define SMSC9220_FIFO_LEVEL_IRQ_MASK         0xFFU
180     #define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN    0U
181     #define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX    SMSC9220_FIFO_LEVEL_IRQ_MASK
182 
183 /**
184  * \brief Initializes SMSC9220 Ethernet controller to a known default state:
185  *          - device ID is checked
186  *          - global interrupt is enabled, but all irq sources are disabled
187  *          - all capabilities are advertised
188  *              - 10Mbps able
189  *              - 10Mbps with full duplex
190  *              - 100Mbps Tx able
191  *              - 100Mbps with full duplex
192  *              - Symmetric Pause
193  *              - Asymmetric Pause
194  *          - Establish link enabled
195  *          - Rx enabled
196  *          - Tx enabled
197  *        Init should be called prior to any other process and
198  *        it's the caller's responsibility to follow proper call order.
199  *
200  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
201  * \param[in] wait_ms_function function pointer to a millisec delay function
202  *                             for proper timing of some processes
203  *
204  * \return error code /ref smsc9220_error_t
205  */
206     enum smsc9220_error_t smsc9220_init( const struct smsc9220_eth_dev_t * dev,
207                                          void ( * wait_ms_function )( uint32_t ) );
208 
209 /**
210  * \brief Reads the MAC register.
211  *
212  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
213  * \param[in] regoffset Register offset
214  * \param[in, out] data Pointer to register will be read
215  *
216  * \return error code /ref smsc9220_error_t
217  */
218     enum smsc9220_error_t smsc9220_mac_regread( const struct smsc9220_eth_dev_t * dev,
219                                                 enum smsc9220_mac_reg_offsets_t regoffset,
220                                                 uint32_t * data );
221 
222 /**
223  * \brief Writes the MAC register.
224  *
225  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
226  * \param[in] regoffset Register offset
227  * \param[in] data Register value to write
228  *
229  * \return error code /ref smsc9220_error_t
230  */
231     enum smsc9220_error_t smsc9220_mac_regwrite( const struct smsc9220_eth_dev_t * dev,
232                                                  enum smsc9220_mac_reg_offsets_t regoffset,
233                                                  uint32_t data );
234 
235 /**
236  * \brief Reads the PHY register.
237  *
238  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
239  * \param[in] regoffset Register offset
240  * \param[out] data Register value is read
241  *
242  * \return error code /ref smsc9220_error_t
243  */
244     enum smsc9220_error_t smsc9220_phy_regread( const struct smsc9220_eth_dev_t * dev,
245                                                 enum phy_reg_offsets_t,
246                                                 uint32_t * data );
247 
248 /**
249  * \brief Writes the PHY register.
250  *
251  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
252  * \param[in] regoffset Register offset
253  * \param[in] data Register value to write
254  *
255  * \return error code /ref smsc9220_error_t
256  */
257     enum smsc9220_error_t smsc9220_phy_regwrite( const struct smsc9220_eth_dev_t * dev,
258                                                  enum phy_reg_offsets_t,
259                                                  uint32_t data );
260 
261 /**
262  * \brief Reads the Ethernet Controller's ID.
263  *
264  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
265  *
266  * \return ID number
267  */
268     uint32_t smsc9220_read_id( const struct smsc9220_eth_dev_t * dev );
269 
270 /**
271  * \brief Initiates a soft reset, returns failure or success.
272  *
273  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
274  *
275  * \return error code /ref smsc9220_error_t
276  */
277     enum smsc9220_error_t smsc9220_soft_reset( const struct smsc9220_eth_dev_t * dev );
278 
279 /**
280  * \brief Sets the Maximum Transmission Unit by Tx fifo size.
281  *        Note: The MTU will be smaller by 512 bytes,
282  *        whis is used by the status.
283  *
284  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
285  * \param[in] val Size of the fifo in kbytes
286  *                \ref HW_CFG_REG_TX_FIFO_SIZE_MIN
287  *                \ref HW_CFG_REG_TX_FIFO_SIZE_MAX
288  */
289     void smsc9220_set_txfifo( const struct smsc9220_eth_dev_t * dev,
290                               uint32_t val );
291 
292 /**
293  * \brief Sets the FIFO level interrupt for a given source.
294  *
295  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
296  * \param[in] irq_level_pos Bit position of the FIFO to set
297  *            \ref smsc9220_fifo_level_irq_pos_t
298  * \param[in] level Level of the FIFO, when the FIFO used space is greater
299  *             than this value, corresponding interrupt will be generated.
300  *
301  * \return error code /ref smsc9220_error_t
302  */
303     enum smsc9220_error_t smsc9220_set_fifo_level_irq( const struct smsc9220_eth_dev_t * dev,
304                                                        enum smsc9220_fifo_level_irq_pos_t irq_level_pos,
305                                                        uint32_t level );
306 
307 /**
308  * \brief Waits for EEPROM to be ready to use.
309  *
310  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
311  *
312  * \return error code /ref smsc9220_error_t
313  */
314     enum smsc9220_error_t smsc9220_wait_eeprom( const struct smsc9220_eth_dev_t * dev );
315 
316 /**
317  * \brief Initializes irqs by clearing and disabling all interrupt sources
318  *        and enable interrupts. Since all interrupt sources are disabled,
319  *        interrupt won't be triggered, until interrupt sources won't be
320  *        enabled by \ref smsc9220_enable_interrupt
321  *
322  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
323  */
324     void smsc9220_init_irqs( const struct smsc9220_eth_dev_t * dev );
325 
326 /**
327  * \brief Checks PHY ID registers.
328  *
329  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
330  *
331  * \return error code /ref smsc9220_error_t
332  */
333     enum smsc9220_error_t smsc9220_check_phy( const struct smsc9220_eth_dev_t * dev );
334 
335 /**
336  * \brief Resets PHY.
337  *
338  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
339  *
340  * \return error code /ref smsc9220_error_t
341  */
342     enum smsc9220_error_t smsc9220_reset_phy( const struct smsc9220_eth_dev_t * dev );
343 
344 /**
345  * \brief Advertises all speeds and pauses capabilities.
346  *
347  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
348  */
349     void smsc9220_advertise_cap( const struct smsc9220_eth_dev_t * dev );
350 
351 /**
352  * \brief Enables transmission.
353  *
354  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
355  */
356     void smsc9220_enable_xmit( const struct smsc9220_eth_dev_t * dev );
357 
358 /**
359  * \brief Disables transmission.
360  *
361  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
362  */
363     void smsc9220_disable_xmit( const struct smsc9220_eth_dev_t * dev );
364 
365 /**
366  * \brief Enables MAC Transmitter.
367  *
368  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
369  */
370     void smsc9220_enable_mac_xmit( const struct smsc9220_eth_dev_t * dev );
371 
372 /**
373  * \brief Disables MAC Transmitter.
374  *
375  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
376  */
377     void smsc9220_disable_mac_xmit( const struct smsc9220_eth_dev_t * dev );
378 
379 /**
380  * \brief Enables receiving.
381  *
382  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
383  */
384     void smsc9220_enable_mac_recv( const struct smsc9220_eth_dev_t * dev );
385 
386 /**
387  * \brief Disables receiving.
388  *
389  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
390  */
391     void smsc9220_disable_mac_recv( const struct smsc9220_eth_dev_t * dev );
392 
393 /**
394  * \brief Enables the given interrupt source.
395  *
396  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
397  * \param[in] source Enum of the interrupt source.
398  */
399     void smsc9220_enable_interrupt( const struct smsc9220_eth_dev_t * dev,
400                                     enum smsc9220_interrupt_source source );
401 
402 /**
403  * \brief Disables the given interrupt source.
404  *
405  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
406  * \param[in] source Enum of the interrupt source.
407  */
408     void smsc9220_disable_interrupt( const struct smsc9220_eth_dev_t * dev,
409                                      enum smsc9220_interrupt_source source );
410 
411 /**
412  * \brief Disables all interrupt sources.
413  *
414  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
415  */
416     void smsc9220_disable_all_interrupts( const struct smsc9220_eth_dev_t * dev );
417 
418 /**
419  * \brief Clears the given interrupt source.
420  *
421  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
422  * \param[in] source Enum of the interrupt source.
423  */
424     void smsc9220_clear_interrupt( const struct smsc9220_eth_dev_t * dev,
425                                    enum smsc9220_interrupt_source source );
426 
427 /**
428  * \brief Clears all interrupt sources.
429  *
430  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
431  */
432     void smsc9220_clear_all_interrupts( const struct smsc9220_eth_dev_t * dev );
433 
434 /**
435  * \brief Gets the status of the given interrupt source.
436  *
437  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
438  * \param[in] source Enum of the interrupt source.
439  *
440  * \return non-zero if the given interrupt source is triggered, zero otherwise
441  */
442     int smsc9220_get_interrupt( const struct smsc9220_eth_dev_t * dev,
443                                 enum smsc9220_interrupt_source source );
444 
445 /**
446  * \brief Establishes link
447  *
448  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
449  */
450     void smsc9220_establish_link( const struct smsc9220_eth_dev_t * dev );
451 
452 /**
453  * \brief Reads the Ethernet Controller's MAC address from its EEPROM.
454  *
455  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
456  * \param[in,out] mac array will include the read MAC address in
457  *                6 bytes hexadecimal format.
458  *                It should be allocated by the caller to 6 bytes.
459  *
460  * \return error code /ref smsc9220_error_t
461  */
462     enum smsc9220_error_t smsc9220_read_mac_address( const struct smsc9220_eth_dev_t * dev,
463                                                      char * mac );
464 
465 /**
466  * \brief Check device ID.
467  *
468  * \return error code /ref smsc9220_error_t
469  */
470     int smsc9220_check_id( const struct smsc9220_eth_dev_t * dev );
471 
472 /**
473  * \brief Gets the data size of the Tx buffer, aka Maximum Trasmission Unit
474  *
475  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
476  *
477  * \return Fifo data size in bytes
478  */
479     uint32_t smsc9220_get_tx_data_fifo_size( const struct
480                                              smsc9220_eth_dev_t * dev );
481 
482 /**
483  * \brief Sends data from the given buffer as an Ethernet packet.
484  *        The full packet length must be specified at the beginning
485  *        of a new packet transmission.
486  *
487  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
488  * \param[in] total_payload_length Length of the ethernet payload.
489  *            Should be equal to the sum of passed buffers within a packet.
490  * \param[in] is_new_packet Should be set to true if the input buffer has to
491  *            be sent as the start of a new packet or as a full packet.
492  * \param[in] data Pointer to the data buffer to be sent.
493  * \param[in] current_size Size of the data in bytes.
494  *
495  * \return error code /ref smsc9220_error_t
496  */
497     enum smsc9220_error_t smsc9220_send_by_chunks( const struct smsc9220_eth_dev_t * dev,
498                                                    uint32_t total_payload_length,
499                                                    bool is_new_packet,
500                                                    const char * data,
501                                                    uint32_t current_size );
502 
503 /**
504  * \brief Reads an incoming Ethernet packet into the given buffer.
505  *        Stops reading at packet border.
506  *
507  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
508  * \param[in,out] data Pointer to a pre-allocated input buffer.
509  *                     Allocating sufficient memory space is the caller's
510  *                     responsibility, which is typically done by calling
511  *                     \ref smsc9220_peek_next_packet_size.
512  * \param[in] dlen Length of the allocated data in bytes.
513  *
514  * \return Number of bytes read from the Rx FIFO into the given buffer.
515  */
516     uint32_t smsc9220_receive_by_chunks( const struct smsc9220_eth_dev_t * dev,
517                                          char * data,
518                                          uint32_t dlen );
519 
520 /**
521  * \brief Get the used space of Rx fifo in bytes.
522  *
523  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
524  *
525  * \return Data received and waiting for read in bytes
526  */
527     uint32_t smsc9220_get_rxfifo_data_used_space( const struct
528                                                   smsc9220_eth_dev_t * dev );
529 
530 /**
531  * \brief Gets the size of next unread packet in Rx buffer, using the peak
532  *        register, which is not destructive so can be read asynchronously.
533  *        Warning: In case of heavy receiving loads, this register may not
534  *        be in perfect sync.
535  *
536  * \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
537  *
538  * \return Size of the next packet in bytes, read from the Rx Peek register.
539  */
540     uint32_t smsc9220_peek_next_packet_size( const struct
541                                              smsc9220_eth_dev_t * dev );
542 
543     #ifdef __cplusplus
544 }
545     #endif
546 
547 #endif /* __SMSC9220_ETH_H__ */
548