123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- #ifndef _SMSCUSB_H
- #define _SMSCUSB_H
-
- /** @file
- *
- * SMSC USB Ethernet drivers
- *
- */
-
- FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
- #include <stdint.h>
- #include <string.h>
- #include <byteswap.h>
- #include <ipxe/usb.h>
- #include <ipxe/usbnet.h>
- #include <ipxe/netdevice.h>
- #include <ipxe/mii.h>
- #include <ipxe/if_ether.h>
-
- /** Register write command */
- #define SMSCUSB_REGISTER_WRITE \
- ( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
- USB_REQUEST_TYPE ( 0xa0 ) )
-
- /** Register read command */
- #define SMSCUSB_REGISTER_READ \
- ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
- USB_REQUEST_TYPE ( 0xa1 ) )
-
- /** Get statistics command */
- #define SMSCUSB_GET_STATISTICS \
- ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
- USB_REQUEST_TYPE ( 0xa2 ) )
-
- /** EEPROM command register offset */
- #define SMSCUSB_E2P_CMD 0x000
- #define SMSCUSB_E2P_CMD_EPC_BSY 0x80000000UL /**< EPC busy */
- #define SMSCUSB_E2P_CMD_EPC_CMD_READ 0x00000000UL /**< READ command */
- #define SMSCUSB_E2P_CMD_EPC_ADDR(addr) ( (addr) << 0 ) /**< EPC address */
-
- /** EEPROM data register offset */
- #define SMSCUSB_E2P_DATA 0x004
- #define SMSCUSB_E2P_DATA_GET(e2p_data) \
- ( ( (e2p_data) >> 0 ) & 0xff ) /**< EEPROM data */
-
- /** MAC address EEPROM address */
- #define SMSCUSB_EEPROM_MAC 0x01
-
- /** Maximum time to wait for EEPROM (in milliseconds) */
- #define SMSCUSB_EEPROM_MAX_WAIT_MS 100
-
- /** OTP power register offset */
- #define SMSCUSB_OTP_POWER 0x000
- #define SMSCUSB_OTP_POWER_DOWN 0x00000001UL /**< OTP power down */
-
- /** OTP address high byte register offset */
- #define SMSCUSB_OTP_ADDRH 0x004
-
- /** OTP address low byte register offset */
- #define SMSCUSB_OTP_ADDRL 0x008
-
- /** OTP data register offset */
- #define SMSCUSB_OTP_DATA 0x018
- #define SMSCUSB_OTP_DATA_GET(otp_data) \
- ( ( (otp_data) >> 0 ) & 0xff ) /**< OTP data */
-
- /** OTP command selection register offset */
- #define SMSCUSB_OTP_CMD 0x020
- #define SMSCUSB_OTP_CMD_READ 0x00000001UL /**< Read command */
-
- /** OTP command initiation register offset */
- #define SMSCUSB_OTP_GO 0x028
- #define SMSCUSB_OTP_GO_GO 0x00000001UL /**< Initiate command */
-
- /** OTP status register offset */
- #define SMSCUSB_OTP_STATUS 0x030
- #define SMSCUSB_OTP_STATUS_BUSY 0x00000001UL /**< OTP busy */
-
- /** Maximum time to wait for OTP (in milliseconds) */
- #define SMSCUSB_OTP_MAX_WAIT_MS 100
-
- /** OTP layout 1 signature */
- #define SMSCUSB_OTP_1_SIG 0xf3
-
- /** OTP layout 1 MAC address offset */
- #define SMSCUSB_OTP_1_MAC 0x001
-
- /** OTP layout 2 signature */
- #define SMSCUSB_OTP_2_SIG 0xf7
-
- /** OTP layout 2 MAC address offset */
- #define SMSCUSB_OTP_2_MAC 0x101
-
- /** MII access register offset */
- #define SMSCUSB_MII_ACCESS 0x000
- #define SMSCUSB_MII_ACCESS_PHY_ADDRESS 0x00000800UL /**< PHY address */
- #define SMSCUSB_MII_ACCESS_MIIRINDA(addr) ( (addr) << 6 ) /**< MII register */
- #define SMSCUSB_MII_ACCESS_MIIWNR 0x00000002UL /**< MII write */
- #define SMSCUSB_MII_ACCESS_MIIBZY 0x00000001UL /**< MII busy */
-
- /** MII data register offset */
- #define SMSCUSB_MII_DATA 0x004
- #define SMSCUSB_MII_DATA_SET(data) ( (data) << 0 ) /**< Set data */
- #define SMSCUSB_MII_DATA_GET(mii_data) \
- ( ( (mii_data) >> 0 ) & 0xffff ) /**< Get data */
-
- /** Maximum time to wait for MII (in milliseconds) */
- #define SMSCUSB_MII_MAX_WAIT_MS 100
-
- /** MAC address */
- union smscusb_mac {
- /** MAC receive address registers */
- struct {
- /** MAC receive address low register */
- uint32_t l;
- /** MAC receive address high register */
- uint32_t h;
- } __attribute__ (( packed )) addr;
- /** Raw MAC address */
- uint8_t raw[ETH_ALEN];
- };
-
- /** MAC receive address high register offset */
- #define SMSCUSB_RX_ADDRH 0x000
-
- /** MAC receive address low register offset */
- #define SMSCUSB_RX_ADDRL 0x004
-
- /** MAC address perfect filter N high register offset */
- #define SMSCUSB_ADDR_FILTH(n) ( 0x000 + ( 8 * (n) ) )
- #define SMSCUSB_ADDR_FILTH_VALID 0x80000000UL /**< Address valid */
-
- /** MAC address perfect filter N low register offset */
- #define SMSCUSB_ADDR_FILTL(n) ( 0x004 + ( 8 * (n) ) )
-
- /** Interrupt packet format */
- struct smscusb_interrupt {
- /** Current value of INT_STS register */
- uint32_t int_sts;
- } __attribute__ (( packed ));
-
- /** An SMSC USB device */
- struct smscusb_device {
- /** USB device */
- struct usb_device *usb;
- /** USB bus */
- struct usb_bus *bus;
- /** Network device */
- struct net_device *netdev;
- /** USB network device */
- struct usbnet_device usbnet;
- /** MII interface */
- struct mii_interface mdio;
- /** MII device */
- struct mii_device mii;
- /** MII register base */
- uint16_t mii_base;
- /** PHY interrupt source register */
- uint16_t phy_source;
- /** Interrupt status */
- uint32_t int_sts;
- };
-
- extern int smscusb_raw_writel ( struct smscusb_device *smscusb,
- unsigned int address, uint32_t value );
- extern int smscusb_raw_readl ( struct smscusb_device *smscusb,
- unsigned int address, uint32_t *value );
-
- /**
- * Write register
- *
- * @v smscusb SMSC USB device
- * @v address Register address
- * @v value Register value
- * @ret rc Return status code
- */
- static inline __attribute__ (( always_inline )) int
- smscusb_writel ( struct smscusb_device *smscusb, unsigned int address,
- uint32_t value ) {
- int rc;
-
- /* Write register */
- if ( ( rc = smscusb_raw_writel ( smscusb, address,
- cpu_to_le32 ( value ) ) ) != 0 )
- return rc;
-
- return 0;
- }
-
- /**
- * Read register
- *
- * @v smscusb SMSC USB device
- * @v address Register address
- * @ret value Register value
- * @ret rc Return status code
- */
- static inline __attribute__ (( always_inline )) int
- smscusb_readl ( struct smscusb_device *smscusb, unsigned int address,
- uint32_t *value ) {
- int rc;
-
- /* Read register */
- if ( ( rc = smscusb_raw_readl ( smscusb, address, value ) ) != 0 )
- return rc;
- le32_to_cpus ( value );
-
- return 0;
- }
-
- /**
- * Get statistics
- *
- * @v smscusb SMSC USB device
- * @v index Statistics set index
- * @v data Statistics data to fill in
- * @v len Length of statistics data
- * @ret rc Return status code
- */
- static inline __attribute__ (( always_inline )) int
- smscusb_get_statistics ( struct smscusb_device *smscusb, unsigned int index,
- void *data, size_t len ) {
- int rc;
-
- /* Read statistics */
- if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_GET_STATISTICS, 0,
- index, data, len ) ) != 0 ) {
- DBGC ( smscusb, "SMSCUSB %p could not get statistics set %d: "
- "%s\n", smscusb, index, strerror ( rc ) );
- return rc;
- }
-
- return 0;
- }
-
- /** Interrupt maximum fill level
- *
- * This is a policy decision.
- */
- #define SMSCUSB_INTR_MAX_FILL 2
-
- extern struct usb_endpoint_driver_operations smscusb_intr_operations;
- extern struct usb_endpoint_driver_operations smscusb_out_operations;
- extern struct mii_operations smscusb_mii_operations;
-
- /**
- * Initialise SMSC USB device
- *
- * @v smscusb SMSC USB device
- * @v netdev Network device
- * @v func USB function
- * @v in Bulk IN endpoint operations
- */
- static inline __attribute__ (( always_inline )) void
- smscusb_init ( struct smscusb_device *smscusb, struct net_device *netdev,
- struct usb_function *func,
- struct usb_endpoint_driver_operations *in ) {
- struct usb_device *usb = func->usb;
-
- smscusb->usb = usb;
- smscusb->bus = usb->port->hub->bus;
- smscusb->netdev = netdev;
- usbnet_init ( &smscusb->usbnet, func, &smscusb_intr_operations, in,
- &smscusb_out_operations );
- usb_refill_init ( &smscusb->usbnet.intr, 0, 0, SMSCUSB_INTR_MAX_FILL );
- }
-
- /**
- * Initialise SMSC USB device MII interface
- *
- * @v smscusb SMSC USB device
- * @v mii_base MII register base
- * @v phy_source Interrupt source PHY register
- */
- static inline __attribute__ (( always_inline )) void
- smscusb_mii_init ( struct smscusb_device *smscusb, unsigned int mii_base,
- unsigned int phy_source ) {
-
- mdio_init ( &smscusb->mdio, &smscusb_mii_operations );
- mii_init ( &smscusb->mii, &smscusb->mdio, 0 );
- smscusb->mii_base = mii_base;
- smscusb->phy_source = phy_source;
- }
-
- extern int smscusb_eeprom_fetch_mac ( struct smscusb_device *smscusb,
- unsigned int e2p_base );
- extern int smscusb_otp_fetch_mac ( struct smscusb_device *smscusb,
- unsigned int otp_base );
- extern int smscusb_fdt_fetch_mac ( struct smscusb_device *smscusb );
- extern int smscusb_mii_check_link ( struct smscusb_device *smscusb );
- extern int smscusb_mii_open ( struct smscusb_device *smscusb,
- unsigned int phy_mask, unsigned int intrs );
- extern int smscusb_set_address ( struct smscusb_device *smscusb,
- unsigned int addr_base );
- extern int smscusb_set_filter ( struct smscusb_device *smscusb,
- unsigned int filt_base );
-
- #endif /* _SMSCUSB_H */
|