summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/icplus.h
blob: 35fa422adf394a80c454f5cdfdc539e774f25a5a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#ifndef _ICPLUS_H
#define _ICPLUS_H

/** @file
 *
 * IC+ network driver
 *
 */

#include <ipxe/nvs.h>
#include <ipxe/mii_bit.h>

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

/** BAR size */
#define ICP_BAR_SIZE 0x200

/** Alignment requirement */
#define ICP_ALIGN 0x8

/** Base address low register offset */
#define ICP_BASE_LO 0x0

/** Base address high register offset */
#define ICP_BASE_HI 0x4

/** ASIC control register (double word) */
#define ICP_ASICCTRL 0x30
#define ICP_ASICCTRL_PHYSPEED1000	0x00000040UL	/**< PHY speed 1000 */
#define ICP_ASICCTRL_GLOBALRESET	0x00010000UL	/**< Global reset */
#define ICP_ASICCTRL_DMA		0x00080000UL	/**< DMA */
#define ICP_ASICCTRL_FIFO		0x00100000UL	/**< FIFO */
#define ICP_ASICCTRL_NETWORK		0x00200000UL	/**< Network */
#define ICP_ASICCTRL_HOST		0x00400000UL	/**< Host */
#define ICP_ASICCTRL_AUTOINIT		0x00800000UL	/**< Auto init */
#define ICP_ASICCTRL_RESETBUSY		0x04000000UL	/**< Reset busy */

/** Maximum time to wait for reset */
#define ICP_RESET_MAX_WAIT_MS 1000

/** DMA control register (word/double word) */
#define ICP_DMACTRL 0x00
#define ICP_DMACTRL_RXPOLLNOW		0x0010		/**< Receive poll now */
#define ICP_DMACTRL_TXPOLLNOW 		0x1000		/**< Transmit poll now */

/** EEPROM control register (word) */
#define ICP_EEPROMCTRL 0x4a
#define ICP_EEPROMCTRL_ADDRESS( x )	( (x) << 0 )	/**< Address */
#define ICP_EEPROMCTRL_OPCODE( x )	( (x) << 8 )	/**< Opcode */
#define ICP_EEPROMCTRL_OPCODE_READ \
	ICP_EEPROMCTRL_OPCODE ( 2 )			/**< Read register */
#define ICP_EEPROMCTRL_BUSY		0x8000		/**< EEPROM busy */

/** Maximum time to wait for reading EEPROM */
#define ICP_EEPROM_MAX_WAIT_MS 1000

/** EEPROM word length */
#define ICP_EEPROM_WORD_LEN_LOG2 1

/** Minimum EEPROM size, in words */
#define ICP_EEPROM_MIN_SIZE_WORDS 0x20

/** Address of MAC address within EEPROM */
#define ICP_EEPROM_MAC 0x10

/** EEPROM data register (word) */
#define ICP_EEPROMDATA 0x48

/** Interupt status register (word) */
#define ICP_INTSTATUS 0x5e
#define ICP_INTSTATUS_TXCOMPLETE	0x0004		/**< TX complete */
#define ICP_INTSTATUS_LINKEVENT		0x0100		/**< Link event */
#define ICP_INTSTATUS_RXDMACOMPLETE	0x0400		/**< RX DMA complete */

/** MAC control register (double word) */
#define ICP_MACCTRL 0x6c
#define ICP_MACCTRL_DUPLEX		0x00000020UL	/**< Duplex select */
#define ICP_MACCTRL_TXENABLE		0x01000000UL	/**< TX enable */
#define ICP_MACCTRL_TXDISABLE		0x02000000UL	/**< TX disable */
#define ICP_MACCTRL_RXENABLE		0x08000000UL	/**< RX enable */
#define ICP_MACCTRL_RXDISABLE		0x10000000UL	/**< RX disable */

/** PHY control register (byte) */
#define ICP_PHYCTRL 0x76
#define ICP_PHYCTRL_MGMTCLK		0x01		/**< Management clock */
#define ICP_PHYCTRL_MGMTDATA		0x02		/**< Management data */
#define ICP_PHYCTRL_MGMTDIR		0x04		/**< Management direction */
#define ICP_PHYCTRL_LINKSPEED		0xc0		/**< Link speed */

/** Receive mode register (word) */
#define ICP_RXMODE 0x88
#define ICP_RXMODE_UNICAST		0x0001		/**< Receive unicast */
#define ICP_RXMODE_MULTICAST		0x0002		/**< Receice multicast */
#define ICP_RXMODE_BROADCAST		0x0004		/**< Receive broadcast */
#define ICP_RXMODE_ALLFRAMES		0x0008		/**< Receive all frames */

/** List pointer receive register */
#define ICP_RFDLISTPTR 0x1c

/** List pointer transmit register */
#define ICP_TFDLISTPTR 0x10

/** Transmit status register */
#define ICP_TXSTATUS 0x60
#define ICP_TXSTATUS_ERROR		0x00000001UL	/**< TX error */

/** Data fragment */
union icplus_fragment {
	/** Address of data */
	uint64_t address;
	/** Length */
	struct {
		/** Reserved */
		uint8_t reserved[6];
		/** Length of data */
		uint16_t len;
	};
};

/** Transmit or receive descriptor */
struct icplus_descriptor {
	/** Address of next descriptor */
	uint64_t next;
	/** Actual length */
	uint16_t len;
	/** Flags */
	uint8_t flags;
	/** Control */
	uint8_t control;
	/** VLAN */
	uint16_t vlan;
	/** Reserved */
	uint16_t reserved_a;
	/** Data buffer */
	union icplus_fragment data;
	/** Reserved */
	uint8_t reserved_b[8];
};

/** Descriptor complete */
#define ICP_DONE 0x80

/** Transmit alignment disabled */
#define ICP_TX_UNALIGN 0x01

/** Request transmit completion */
#define ICP_TX_INDICATE 0x40

/** Sole transmit fragment */
#define ICP_TX_SOLE_FRAG 0x01

/** Recieve frame overrun error */
#define ICP_RX_ERR_OVERRUN 0x01

/** Receive runt frame error */
#define ICP_RX_ERR_RUNT 0x02

/** Receive alignment error */
#define ICP_RX_ERR_ALIGN 0x04

/** Receive FCS error */
#define ICP_RX_ERR_FCS 0x08

/** Receive oversized frame error */
#define ICP_RX_ERR_OVERSIZED 0x10

/** Recieve length error */
#define ICP_RX_ERR_LEN 0x20

/** Descriptor ring */
struct icplus_ring {
	/** Producer counter */
	unsigned int prod;
	/** Consumer counter */
	unsigned int cons;
	/** Ring entries */
	struct icplus_descriptor *entry;
	/* List pointer register */
	unsigned int listptr;
};

/** Number of descriptors */
#define ICP_NUM_DESC 4

/** Maximum receive packet length */
#define ICP_RX_MAX_LEN ETH_FRAME_LEN

/** An IC+ network card */
struct icplus_nic {
	/** Registers */
	void *regs;
	/** EEPROM */
	struct nvs_device eeprom;
	/** MII bit bashing interface */
	struct mii_bit_basher miibit;
	/** MII device */
	struct mii_device mii;
	/** Transmit descriptor ring */
	struct icplus_ring tx;
	/** Receive descriptor ring */
	struct icplus_ring rx;
	/** Receive I/O buffers */
	struct io_buffer *rx_iobuf[ICP_NUM_DESC];
};

#endif /* _ICPLUS_H */