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 #include "smsc9220_eth_drv.h"
20 /*#include "CMSIS/SMM_MPS2.h" */
21 
22 /** Setter bit manipulation macro */
23 #define SET_BIT( WORD, BIT_INDEX )    ( ( WORD ) |= ( 1U << ( BIT_INDEX ) ) )
24 /** Clearing bit manipulation macro */
25 #define CLR_BIT( WORD, BIT_INDEX )    ( ( WORD ) &= ~( 1U << ( BIT_INDEX ) ) )
26 /** Getter bit manipulation macro */
27 #define GET_BIT( WORD, BIT_INDEX )    ( bool ) ( ( ( WORD ) & ( 1U << ( BIT_INDEX ) ) ) )
28 
29 /** Setter bit-field manipulation macro */
30 #define SET_BIT_FIELD( WORD, BIT_MASK, BIT_OFFSET, VALUE ) \
31     ( WORD |= ( ( VALUE & BIT_MASK ) << BIT_OFFSET ) )
32 
33 /** Clearing bit-field manipulation macro */
34 #define CLR_BIT_FIELD( WORD, BIT_MASK, BIT_OFFSET, VALUE ) \
35     ( WORD &= ~( ( VALUE & BIT_MASK ) << BIT_OFFSET ) )
36 
37 /** Getter bit-field manipulation macro */
38 #define GET_BIT_FIELD( WORD, BIT_MASK, BIT_OFFSET ) \
39     ( ( WORD >> BIT_OFFSET ) & BIT_MASK )
40 
41 /** Millisec timeout macros */
42 #define RESET_TIME_OUT_MS        10U
43 #define REG_WRITE_TIME_OUT_MS    50U
44 #define PHY_RESET_TIME_OUT_MS    100U
45 #define INIT_FINISH_DELAY        2000U
46 
47 struct smsc9220_eth_reg_map_t
48 {
49     volatile uint32_t rx_data_port; /**< Receive FIFO Ports (offset 0x0) */
50     uint32_t reserved1[ 0x7 ];
51     volatile uint32_t tx_data_port; /**< Transmit FIFO Ports (offset 0x20) */
52     uint32_t reserved2[ 0x7 ];
53 
54     volatile uint32_t rx_status_port;    /**< Receive FIFO status port (offset 0x40) */
55     volatile uint32_t rx_status_peek;    /**< Receive FIFO status peek (offset 0x44) */
56     volatile uint32_t tx_status_port;    /**< Transmit FIFO status port (offset 0x48) */
57     volatile uint32_t tx_status_peek;    /**< Transmit FIFO status peek (offset 0x4C) */
58 
59     volatile uint32_t id_revision;       /**< Chip ID and Revision (offset 0x50) */
60     volatile uint32_t irq_cfg;           /**< Main Interrupt Config (offset 0x54) */
61     volatile uint32_t irq_status;        /**< Interrupt Status (offset 0x58) */
62     volatile uint32_t irq_enable;        /**< Interrupt Enable Register (offset 0x5C) */
63     uint32_t reserved3;                  /**< Reserved for future use (offset 0x60) */
64     volatile uint32_t byte_test;         /**< Byte order test 87654321h (offset 0x64) */
65     volatile uint32_t fifo_level_irq;    /**< FIFO Level Interrupts (offset 0x68) */
66     volatile uint32_t rx_cfg;            /**< Receive Configuration (offset 0x6C) */
67     volatile uint32_t tx_cfg;            /**< Transmit Configuration (offset 0x70) */
68     volatile uint32_t hw_cfg;            /**< Hardware Configuration (offset 0x74) */
69     volatile uint32_t rx_datapath_ctrl;  /**< RX Datapath Control (offset 0x78) */
70     volatile uint32_t rx_fifo_inf;       /**< Receive FIFO Information (offset 0x7C) */
71     volatile uint32_t tx_fifo_inf;       /**< Transmit FIFO Information (offset 0x80) */
72     volatile uint32_t pmt_ctrl;          /**< Power Management Control (offset 0x84) */
73     volatile uint32_t gpio_cfg;          /**< GPIO Configuration (offset 0x88) */
74     volatile uint32_t gptimer_cfg;       /**< GP Timer Configuration (offset 0x8C) */
75     volatile uint32_t gptimer_count;     /**< GP Timer Count (offset 0x90) */
76     uint32_t reserved4;                  /**< Reserved for future use (offset 0x94) */
77     volatile uint32_t word_swap;         /**< WORD SWAP Register (offset 0x98) */
78     volatile uint32_t free_run_counter;  /**< Free Run Counter (offset 0x9C) */
79     volatile uint32_t rx_dropped_frames; /**< RX Dropped Frames Counter (offset 0xA0) */
80     volatile uint32_t mac_csr_cmd;       /**< MAC CSR Synchronizer Cmd (offset 0xA4) */
81     volatile uint32_t mac_csr_data;      /**< MAC CSR Synchronizer Data (offset 0xA8) */
82     volatile uint32_t afc_cfg;           /**< AutomaticFlow Ctrl Config (offset 0xAC) */
83     volatile uint32_t eeprom_cmd;        /**< EEPROM Command (offset 0xB0) */
84     volatile uint32_t eeprom_data;       /**< EEPROM Data (offset 0xB4) */
85 };
86 
87 /**
88  * \brief TX FIFO Size definitions
89  *
90  */
91 #define TX_STATUS_FIFO_SIZE_BYTES        512U /*< fixed allocation in bytes */
92 #define TX_DATA_FIFO_SIZE_KBYTES_POS     16U
93 #define TX_DATA_FIFO_SIZE_KBYTES_MASK    0x0FU
94 #define KBYTES_TO_BYTES_MULTIPLIER       1024U
95 
96 /**
97  * \brief FIFO Info definitions
98  *
99  */
100 #define FIFO_USED_SPACE_MASK             0xFFFFU
101 #define DATA_FIFO_USED_SPACE_POS         0U
102 #define STATUS_FIFO_USED_SPACE_POS       16U
103 
104 /**
105  * \brief MAC CSR Synchronizer Command bit definitions
106  *
107  */
108 enum mac_csr_cmd_bits_t
109 {
110     MAC_CSR_CMD_RW_INDEX = 30U,
111     MAC_CSR_CMD_BUSY_INDEX = 31U,
112 };
113 
114 #define MAC_CSR_CMD_ADDRESS_MASK    0x0FU
115 
116 /**
117  * \brief MAC Control register bit definitions
118  *
119  */
120 enum mac_reg_cr_bits_t
121 {
122     MAC_REG_CR_RXEN_INDEX = 2U,
123     MAC_REG_CR_TXEN_INDEX = 3U
124 };
125 
126 /**
127  * \brief MII Access register bit definitions
128  *
129  */
130 enum mac_reg_mii_acc_bits_t
131 {
132     MAC_REG_MII_ACC_BUSY_INDEX = 0U,
133     MAC_REG_MII_ACC_WRITE_INDEX = 1U,
134     MAC_REG_MII_ACC_PHYADDR_INDEX = 11U
135 };
136 #define MAC_REG_MII_ACC_MII_REG_MASK      0x1FU
137 #define MAC_REG_MII_ACC_MII_REG_OFFSET    6U
138 
139 /**
140  * \brief Hardware config register bit definitions
141  *
142  */
143 enum hw_cfg_reg_bits_t
144 {
145     HW_CFG_REG_SRST_INDEX = 0U,
146     HW_CFG_REG_SRST_TIMEOUT_INDEX = 1U,
147     HW_CFG_REG_MUST_BE_ONE_INDEX = 20U,
148 };
149 #define HW_CFG_REG_TX_FIFO_SIZE_POS    16U
150 #define HW_CFG_REG_TX_FIFO_SIZE_MIN    2U   /*< Min Tx fifo size in KB */
151 #define HW_CFG_REG_TX_FIFO_SIZE_MAX    14U  /*< Max Tx fifo size in KB */
152 #define HW_CFG_REG_TX_FIFO_SIZE        5U   /*< Tx fifo size in KB */
153 
154 /**
155  * \brief EEPROM command register bit definitions
156  *
157  */
158 enum eeprom_cmd_reg_bits_t
159 {
160     EEPROM_CMD_REG_BUSY_INDEX = 31U,
161 };
162 
163 /**
164  * \brief PHY Basic Control register bit definitions
165  *
166  */
167 enum phy_reg_bctrl_reg_bits_t
168 {
169     PHY_REG_BCTRL_RST_AUTO_NEG_INDEX = 9U,
170     PHY_REG_BCTRL_AUTO_NEG_EN_INDEX = 12U,
171     PHY_REG_BCTRL_RESET_INDEX = 15U
172 };
173 
174 /**
175  * \brief TX Command A bit definitions
176  *
177  */
178 #define TX_CMD_DATA_START_OFFSET_BYTES_POS     16U
179 #define TX_CMD_DATA_START_OFFSET_BYTES_MASK    0x1FU
180 
181 
182 enum tx_command_a_bits_t
183 {
184     TX_COMMAND_A_LAST_SEGMENT_INDEX = 12U,
185     TX_COMMAND_A_FIRST_SEGMENT_INDEX = 13U
186 };
187 
188 #define TX_CMD_PKT_LEN_BYTES_MASK    0x7FFU
189 #define TX_CMD_PKT_TAG_MASK          0xFFFFU
190 #define TX_CMD_PKT_TAG_POS           16U
191 
192 
193 /**
194  * \brief RX Fifo Status bit definitions
195  *
196  */
197 enum rx_fifo_status_bits_t
198 {
199     RX_FIFO_STATUS_CRC_ERROR_INDEX = 1U,
200     RX_FIFO_STATUS_DRIBBLING_BIT_INDEX = 2U,
201     RX_FIFO_STATUS_MII_ERROR_INDEX = 3U,
202     RX_FIFO_STATUS_REC_WD_TIMEOUT_INDEX = 4U,
203     RX_FIFO_STATUS_FRAME_TYPE_INDEX = 5U,
204     RX_FIFO_STATUS_COLLISION_SEEN_INDEX = 6U,
205     RX_FIFO_STATUS_FRAME_TOO_LONG_INDEX = 7U,
206     RX_FIFO_STATUS_MULTICAST_INDEX = 10U,
207     RX_FIFO_STATUS_RUNT_FRAME_INDEX = 11U,
208     RX_FIFO_STATUS_LENGTH_ERROR_INDEX = 12U,
209     RX_FIFO_STATUS_BROADCAST_FRAME_INDEX = 13U,
210     RX_FIFO_STATUS_ERROR_INDEX = 15U,
211     RX_FIFO_STATUS_FILTERING_FAIL_INDEX = 30U,
212 };
213 #define RX_FIFO_STATUS_PKT_LENGTH_POS     16U
214 #define RX_FIFO_STATUS_PKT_LENGTH_MASK    0x3FFFU
215 
216 /**
217  * \brief Interrupt Configuration register bit definitions
218  *
219  */
220 enum irq_cfg_bits_t
221 {
222     IRQ_CFG_IRQ_TYPE = 0U,
223     IRQ_CFG_IRQ_POL = 4U,
224     IRQ_CFG_IRQ_EN_INDEX = 8U
225 };
226 
227 #define IRQ_CFG_INT_DEAS_MASK    0xFFU
228 #define IRQ_CFG_INT_DEAS_POS     24U
229 #define IRQ_CFG_INT_DEAS_10US    0x22U
230 
231 /**
232  * \brief Automatic Flow Control register bit definitions
233  *
234  */
235 enum afc_bits_t
236 {
237     AFC_ANY_INDEX = 0U,
238     AFC_ADDR_INDEX = 1U,
239     AFC_BROADCAST_INDEX = 2U,
240     AFC_MULTICAST_INDEX = 3U
241 };
242 
243 #define AFC_BACK_DUR_MASK      0x0FU
244 #define AFC_BACK_DUR_POS       4U
245 #define AFC_BACK_DUR           4U /**< equal to 50us */
246 
247 #define AFC_LOW_LEVEL_MASK     0xFFU
248 #define AFC_LOW_LEVEL_POS      8U
249 #define AFC_LOW_LEVEL          55U /**< specifies in multiple of 64 bytes */
250 
251 #define AFC_HIGH_LEVEL_MASK    0xFFU
252 #define AFC_HIGH_LEVEL_POS     16U
253 #define AFC_HIGH_LEVEL         110U /**< specifies in multiple of 64 bytes */
254 
255 /**
256  * \brief Auto-Negotiation Advertisement register bit definitions
257  *
258  */
259 enum aneg_bits_t
260 {
261     ANEG_10_BASE_T_INDEX = 5U,             /**< 10Mbps able */
262     ANEG_10_BASE_T_FULL_DUPL_INDEX = 6U,   /**< 10Mbps with full duplex */
263     ANEG_100_BASE_TX_INDEX = 7U,           /**< 100Mbps Tx able */
264     ANEG_100_BASE_TX_FULL_DUPL_INDEX = 8U, /**< 100Mbps with full duplex */
265     ANEG_SYMM_PAUSE_INDEX = 10U,           /**< Symmetric Pause */
266     ANEG_ASYMM_PAUSE_INDEX = 11U           /**< Asymmetric Pause */
267 };
268 
269 /**
270  * \brief Transmit Configuration register bit definitions
271  *
272  */
273 enum tx_cfg_bits_t
274 {
275     TX_CFG_STOP_INDEX = 0U,      /*< stop */
276     TX_CFG_ON_INDEX = 1U,        /*< on */
277     TX_CFG_AO_INDEX = 2U,        /*< allow overrun */
278     TX_CFG_TXD_DUMP_INDEX = 14U, /*< Data FIFO dump */
279     TX_CFG_TXS_DUMP_INDEX = 15U  /*< Status FIFO dump */
280 };
281 
282 /**
283  * \brief Chip ID definitions
284  *
285  */
286 /*#define CHIP_ID         0x9220U */
287 #define CHIP_ID         0x0118U
288 #define CHIP_ID_MASK    0xFFFFU
289 #define CHIP_ID_POS     16U
290 
291 /**
292  * \brief GPIO Configuration register bit definitions
293  *
294  */
295 enum gpio_cfg_bits_t
296 {
297     GPIO_CFG_GPIO0_PUSHPULL_INDEX = 16U, /*< GPIO0 push/pull or open-drain */
298     GPIO_CFG_GPIO1_PUSHPULL_INDEX = 17U, /*< GPIO1 push/pull or open-drain */
299     GPIO_CFG_GPIO2_PUSHPULL_INDEX = 18U, /*< GPIO2 push/pull or open-drain */
300     GPIO_CFG_GPIO0_LED_INDEX = 28U,      /*< GPIO0 set to LED1 */
301     GPIO_CFG_GPIO1_LED_INDEX = 29U,      /*< GPIO1 set to LED2 */
302     GPIO_CFG_GPIO2_LED_INDEX = 30U       /*< GPIO2 set to LED3 */
303 };
304 
305 
fill_tx_fifo(const struct smsc9220_eth_dev_t * dev,uint8_t * data,uint32_t size_bytes)306 static void fill_tx_fifo( const struct smsc9220_eth_dev_t * dev,
307                           uint8_t * data,
308                           uint32_t size_bytes )
309 {
310     struct smsc9220_eth_reg_map_t * register_map =
311         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
312 
313     uint32_t tx_data_port_tmp = 0;
314     uint8_t * tx_data_port_tmp_ptr = ( uint8_t * ) &tx_data_port_tmp;
315 
316     /*If the data length is not a multiple of 4, then the beginning of the first
317      * DWORD of the TX DATA FIFO gets filled up with zeros and a byte offset is
318      * set accordingly to guarantee proper transmission.*/
319     uint32_t remainder_bytes = ( size_bytes % 4 );
320     uint32_t filler_bytes = ( 4 - remainder_bytes );
321 
322     for( uint32_t i = 0; i < 4; i++ )
323     {
324         if( i < filler_bytes )
325         {
326             tx_data_port_tmp_ptr[ i ] = 0;
327         }
328         else
329         {
330             tx_data_port_tmp_ptr[ i ] = data[ i - filler_bytes ];
331         }
332     }
333 
334     register_map->tx_data_port = tx_data_port_tmp;
335     size_bytes -= remainder_bytes;
336     data += remainder_bytes;
337 
338     while( size_bytes > 0 )
339     {
340         /* Keep the same endianness in data as in the temp variable */
341         tx_data_port_tmp_ptr[ 0 ] = data[ 0 ];
342         tx_data_port_tmp_ptr[ 1 ] = data[ 1 ];
343         tx_data_port_tmp_ptr[ 2 ] = data[ 2 ];
344         tx_data_port_tmp_ptr[ 3 ] = data[ 3 ];
345         register_map->tx_data_port = tx_data_port_tmp;
346         data += 4;
347         size_bytes -= 4;
348     }
349 }
350 
empty_rx_fifo(const struct smsc9220_eth_dev_t * dev,uint8_t * data,uint32_t size_bytes)351 static void empty_rx_fifo( const struct smsc9220_eth_dev_t * dev,
352                            uint8_t * data,
353                            uint32_t size_bytes )
354 {
355     struct smsc9220_eth_reg_map_t * register_map =
356         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
357 
358     uint32_t rx_data_port_tmp = 0;
359     uint8_t * rx_data_port_tmp_ptr = ( uint8_t * ) &rx_data_port_tmp;
360 
361     uint32_t remainder_bytes = ( size_bytes % 4 );
362 
363     size_bytes -= remainder_bytes;
364 
365     while( size_bytes > 0 )
366     {
367         /* Keep the same endianness in data as in the temp variable */
368         rx_data_port_tmp = register_map->rx_data_port;
369         data[ 0 ] = rx_data_port_tmp_ptr[ 0 ];
370         data[ 1 ] = rx_data_port_tmp_ptr[ 1 ];
371         data[ 2 ] = rx_data_port_tmp_ptr[ 2 ];
372         data[ 3 ] = rx_data_port_tmp_ptr[ 3 ];
373         data += 4;
374         size_bytes -= 4;
375     }
376 
377     rx_data_port_tmp = register_map->rx_data_port;
378 
379     for( uint32_t i = 0; i < remainder_bytes; i++ )
380     {
381         data[ i ] = rx_data_port_tmp_ptr[ i ];
382     }
383 }
384 
smsc9220_mac_regread(const struct smsc9220_eth_dev_t * dev,enum smsc9220_mac_reg_offsets_t regoffset,uint32_t * data)385 enum smsc9220_error_t smsc9220_mac_regread( const struct smsc9220_eth_dev_t * dev,
386                                             enum smsc9220_mac_reg_offsets_t regoffset,
387                                             uint32_t * data )
388 {
389     volatile uint32_t val;
390     uint32_t maccmd = GET_BIT_FIELD( regoffset,
391                                      MAC_CSR_CMD_ADDRESS_MASK, 0 );
392     uint32_t time_out = REG_WRITE_TIME_OUT_MS;
393 
394     struct smsc9220_eth_reg_map_t * register_map =
395         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
396 
397     /* Make sure there's no pending operation */
398     if( !( GET_BIT( register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX ) ) )
399     {
400         SET_BIT( maccmd, MAC_CSR_CMD_RW_INDEX );
401         SET_BIT( maccmd, MAC_CSR_CMD_BUSY_INDEX );
402         register_map->mac_csr_cmd = maccmd; /* Start operation */
403 
404         do
405         {
406             val = register_map->byte_test; /* A no-op read. */
407             ( void ) val;
408 
409             if( dev->data->wait_ms )
410             {
411                 dev->data->wait_ms( 1 );
412             }
413 
414             time_out--;
415         } while( time_out &&
416                  GET_BIT( register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX ) );
417 
418         if( !time_out )
419         {
420             return SMSC9220_ERROR_TIMEOUT;
421         }
422         else
423         {
424             *data = register_map->mac_csr_data;
425         }
426     }
427     else
428     {
429         return SMSC9220_ERROR_BUSY;
430     }
431 
432     return SMSC9220_ERROR_NONE;
433 }
434 
smsc9220_mac_regwrite(const struct smsc9220_eth_dev_t * dev,enum smsc9220_mac_reg_offsets_t regoffset,uint32_t data)435 enum smsc9220_error_t smsc9220_mac_regwrite( const struct smsc9220_eth_dev_t * dev,
436                                              enum smsc9220_mac_reg_offsets_t regoffset,
437                                              uint32_t data )
438 {
439     volatile uint32_t read = 0;
440     uint32_t maccmd = GET_BIT_FIELD( regoffset,
441                                      MAC_CSR_CMD_ADDRESS_MASK, 0 );
442     uint32_t time_out = REG_WRITE_TIME_OUT_MS;
443 
444     struct smsc9220_eth_reg_map_t * register_map =
445         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
446 
447     /* Make sure there's no pending operation */
448     if( !GET_BIT( register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX ) )
449     {
450         register_map->mac_csr_data = data; /* Store data. */
451         CLR_BIT( maccmd, MAC_CSR_CMD_RW_INDEX );
452         SET_BIT( maccmd, MAC_CSR_CMD_BUSY_INDEX );
453         register_map->mac_csr_cmd = maccmd;
454 
455         do
456         {
457             read = register_map->byte_test; /* A no-op read. */
458             ( void ) read;
459 
460             if( dev->data->wait_ms )
461             {
462                 dev->data->wait_ms( 1 );
463             }
464 
465             time_out--;
466         } while( time_out &&
467                  ( register_map->mac_csr_cmd &
468                    GET_BIT( register_map->mac_csr_cmd, MAC_CSR_CMD_BUSY_INDEX ) ) );
469 
470         if( !time_out )
471         {
472             return SMSC9220_ERROR_TIMEOUT;
473         }
474     }
475     else
476     {
477         return SMSC9220_ERROR_BUSY;
478     }
479 
480     return SMSC9220_ERROR_NONE;
481 }
482 
smsc9220_phy_regread(const struct smsc9220_eth_dev_t * dev,enum phy_reg_offsets_t regoffset,uint32_t * data)483 enum smsc9220_error_t smsc9220_phy_regread( const struct smsc9220_eth_dev_t * dev,
484                                             enum phy_reg_offsets_t regoffset,
485                                             uint32_t * data )
486 {
487     uint32_t val = 0;
488     uint32_t phycmd = 0;
489     uint32_t time_out = REG_WRITE_TIME_OUT_MS;
490 
491     if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, &val ) )
492     {
493         return SMSC9220_ERROR_INTERNAL;
494     }
495 
496     if( !GET_BIT( val, MAC_REG_MII_ACC_BUSY_INDEX ) )
497     {
498         phycmd = 0;
499         SET_BIT( phycmd, MAC_REG_MII_ACC_PHYADDR_INDEX );
500         SET_BIT_FIELD( phycmd, MAC_REG_MII_ACC_MII_REG_MASK,
501                        MAC_REG_MII_ACC_MII_REG_OFFSET, regoffset );
502         CLR_BIT( phycmd, MAC_REG_MII_ACC_WRITE_INDEX );
503         SET_BIT( phycmd, MAC_REG_MII_ACC_BUSY_INDEX );
504 
505         if( smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_MII_ACC,
506                                    phycmd ) )
507         {
508             return SMSC9220_ERROR_INTERNAL;
509         }
510 
511         val = 0;
512 
513         do
514         {
515             if( dev->data->wait_ms )
516             {
517                 dev->data->wait_ms( 1 );
518             }
519 
520             time_out--;
521 
522             if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_MII_ACC,
523                                       &val ) )
524             {
525                 return SMSC9220_ERROR_INTERNAL;
526             }
527         } while( time_out && ( GET_BIT( val, MAC_REG_MII_ACC_BUSY_INDEX ) ) );
528 
529         if( !time_out )
530         {
531             return SMSC9220_ERROR_TIMEOUT;
532         }
533         else if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_MII_DATA,
534                                        data ) )
535         {
536             return SMSC9220_ERROR_INTERNAL;
537         }
538     }
539     else
540     {
541         return SMSC9220_ERROR_BUSY;
542     }
543 
544     return SMSC9220_ERROR_NONE;
545 }
546 
smsc9220_phy_regwrite(const struct smsc9220_eth_dev_t * dev,enum phy_reg_offsets_t regoffset,uint32_t data)547 enum smsc9220_error_t smsc9220_phy_regwrite( const struct smsc9220_eth_dev_t * dev,
548                                              enum phy_reg_offsets_t regoffset,
549                                              uint32_t data )
550 {
551     uint32_t val = 0;
552     uint32_t phycmd = 0;
553     uint32_t time_out = REG_WRITE_TIME_OUT_MS;
554 
555     if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_MII_ACC, &val ) )
556     {
557         return SMSC9220_ERROR_INTERNAL;
558     }
559 
560     if( !GET_BIT( val, MAC_REG_MII_ACC_BUSY_INDEX ) )
561     {
562         /* Load the data */
563         if( smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_MII_DATA,
564                                    ( data & 0xFFFF ) ) )
565         {
566             return SMSC9220_ERROR_INTERNAL;
567         }
568 
569         phycmd = 0;
570         SET_BIT( phycmd, MAC_REG_MII_ACC_PHYADDR_INDEX );
571         SET_BIT_FIELD( phycmd, MAC_REG_MII_ACC_MII_REG_MASK,
572                        MAC_REG_MII_ACC_MII_REG_OFFSET, regoffset );
573         SET_BIT( phycmd, MAC_REG_MII_ACC_WRITE_INDEX );
574         SET_BIT( phycmd, MAC_REG_MII_ACC_BUSY_INDEX );
575 
576         /* Start operation */
577         if( smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_MII_ACC,
578                                    phycmd ) )
579         {
580             return SMSC9220_ERROR_INTERNAL;
581         }
582 
583         phycmd = 0;
584 
585         do
586         {
587             if( dev->data->wait_ms )
588             {
589                 dev->data->wait_ms( 1 );
590             }
591 
592             time_out--;
593 
594             if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_MII_ACC,
595                                       &phycmd ) )
596             {
597                 return SMSC9220_ERROR_INTERNAL;
598             }
599         } while( time_out && GET_BIT( phycmd, 0 ) );
600 
601         if( !time_out )
602         {
603             return SMSC9220_ERROR_TIMEOUT;
604         }
605     }
606     else
607     {
608         return SMSC9220_ERROR_BUSY;
609     }
610 
611     return SMSC9220_ERROR_NONE;
612 }
613 
smsc9220_read_id(const struct smsc9220_eth_dev_t * dev)614 uint32_t smsc9220_read_id( const struct smsc9220_eth_dev_t * dev )
615 {
616     struct smsc9220_eth_reg_map_t * register_map =
617         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
618 
619     return register_map->id_revision;
620 }
621 
smsc9220_soft_reset(const struct smsc9220_eth_dev_t * dev)622 enum smsc9220_error_t smsc9220_soft_reset( const struct smsc9220_eth_dev_t * dev )
623 {
624     uint32_t time_out = RESET_TIME_OUT_MS;
625 
626     struct smsc9220_eth_reg_map_t * register_map =
627         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
628 
629     /* Soft reset */
630     SET_BIT( register_map->hw_cfg, HW_CFG_REG_SRST_INDEX );
631 
632     do
633     {
634         if( dev->data->wait_ms )
635         {
636             dev->data->wait_ms( 1 );
637         }
638 
639         time_out--;
640     } while( time_out &&
641              GET_BIT( register_map->hw_cfg, HW_CFG_REG_SRST_TIMEOUT_INDEX ) );
642 
643     if( !time_out )
644     {
645         return SMSC9220_ERROR_TIMEOUT;
646     }
647 
648     return SMSC9220_ERROR_NONE;
649 }
650 
smsc9220_set_txfifo(const struct smsc9220_eth_dev_t * dev,uint32_t val)651 void smsc9220_set_txfifo( const struct smsc9220_eth_dev_t * dev,
652                           uint32_t val )
653 {
654     struct smsc9220_eth_reg_map_t * register_map =
655         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
656 
657     if( ( val >= HW_CFG_REG_TX_FIFO_SIZE_MIN ) &&
658         ( val <= HW_CFG_REG_TX_FIFO_SIZE_MAX ) )
659     {
660         register_map->hw_cfg = val << HW_CFG_REG_TX_FIFO_SIZE_POS;
661     }
662 }
663 
smsc9220_set_fifo_level_irq(const struct smsc9220_eth_dev_t * dev,enum smsc9220_fifo_level_irq_pos_t irq_level_pos,uint32_t level)664 enum smsc9220_error_t smsc9220_set_fifo_level_irq( const struct smsc9220_eth_dev_t * dev,
665                                                    enum smsc9220_fifo_level_irq_pos_t irq_level_pos,
666                                                    uint32_t level )
667 {
668     struct smsc9220_eth_reg_map_t * register_map =
669         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
670     enum smsc9220_error_t eReturn = SMSC9220_ERROR_PARAM;
671 
672     #if ( SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN > 0 )
673         if( level < SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN )
674         {
675             /* An error will be returned. */
676         }
677         else
678     #endif
679 
680     if( level <= SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX )
681     {
682         CLR_BIT_FIELD( register_map->fifo_level_irq, SMSC9220_FIFO_LEVEL_IRQ_MASK,
683                        irq_level_pos, SMSC9220_FIFO_LEVEL_IRQ_MASK );
684         SET_BIT_FIELD( register_map->fifo_level_irq, SMSC9220_FIFO_LEVEL_IRQ_MASK,
685                        irq_level_pos, level );
686         eReturn = SMSC9220_ERROR_NONE;
687     }
688 
689     return eReturn;
690 }
691 
smsc9220_wait_eeprom(const struct smsc9220_eth_dev_t * dev)692 enum smsc9220_error_t smsc9220_wait_eeprom( const struct smsc9220_eth_dev_t * dev )
693 {
694     uint32_t time_out = REG_WRITE_TIME_OUT_MS;
695 
696     struct smsc9220_eth_reg_map_t * register_map =
697         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
698 
699     do
700     {
701         if( dev->data->wait_ms )
702         {
703             dev->data->wait_ms( 1 );
704         }
705 
706         time_out--;
707     } while( time_out &&
708              GET_BIT( register_map->eeprom_cmd, EEPROM_CMD_REG_BUSY_INDEX ) );
709 
710     if( !time_out )
711     {
712         return SMSC9220_ERROR_TIMEOUT;
713     }
714 
715     return SMSC9220_ERROR_NONE;
716 }
717 
smsc9220_init_irqs(const struct smsc9220_eth_dev_t * dev)718 void smsc9220_init_irqs( const struct smsc9220_eth_dev_t * dev )
719 {
720     struct smsc9220_eth_reg_map_t * register_map =
721         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
722 
723     smsc9220_disable_all_interrupts( dev );
724     smsc9220_clear_all_interrupts( dev );
725 
726     /* Set IRQ deassertion interval */
727     SET_BIT_FIELD( register_map->irq_cfg, IRQ_CFG_INT_DEAS_MASK,
728                    IRQ_CFG_INT_DEAS_POS, IRQ_CFG_INT_DEAS_10US );
729 
730     /* enable interrupts */
731     SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_TYPE );
732     SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_POL );
733     SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_EN_INDEX );
734 }
735 
smsc9220_check_phy(const struct smsc9220_eth_dev_t * dev)736 enum smsc9220_error_t smsc9220_check_phy( const struct smsc9220_eth_dev_t * dev )
737 {
738     uint32_t phyid1 = 0;
739     uint32_t phyid2 = 0;
740 
741     if( smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_ID1, &phyid1 ) )
742     {
743         return SMSC9220_ERROR_INTERNAL;
744     }
745 
746     if( smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_ID2, &phyid2 ) )
747     {
748         return SMSC9220_ERROR_INTERNAL;
749     }
750 
751     if( ( ( phyid1 == 0xFFFF ) && ( phyid2 == 0xFFFF ) ) ||
752         ( ( phyid1 == 0x0 ) && ( phyid2 == 0x0 ) ) )
753     {
754         return SMSC9220_ERROR_INTERNAL;
755     }
756 
757     return SMSC9220_ERROR_NONE;
758 }
759 
smsc9220_reset_phy(const struct smsc9220_eth_dev_t * dev)760 enum smsc9220_error_t smsc9220_reset_phy( const struct smsc9220_eth_dev_t * dev )
761 {
762     uint32_t read = 0;
763 
764     if( smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_BCTRL, &read ) )
765     {
766         return SMSC9220_ERROR_INTERNAL;
767     }
768 
769     SET_BIT( read, PHY_REG_BCTRL_RESET_INDEX );
770 
771     if( smsc9220_phy_regwrite( dev, SMSC9220_PHY_REG_OFFSET_BCTRL, read ) )
772     {
773         return SMSC9220_ERROR_INTERNAL;
774     }
775 
776     return SMSC9220_ERROR_NONE;
777 }
778 
smsc9220_advertise_cap(const struct smsc9220_eth_dev_t * dev)779 void smsc9220_advertise_cap( const struct smsc9220_eth_dev_t * dev )
780 {
781     uint32_t aneg_adv = 0;
782 
783     smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_ANEG_ADV, &aneg_adv );
784 
785     SET_BIT( aneg_adv, ANEG_10_BASE_T_INDEX );
786     SET_BIT( aneg_adv, ANEG_10_BASE_T_FULL_DUPL_INDEX );
787     SET_BIT( aneg_adv, ANEG_100_BASE_TX_INDEX );
788     SET_BIT( aneg_adv, ANEG_100_BASE_TX_FULL_DUPL_INDEX );
789     SET_BIT( aneg_adv, ANEG_SYMM_PAUSE_INDEX );
790     SET_BIT( aneg_adv, ANEG_ASYMM_PAUSE_INDEX );
791 
792     smsc9220_phy_regwrite( dev, SMSC9220_PHY_REG_OFFSET_ANEG_ADV, aneg_adv );
793 }
794 
smsc9220_enable_xmit(const struct smsc9220_eth_dev_t * dev)795 void smsc9220_enable_xmit( const struct smsc9220_eth_dev_t * dev )
796 {
797     struct smsc9220_eth_reg_map_t * register_map =
798         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
799 
800     SET_BIT( register_map->tx_cfg, TX_CFG_ON_INDEX );
801 }
802 
smsc9220_disable_xmit(const struct smsc9220_eth_dev_t * dev)803 void smsc9220_disable_xmit( const struct smsc9220_eth_dev_t * dev )
804 {
805     struct smsc9220_eth_reg_map_t * register_map =
806         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
807 
808     CLR_BIT( register_map->tx_cfg, TX_CFG_ON_INDEX );
809 }
810 
smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t * dev)811 void smsc9220_enable_mac_xmit( const struct smsc9220_eth_dev_t * dev )
812 {
813     uint32_t mac_cr = 0;
814 
815     smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr );
816 
817     SET_BIT( mac_cr, MAC_REG_CR_TXEN_INDEX );
818 
819     smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr );
820 }
821 
smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t * dev)822 void smsc9220_disable_mac_xmit( const struct smsc9220_eth_dev_t * dev )
823 {
824     uint32_t mac_cr = 0;
825 
826     smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr );
827 
828     CLR_BIT( mac_cr, MAC_REG_CR_TXEN_INDEX );
829 
830     smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr );
831 }
832 
smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t * dev)833 void smsc9220_enable_mac_recv( const struct smsc9220_eth_dev_t * dev )
834 {
835     uint32_t mac_cr = 0;
836 
837     smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr );
838 
839     SET_BIT( mac_cr, MAC_REG_CR_RXEN_INDEX );
840 
841     smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr );
842 }
843 
smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t * dev)844 void smsc9220_disable_mac_recv( const struct smsc9220_eth_dev_t * dev )
845 {
846     uint32_t mac_cr = 0;
847 
848     smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_CR, &mac_cr );
849 
850     CLR_BIT( mac_cr, MAC_REG_CR_RXEN_INDEX );
851 
852     smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_CR, mac_cr );
853 }
854 
smsc9220_check_id(const struct smsc9220_eth_dev_t * dev)855 int smsc9220_check_id( const struct smsc9220_eth_dev_t * dev )
856 {
857     uint32_t id = smsc9220_read_id( dev );
858 
859     return( ( GET_BIT_FIELD( id, CHIP_ID_MASK, CHIP_ID_POS ) == CHIP_ID ) ? 0 : 1 );
860 }
861 
smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t * dev,enum smsc9220_interrupt_source source)862 void smsc9220_enable_interrupt( const struct smsc9220_eth_dev_t * dev,
863                                 enum smsc9220_interrupt_source source )
864 {
865     struct smsc9220_eth_reg_map_t * register_map =
866         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
867 
868     SET_BIT( register_map->irq_enable, source );
869 }
870 
smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t * dev,enum smsc9220_interrupt_source source)871 void smsc9220_disable_interrupt( const struct smsc9220_eth_dev_t * dev,
872                                  enum smsc9220_interrupt_source source )
873 {
874     struct smsc9220_eth_reg_map_t * register_map =
875         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
876 
877     CLR_BIT( register_map->irq_enable, source );
878 }
879 
smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t * dev)880 void smsc9220_disable_all_interrupts( const struct smsc9220_eth_dev_t * dev )
881 {
882     struct smsc9220_eth_reg_map_t * register_map =
883         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
884 
885     register_map->irq_enable = 0;
886 }
887 
smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t * dev,enum smsc9220_interrupt_source source)888 void smsc9220_clear_interrupt( const struct smsc9220_eth_dev_t * dev,
889                                enum smsc9220_interrupt_source source )
890 {
891     struct smsc9220_eth_reg_map_t * register_map =
892         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
893 
894     SET_BIT( register_map->irq_status, source );
895 }
896 
get_irq_status(const struct smsc9220_eth_dev_t * dev)897 uint32_t get_irq_status( const struct smsc9220_eth_dev_t * dev )
898 {
899     struct smsc9220_eth_reg_map_t * register_map =
900         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
901 
902     return register_map->irq_status;
903 }
904 
905 
smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t * dev)906 void smsc9220_clear_all_interrupts( const struct smsc9220_eth_dev_t * dev )
907 {
908     struct smsc9220_eth_reg_map_t * register_map =
909         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
910 
911     register_map->irq_status = UINT32_MAX;
912 }
913 
smsc9220_get_interrupt(const struct smsc9220_eth_dev_t * dev,enum smsc9220_interrupt_source source)914 int smsc9220_get_interrupt( const struct smsc9220_eth_dev_t * dev,
915                             enum smsc9220_interrupt_source source )
916 {
917     struct smsc9220_eth_reg_map_t * register_map =
918         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
919 
920     return GET_BIT( register_map->irq_status, source );
921 }
922 
smsc9220_establish_link(const struct smsc9220_eth_dev_t * dev)923 void smsc9220_establish_link( const struct smsc9220_eth_dev_t * dev )
924 {
925     uint32_t bcr = 0;
926     struct smsc9220_eth_reg_map_t * register_map =
927         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
928 
929     smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_BCTRL, &bcr );
930     SET_BIT( bcr, PHY_REG_BCTRL_AUTO_NEG_EN_INDEX );
931     SET_BIT( bcr, PHY_REG_BCTRL_RST_AUTO_NEG_INDEX );
932     smsc9220_phy_regwrite( dev, SMSC9220_PHY_REG_OFFSET_BCTRL, bcr );
933 
934     SET_BIT( register_map->hw_cfg, HW_CFG_REG_MUST_BE_ONE_INDEX );
935 }
936 
smsc9220_read_mac_address(const struct smsc9220_eth_dev_t * dev,char * mac)937 enum smsc9220_error_t smsc9220_read_mac_address( const struct smsc9220_eth_dev_t * dev,
938                                                  char * mac )
939 {
940     uint32_t mac_low = 0;
941     uint32_t mac_high = 0;
942 
943     if( !mac )
944     {
945         return SMSC9220_ERROR_PARAM;
946     }
947 
948     if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_ADDRH, &mac_high ) )
949     {
950         return SMSC9220_ERROR_INTERNAL;
951     }
952 
953     if( smsc9220_mac_regread( dev, SMSC9220_MAC_REG_OFFSET_ADDRL, &mac_low ) )
954     {
955         return SMSC9220_ERROR_INTERNAL;
956     }
957 
958     mac[ 0 ] = mac_low & 0xFF;
959     mac[ 1 ] = ( mac_low >> 8 ) & 0xFF;
960     mac[ 2 ] = ( mac_low >> 16 ) & 0xFF;
961     mac[ 3 ] = ( mac_low >> 24 ) & 0xFF;
962     mac[ 4 ] = mac_high & 0xFF;
963     mac[ 5 ] = ( mac_high >> 8 ) & 0xFF;
964 
965     return SMSC9220_ERROR_NONE;
966 }
967 
smsc9220_get_tx_data_fifo_size(const struct smsc9220_eth_dev_t * dev)968 uint32_t smsc9220_get_tx_data_fifo_size( const struct smsc9220_eth_dev_t * dev )
969 {
970     struct smsc9220_eth_reg_map_t * register_map =
971         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
972 
973     uint32_t tx_fifo_size =
974         GET_BIT_FIELD( register_map->hw_cfg,
975                        TX_DATA_FIFO_SIZE_KBYTES_MASK,
976                        TX_DATA_FIFO_SIZE_KBYTES_POS ) * KBYTES_TO_BYTES_MULTIPLIER;
977 
978     return( tx_fifo_size - TX_STATUS_FIFO_SIZE_BYTES );
979 }
980 
smsc9220_init(const struct smsc9220_eth_dev_t * dev,void (* wait_ms_function)(uint32_t))981 enum smsc9220_error_t smsc9220_init( const struct smsc9220_eth_dev_t * dev,
982                                      void ( *wait_ms_function )( uint32_t ) )
983 {
984     uint32_t phyreset = 0;
985     enum smsc9220_error_t error = SMSC9220_ERROR_NONE;
986     struct smsc9220_eth_reg_map_t * register_map =
987         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
988 
989     if( !wait_ms_function )
990     {
991         return SMSC9220_ERROR_PARAM;
992     }
993 
994     dev->data->wait_ms = wait_ms_function;
995 
996     error = smsc9220_check_id( dev );
997 
998     if( error != SMSC9220_ERROR_NONE )
999     {
1000         return error;
1001     }
1002 
1003     error = smsc9220_soft_reset( dev );
1004 
1005     if( error != SMSC9220_ERROR_NONE )
1006     {
1007         return error;
1008     }
1009 
1010     smsc9220_set_txfifo( dev, HW_CFG_REG_TX_FIFO_SIZE );
1011 
1012     SET_BIT_FIELD( register_map->afc_cfg, AFC_BACK_DUR_MASK,
1013                    AFC_BACK_DUR_POS, AFC_BACK_DUR );
1014     SET_BIT_FIELD( register_map->afc_cfg, AFC_LOW_LEVEL_MASK,
1015                    AFC_LOW_LEVEL_POS, AFC_LOW_LEVEL );
1016     SET_BIT_FIELD( register_map->afc_cfg, AFC_HIGH_LEVEL_MASK,
1017                    AFC_HIGH_LEVEL_POS, AFC_HIGH_LEVEL );
1018 
1019     error = smsc9220_wait_eeprom( dev );
1020 
1021     if( error != SMSC9220_ERROR_NONE )
1022     {
1023         return error;
1024     }
1025 
1026     /* Configure GPIOs as LED outputs. */
1027     register_map->gpio_cfg = 0;
1028     SET_BIT( register_map->gpio_cfg, GPIO_CFG_GPIO0_PUSHPULL_INDEX );
1029     SET_BIT( register_map->gpio_cfg, GPIO_CFG_GPIO1_PUSHPULL_INDEX );
1030     SET_BIT( register_map->gpio_cfg, GPIO_CFG_GPIO2_PUSHPULL_INDEX );
1031     SET_BIT( register_map->gpio_cfg, GPIO_CFG_GPIO0_LED_INDEX );
1032     SET_BIT( register_map->gpio_cfg, GPIO_CFG_GPIO1_LED_INDEX );
1033     SET_BIT( register_map->gpio_cfg, GPIO_CFG_GPIO2_LED_INDEX );
1034 
1035     smsc9220_init_irqs( dev );
1036 
1037     /* Configure MAC addresses here if needed. */
1038 
1039     error = smsc9220_check_phy( dev );
1040 
1041     if( error != SMSC9220_ERROR_NONE )
1042     {
1043         return error;
1044     }
1045 
1046     error = smsc9220_reset_phy( dev );
1047 
1048     if( error != SMSC9220_ERROR_NONE )
1049     {
1050         return error;
1051     }
1052 
1053     if( dev->data->wait_ms )
1054     {
1055         dev->data->wait_ms( PHY_RESET_TIME_OUT_MS );
1056     }
1057 
1058     /* Checking whether phy reset completed successfully.*/
1059     error = smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_BCTRL,
1060                                   &phyreset );
1061 
1062     if( error != SMSC9220_ERROR_NONE )
1063     {
1064         return error;
1065     }
1066 
1067     if( GET_BIT( phyreset, PHY_REG_BCTRL_RESET_INDEX ) )
1068     {
1069         return SMSC9220_ERROR_INTERNAL;
1070     }
1071 
1072     smsc9220_advertise_cap( dev );
1073     smsc9220_establish_link( dev );
1074 
1075     smsc9220_enable_mac_xmit( dev );
1076     smsc9220_enable_xmit( dev );
1077     smsc9220_enable_mac_recv( dev );
1078 
1079     /* This sleep is compulsory otherwise txmit/receive will fail. */
1080     if( dev->data->wait_ms )
1081     {
1082         dev->data->wait_ms( INIT_FINISH_DELAY );
1083     }
1084 
1085     dev->data->state = 1;
1086 
1087     return SMSC9220_ERROR_NONE;
1088 }
1089 
smsc9220_send_by_chunks(const struct smsc9220_eth_dev_t * dev,uint32_t total_payload_length,bool is_new_packet,const char * data,uint32_t current_size)1090 enum smsc9220_error_t smsc9220_send_by_chunks( const struct smsc9220_eth_dev_t * dev,
1091                                                uint32_t total_payload_length,
1092                                                bool is_new_packet,
1093                                                const char * data,
1094                                                uint32_t current_size )
1095 {
1096     struct smsc9220_eth_reg_map_t * register_map =
1097         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
1098     bool is_first_segment = false;
1099     bool is_last_segment = false;
1100     uint32_t txcmd_a, txcmd_b = 0;
1101     uint32_t tx_buffer_free_space = 0;
1102     volatile uint32_t xmit_stat = 0;
1103 
1104     if( !data )
1105     {
1106         return SMSC9220_ERROR_PARAM;
1107     }
1108 
1109     if( is_new_packet )
1110     {
1111         is_first_segment = true;
1112         dev->data->ongoing_packet_length = total_payload_length;
1113         dev->data->ongoing_packet_length_sent = 0;
1114     }
1115     else if( ( dev->data->ongoing_packet_length != total_payload_length ) ||
1116              ( dev->data->ongoing_packet_length_sent >= total_payload_length ) )
1117     {
1118         return SMSC9220_ERROR_PARAM;
1119     }
1120 
1121     /* Would next chunk fit into buffer? */
1122     tx_buffer_free_space = GET_BIT_FIELD( register_map->tx_fifo_inf,
1123                                           FIFO_USED_SPACE_MASK,
1124                                           DATA_FIFO_USED_SPACE_POS );
1125 
1126     if( current_size > tx_buffer_free_space )
1127     {
1128         return SMSC9220_ERROR_INTERNAL; /* Not enough space in FIFO */
1129     }
1130 
1131     if( ( dev->data->ongoing_packet_length_sent + current_size ) ==
1132         total_payload_length )
1133     {
1134         is_last_segment = true;
1135     }
1136 
1137     txcmd_a = 0;
1138     txcmd_b = 0;
1139 
1140     if( is_last_segment )
1141     {
1142         SET_BIT( txcmd_a, TX_COMMAND_A_LAST_SEGMENT_INDEX );
1143     }
1144 
1145     if( is_first_segment )
1146     {
1147         SET_BIT( txcmd_a, TX_COMMAND_A_FIRST_SEGMENT_INDEX );
1148     }
1149 
1150     uint32_t data_start_offset_bytes = ( 4 - ( current_size % 4 ) );
1151 
1152     SET_BIT_FIELD( txcmd_a, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size );
1153     SET_BIT_FIELD( txcmd_a, TX_CMD_DATA_START_OFFSET_BYTES_MASK,
1154                    TX_CMD_DATA_START_OFFSET_BYTES_POS,
1155                    data_start_offset_bytes );
1156 
1157     SET_BIT_FIELD( txcmd_b, TX_CMD_PKT_LEN_BYTES_MASK, 0, current_size );
1158     SET_BIT_FIELD( txcmd_b, TX_CMD_PKT_TAG_MASK, TX_CMD_PKT_TAG_POS,
1159                    current_size );
1160 
1161     register_map->tx_data_port = txcmd_a;
1162     register_map->tx_data_port = txcmd_b;
1163 
1164     fill_tx_fifo( dev, ( uint8_t * ) data, current_size );
1165 
1166     if( is_last_segment )
1167     {
1168         /* Pop status port for error check */
1169         xmit_stat = register_map->tx_status_port;
1170         ( void ) xmit_stat;
1171     }
1172 
1173     dev->data->ongoing_packet_length_sent += current_size;
1174     return SMSC9220_ERROR_NONE;
1175 }
1176 
smsc9220_get_rxfifo_data_used_space(const struct smsc9220_eth_dev_t * dev)1177 uint32_t smsc9220_get_rxfifo_data_used_space( const struct
1178                                               smsc9220_eth_dev_t * dev )
1179 {
1180     struct smsc9220_eth_reg_map_t * register_map =
1181         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
1182 
1183     return GET_BIT_FIELD( register_map->rx_fifo_inf, FIFO_USED_SPACE_MASK,
1184                           DATA_FIFO_USED_SPACE_POS );
1185 }
1186 
smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t * dev,char * data,uint32_t dlen)1187 uint32_t smsc9220_receive_by_chunks( const struct smsc9220_eth_dev_t * dev,
1188                                      char * data,
1189                                      uint32_t dlen )
1190 {
1191     uint32_t packet_length_byte = 0;
1192 
1193     if( !data )
1194     {
1195         return 0; /* Invalid input parameter, cannot read */
1196     }
1197 
1198     packet_length_byte = dlen; /*_RB_ Hard set to length read from peek register. */
1199     dev->data->current_rx_size_words = packet_length_byte;
1200 
1201     empty_rx_fifo( dev, ( uint8_t * ) data, packet_length_byte );
1202     dev->data->current_rx_size_words = 0;
1203     return packet_length_byte;
1204 }
1205 
smsc9220_peek_next_packet_size(const struct smsc9220_eth_dev_t * dev)1206 uint32_t smsc9220_peek_next_packet_size( const struct
1207                                          smsc9220_eth_dev_t * dev )
1208 {
1209     uint32_t packet_size = 0;
1210     struct smsc9220_eth_reg_map_t * register_map =
1211         ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;
1212     volatile uint32_t rx_status_from_peek = 0;
1213 
1214     if( smsc9220_get_rxfifo_data_used_space( dev ) )
1215     {
1216         rx_status_from_peek = register_map->rx_status_peek;
1217         /* Warning: try reading from port as peek is often zero. */
1218         rx_status_from_peek = register_map->rx_status_port;
1219 
1220         packet_size = GET_BIT_FIELD( rx_status_from_peek,
1221                                      RX_FIFO_STATUS_PKT_LENGTH_MASK,
1222                                      RX_FIFO_STATUS_PKT_LENGTH_POS );
1223     }
1224     else
1225     {
1226         rx_status_from_peek = -1;
1227     }
1228 
1229     return packet_size;
1230 }
1231