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