[smscusb] Fetch MAC from device tree for Raspberry Pi Model B+
[ipxe.git] / src / drivers / net / smscusb.h
1 #ifndef _SMSCUSB_H
2 #define _SMSCUSB_H
3
4 /** @file
5 *
6 * SMSC USB Ethernet drivers
7 *
8 */
9
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
12 #include <stdint.h>
13 #include <string.h>
14 #include <byteswap.h>
15 #include <ipxe/usb.h>
16 #include <ipxe/usbnet.h>
17 #include <ipxe/netdevice.h>
18 #include <ipxe/mii.h>
19 #include <ipxe/if_ether.h>
20
21 /** Register write command */
22 #define SMSCUSB_REGISTER_WRITE \
23 ( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
24 USB_REQUEST_TYPE ( 0xa0 ) )
25
26 /** Register read command */
27 #define SMSCUSB_REGISTER_READ \
28 ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
29 USB_REQUEST_TYPE ( 0xa1 ) )
30
31 /** Get statistics command */
32 #define SMSCUSB_GET_STATISTICS \
33 ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
34 USB_REQUEST_TYPE ( 0xa2 ) )
35
36 /** EEPROM command register offset */
37 #define SMSCUSB_E2P_CMD 0x000
38 #define SMSCUSB_E2P_CMD_EPC_BSY 0x80000000UL /**< EPC busy */
39 #define SMSCUSB_E2P_CMD_EPC_CMD_READ 0x00000000UL /**< READ command */
40 #define SMSCUSB_E2P_CMD_EPC_ADDR(addr) ( (addr) << 0 ) /**< EPC address */
41
42 /** EEPROM data register offset */
43 #define SMSCUSB_E2P_DATA 0x004
44 #define SMSCUSB_E2P_DATA_GET(e2p_data) \
45 ( ( (e2p_data) >> 0 ) & 0xff ) /**< EEPROM data */
46
47 /** MAC address EEPROM address */
48 #define SMSCUSB_EEPROM_MAC 0x01
49
50 /** Maximum time to wait for EEPROM (in milliseconds) */
51 #define SMSCUSB_EEPROM_MAX_WAIT_MS 100
52
53 /** OTP power register offset */
54 #define SMSCUSB_OTP_POWER 0x000
55 #define SMSCUSB_OTP_POWER_DOWN 0x00000001UL /**< OTP power down */
56
57 /** OTP address high byte register offset */
58 #define SMSCUSB_OTP_ADDRH 0x004
59
60 /** OTP address low byte register offset */
61 #define SMSCUSB_OTP_ADDRL 0x008
62
63 /** OTP data register offset */
64 #define SMSCUSB_OTP_DATA 0x018
65 #define SMSCUSB_OTP_DATA_GET(otp_data) \
66 ( ( (otp_data) >> 0 ) & 0xff ) /**< OTP data */
67
68 /** OTP command selection register offset */
69 #define SMSCUSB_OTP_CMD 0x020
70 #define SMSCUSB_OTP_CMD_READ 0x00000001UL /**< Read command */
71
72 /** OTP command initiation register offset */
73 #define SMSCUSB_OTP_GO 0x028
74 #define SMSCUSB_OTP_GO_GO 0x00000001UL /**< Initiate command */
75
76 /** OTP status register offset */
77 #define SMSCUSB_OTP_STATUS 0x030
78 #define SMSCUSB_OTP_STATUS_BUSY 0x00000001UL /**< OTP busy */
79
80 /** Maximum time to wait for OTP (in milliseconds) */
81 #define SMSCUSB_OTP_MAX_WAIT_MS 100
82
83 /** OTP layout 1 signature */
84 #define SMSCUSB_OTP_1_SIG 0xf3
85
86 /** OTP layout 1 MAC address offset */
87 #define SMSCUSB_OTP_1_MAC 0x001
88
89 /** OTP layout 2 signature */
90 #define SMSCUSB_OTP_2_SIG 0xf7
91
92 /** OTP layout 2 MAC address offset */
93 #define SMSCUSB_OTP_2_MAC 0x101
94
95 /** MII access register offset */
96 #define SMSCUSB_MII_ACCESS 0x000
97 #define SMSCUSB_MII_ACCESS_PHY_ADDRESS 0x00000800UL /**< PHY address */
98 #define SMSCUSB_MII_ACCESS_MIIRINDA(addr) ( (addr) << 6 ) /**< MII register */
99 #define SMSCUSB_MII_ACCESS_MIIWNR 0x00000002UL /**< MII write */
100 #define SMSCUSB_MII_ACCESS_MIIBZY 0x00000001UL /**< MII busy */
101
102 /** MII data register offset */
103 #define SMSCUSB_MII_DATA 0x004
104 #define SMSCUSB_MII_DATA_SET(data) ( (data) << 0 ) /**< Set data */
105 #define SMSCUSB_MII_DATA_GET(mii_data) \
106 ( ( (mii_data) >> 0 ) & 0xffff ) /**< Get data */
107
108 /** Maximum time to wait for MII (in milliseconds) */
109 #define SMSCUSB_MII_MAX_WAIT_MS 100
110
111 /** MAC address */
112 union smscusb_mac {
113 /** MAC receive address registers */
114 struct {
115 /** MAC receive address low register */
116 uint32_t l;
117 /** MAC receive address high register */
118 uint32_t h;
119 } __attribute__ (( packed )) addr;
120 /** Raw MAC address */
121 uint8_t raw[ETH_ALEN];
122 };
123
124 /** MAC receive address high register offset */
125 #define SMSCUSB_RX_ADDRH 0x000
126
127 /** MAC receive address low register offset */
128 #define SMSCUSB_RX_ADDRL 0x004
129
130 /** MAC address perfect filter N high register offset */
131 #define SMSCUSB_ADDR_FILTH(n) ( 0x000 + ( 8 * (n) ) )
132 #define SMSCUSB_ADDR_FILTH_VALID 0x80000000UL /**< Address valid */
133
134 /** MAC address perfect filter N low register offset */
135 #define SMSCUSB_ADDR_FILTL(n) ( 0x004 + ( 8 * (n) ) )
136
137 /** Interrupt packet format */
138 struct smscusb_interrupt {
139 /** Current value of INT_STS register */
140 uint32_t int_sts;
141 } __attribute__ (( packed ));
142
143 /** An SMSC USB device */
144 struct smscusb_device {
145 /** USB device */
146 struct usb_device *usb;
147 /** USB bus */
148 struct usb_bus *bus;
149 /** Network device */
150 struct net_device *netdev;
151 /** USB network device */
152 struct usbnet_device usbnet;
153 /** MII interface */
154 struct mii_interface mdio;
155 /** MII device */
156 struct mii_device mii;
157 /** MII register base */
158 uint16_t mii_base;
159 /** PHY interrupt source register */
160 uint16_t phy_source;
161 /** Interrupt status */
162 uint32_t int_sts;
163 };
164
165 extern int smscusb_raw_writel ( struct smscusb_device *smscusb,
166 unsigned int address, uint32_t value );
167 extern int smscusb_raw_readl ( struct smscusb_device *smscusb,
168 unsigned int address, uint32_t *value );
169
170 /**
171 * Write register
172 *
173 * @v smscusb SMSC USB device
174 * @v address Register address
175 * @v value Register value
176 * @ret rc Return status code
177 */
178 static inline __attribute__ (( always_inline )) int
179 smscusb_writel ( struct smscusb_device *smscusb, unsigned int address,
180 uint32_t value ) {
181 int rc;
182
183 /* Write register */
184 if ( ( rc = smscusb_raw_writel ( smscusb, address,
185 cpu_to_le32 ( value ) ) ) != 0 )
186 return rc;
187
188 return 0;
189 }
190
191 /**
192 * Read register
193 *
194 * @v smscusb SMSC USB device
195 * @v address Register address
196 * @ret value Register value
197 * @ret rc Return status code
198 */
199 static inline __attribute__ (( always_inline )) int
200 smscusb_readl ( struct smscusb_device *smscusb, unsigned int address,
201 uint32_t *value ) {
202 int rc;
203
204 /* Read register */
205 if ( ( rc = smscusb_raw_readl ( smscusb, address, value ) ) != 0 )
206 return rc;
207 le32_to_cpus ( value );
208
209 return 0;
210 }
211
212 /**
213 * Get statistics
214 *
215 * @v smscusb SMSC USB device
216 * @v index Statistics set index
217 * @v data Statistics data to fill in
218 * @v len Length of statistics data
219 * @ret rc Return status code
220 */
221 static inline __attribute__ (( always_inline )) int
222 smscusb_get_statistics ( struct smscusb_device *smscusb, unsigned int index,
223 void *data, size_t len ) {
224 int rc;
225
226 /* Read statistics */
227 if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_GET_STATISTICS, 0,
228 index, data, len ) ) != 0 ) {
229 DBGC ( smscusb, "SMSCUSB %p could not get statistics set %d: "
230 "%s\n", smscusb, index, strerror ( rc ) );
231 return rc;
232 }
233
234 return 0;
235 }
236
237 /** Interrupt maximum fill level
238 *
239 * This is a policy decision.
240 */
241 #define SMSCUSB_INTR_MAX_FILL 2
242
243 extern struct usb_endpoint_driver_operations smscusb_intr_operations;
244 extern struct usb_endpoint_driver_operations smscusb_out_operations;
245 extern struct mii_operations smscusb_mii_operations;
246
247 /**
248 * Initialise SMSC USB device
249 *
250 * @v smscusb SMSC USB device
251 * @v netdev Network device
252 * @v func USB function
253 * @v in Bulk IN endpoint operations
254 */
255 static inline __attribute__ (( always_inline )) void
256 smscusb_init ( struct smscusb_device *smscusb, struct net_device *netdev,
257 struct usb_function *func,
258 struct usb_endpoint_driver_operations *in ) {
259 struct usb_device *usb = func->usb;
260
261 smscusb->usb = usb;
262 smscusb->bus = usb->port->hub->bus;
263 smscusb->netdev = netdev;
264 usbnet_init ( &smscusb->usbnet, func, &smscusb_intr_operations, in,
265 &smscusb_out_operations );
266 usb_refill_init ( &smscusb->usbnet.intr, 0, 0, SMSCUSB_INTR_MAX_FILL );
267 }
268
269 /**
270 * Initialise SMSC USB device MII interface
271 *
272 * @v smscusb SMSC USB device
273 * @v mii_base MII register base
274 * @v phy_source Interrupt source PHY register
275 */
276 static inline __attribute__ (( always_inline )) void
277 smscusb_mii_init ( struct smscusb_device *smscusb, unsigned int mii_base,
278 unsigned int phy_source ) {
279
280 mdio_init ( &smscusb->mdio, &smscusb_mii_operations );
281 mii_init ( &smscusb->mii, &smscusb->mdio, 0 );
282 smscusb->mii_base = mii_base;
283 smscusb->phy_source = phy_source;
284 }
285
286 extern int smscusb_eeprom_fetch_mac ( struct smscusb_device *smscusb,
287 unsigned int e2p_base );
288 extern int smscusb_otp_fetch_mac ( struct smscusb_device *smscusb,
289 unsigned int otp_base );
290 extern int smscusb_fdt_fetch_mac ( struct smscusb_device *smscusb );
291 extern int smscusb_mii_check_link ( struct smscusb_device *smscusb );
292 extern int smscusb_mii_open ( struct smscusb_device *smscusb,
293 unsigned int phy_mask, unsigned int intrs );
294 extern int smscusb_set_address ( struct smscusb_device *smscusb,
295 unsigned int addr_base );
296 extern int smscusb_set_filter ( struct smscusb_device *smscusb,
297 unsigned int filt_base );
298
299 #endif /* _SMSCUSB_H */