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