1 | // SPDX-License-Identifier: BSD-3-Clause |
2 | /* Copyright 2016-2018 NXP |
3 | * Copyright (c) 2018, Sensor-Technik Wiedemann GmbH |
4 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
5 | */ |
6 | #include <linux/spi/spi.h> |
7 | #include <linux/packing.h> |
8 | #include "sja1105.h" |
9 | |
10 | struct sja1105_chunk { |
11 | u8 *buf; |
12 | size_t len; |
13 | u64 reg_addr; |
14 | }; |
15 | |
16 | static void |
17 | sja1105_spi_message_pack(void *buf, const struct sja1105_spi_message *msg) |
18 | { |
19 | const int size = SJA1105_SIZE_SPI_MSG_HEADER; |
20 | |
21 | memset(buf, 0, size); |
22 | |
23 | sja1105_pack(buf, val: &msg->access, start: 31, end: 31, len: size); |
24 | sja1105_pack(buf, val: &msg->read_count, start: 30, end: 25, len: size); |
25 | sja1105_pack(buf, val: &msg->address, start: 24, end: 4, len: size); |
26 | } |
27 | |
28 | /* If @rw is: |
29 | * - SPI_WRITE: creates and sends an SPI write message at absolute |
30 | * address reg_addr, taking @len bytes from *buf |
31 | * - SPI_READ: creates and sends an SPI read message from absolute |
32 | * address reg_addr, writing @len bytes into *buf |
33 | */ |
34 | static int sja1105_xfer(const struct sja1105_private *priv, |
35 | sja1105_spi_rw_mode_t rw, u64 reg_addr, u8 *buf, |
36 | size_t len, struct ptp_system_timestamp *ptp_sts) |
37 | { |
38 | u8 hdr_buf[SJA1105_SIZE_SPI_MSG_HEADER] = {0}; |
39 | struct spi_device *spi = priv->spidev; |
40 | struct spi_transfer xfers[2] = {0}; |
41 | struct spi_transfer *chunk_xfer; |
42 | struct spi_transfer *hdr_xfer; |
43 | struct sja1105_chunk chunk; |
44 | int num_chunks; |
45 | int rc, i = 0; |
46 | |
47 | num_chunks = DIV_ROUND_UP(len, priv->max_xfer_len); |
48 | |
49 | chunk.reg_addr = reg_addr; |
50 | chunk.buf = buf; |
51 | chunk.len = min_t(size_t, len, priv->max_xfer_len); |
52 | |
53 | hdr_xfer = &xfers[0]; |
54 | chunk_xfer = &xfers[1]; |
55 | |
56 | for (i = 0; i < num_chunks; i++) { |
57 | struct spi_transfer *ptp_sts_xfer; |
58 | struct sja1105_spi_message msg; |
59 | |
60 | /* Populate the transfer's header buffer */ |
61 | msg.address = chunk.reg_addr; |
62 | msg.access = rw; |
63 | if (rw == SPI_READ) |
64 | msg.read_count = chunk.len / 4; |
65 | else |
66 | /* Ignored */ |
67 | msg.read_count = 0; |
68 | sja1105_spi_message_pack(buf: hdr_buf, msg: &msg); |
69 | hdr_xfer->tx_buf = hdr_buf; |
70 | hdr_xfer->len = SJA1105_SIZE_SPI_MSG_HEADER; |
71 | |
72 | /* Populate the transfer's data buffer */ |
73 | if (rw == SPI_READ) |
74 | chunk_xfer->rx_buf = chunk.buf; |
75 | else |
76 | chunk_xfer->tx_buf = chunk.buf; |
77 | chunk_xfer->len = chunk.len; |
78 | |
79 | /* Request timestamping for the transfer. Instead of letting |
80 | * callers specify which byte they want to timestamp, we can |
81 | * make certain assumptions: |
82 | * - A read operation will request a software timestamp when |
83 | * what's being read is the PTP time. That is snapshotted by |
84 | * the switch hardware at the end of the command portion |
85 | * (hdr_xfer). |
86 | * - A write operation will request a software timestamp on |
87 | * actions that modify the PTP time. Taking clock stepping as |
88 | * an example, the switch writes the PTP time at the end of |
89 | * the data portion (chunk_xfer). |
90 | */ |
91 | if (rw == SPI_READ) |
92 | ptp_sts_xfer = hdr_xfer; |
93 | else |
94 | ptp_sts_xfer = chunk_xfer; |
95 | ptp_sts_xfer->ptp_sts_word_pre = ptp_sts_xfer->len - 1; |
96 | ptp_sts_xfer->ptp_sts_word_post = ptp_sts_xfer->len - 1; |
97 | ptp_sts_xfer->ptp_sts = ptp_sts; |
98 | |
99 | /* Calculate next chunk */ |
100 | chunk.buf += chunk.len; |
101 | chunk.reg_addr += chunk.len / 4; |
102 | chunk.len = min_t(size_t, (ptrdiff_t)(buf + len - chunk.buf), |
103 | priv->max_xfer_len); |
104 | |
105 | rc = spi_sync_transfer(spi, xfers, num_xfers: 2); |
106 | if (rc < 0) { |
107 | dev_err(&spi->dev, "SPI transfer failed: %d\n" , rc); |
108 | return rc; |
109 | } |
110 | } |
111 | |
112 | return 0; |
113 | } |
114 | |
115 | int sja1105_xfer_buf(const struct sja1105_private *priv, |
116 | sja1105_spi_rw_mode_t rw, u64 reg_addr, |
117 | u8 *buf, size_t len) |
118 | { |
119 | return sja1105_xfer(priv, rw, reg_addr, buf, len, NULL); |
120 | } |
121 | |
122 | /* If @rw is: |
123 | * - SPI_WRITE: creates and sends an SPI write message at absolute |
124 | * address reg_addr |
125 | * - SPI_READ: creates and sends an SPI read message from absolute |
126 | * address reg_addr |
127 | * |
128 | * The u64 *value is unpacked, meaning that it's stored in the native |
129 | * CPU endianness and directly usable by software running on the core. |
130 | */ |
131 | int sja1105_xfer_u64(const struct sja1105_private *priv, |
132 | sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value, |
133 | struct ptp_system_timestamp *ptp_sts) |
134 | { |
135 | u8 packed_buf[8]; |
136 | int rc; |
137 | |
138 | if (rw == SPI_WRITE) |
139 | sja1105_pack(buf: packed_buf, val: value, start: 63, end: 0, len: 8); |
140 | |
141 | rc = sja1105_xfer(priv, rw, reg_addr, buf: packed_buf, len: 8, ptp_sts); |
142 | |
143 | if (rw == SPI_READ) |
144 | sja1105_unpack(buf: packed_buf, val: value, start: 63, end: 0, len: 8); |
145 | |
146 | return rc; |
147 | } |
148 | |
149 | /* Same as above, but transfers only a 4 byte word */ |
150 | int sja1105_xfer_u32(const struct sja1105_private *priv, |
151 | sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value, |
152 | struct ptp_system_timestamp *ptp_sts) |
153 | { |
154 | u8 packed_buf[4]; |
155 | u64 tmp; |
156 | int rc; |
157 | |
158 | if (rw == SPI_WRITE) { |
159 | /* The packing API only supports u64 as CPU word size, |
160 | * so we need to convert. |
161 | */ |
162 | tmp = *value; |
163 | sja1105_pack(buf: packed_buf, val: &tmp, start: 31, end: 0, len: 4); |
164 | } |
165 | |
166 | rc = sja1105_xfer(priv, rw, reg_addr, buf: packed_buf, len: 4, ptp_sts); |
167 | |
168 | if (rw == SPI_READ) { |
169 | sja1105_unpack(buf: packed_buf, val: &tmp, start: 31, end: 0, len: 4); |
170 | *value = tmp; |
171 | } |
172 | |
173 | return rc; |
174 | } |
175 | |
176 | static int sja1105et_reset_cmd(struct dsa_switch *ds) |
177 | { |
178 | struct sja1105_private *priv = ds->priv; |
179 | const struct sja1105_regs *regs = priv->info->regs; |
180 | u32 cold_reset = BIT(3); |
181 | |
182 | /* Cold reset */ |
183 | return sja1105_xfer_u32(priv, rw: SPI_WRITE, reg_addr: regs->rgu, value: &cold_reset, NULL); |
184 | } |
185 | |
186 | static int sja1105pqrs_reset_cmd(struct dsa_switch *ds) |
187 | { |
188 | struct sja1105_private *priv = ds->priv; |
189 | const struct sja1105_regs *regs = priv->info->regs; |
190 | u32 cold_reset = BIT(2); |
191 | |
192 | /* Cold reset */ |
193 | return sja1105_xfer_u32(priv, rw: SPI_WRITE, reg_addr: regs->rgu, value: &cold_reset, NULL); |
194 | } |
195 | |
196 | static int sja1110_reset_cmd(struct dsa_switch *ds) |
197 | { |
198 | struct sja1105_private *priv = ds->priv; |
199 | const struct sja1105_regs *regs = priv->info->regs; |
200 | u32 switch_reset = BIT(20); |
201 | |
202 | /* Only reset the switch core. |
203 | * A full cold reset would re-enable the BASE_MCSS_CLOCK PLL which |
204 | * would turn on the microcontroller, potentially letting it execute |
205 | * code which could interfere with our configuration. |
206 | */ |
207 | return sja1105_xfer_u32(priv, rw: SPI_WRITE, reg_addr: regs->rgu, value: &switch_reset, NULL); |
208 | } |
209 | |
210 | int sja1105_inhibit_tx(const struct sja1105_private *priv, |
211 | unsigned long port_bitmap, bool tx_inhibited) |
212 | { |
213 | const struct sja1105_regs *regs = priv->info->regs; |
214 | u32 inhibit_cmd; |
215 | int rc; |
216 | |
217 | rc = sja1105_xfer_u32(priv, rw: SPI_READ, reg_addr: regs->port_control, |
218 | value: &inhibit_cmd, NULL); |
219 | if (rc < 0) |
220 | return rc; |
221 | |
222 | if (tx_inhibited) |
223 | inhibit_cmd |= port_bitmap; |
224 | else |
225 | inhibit_cmd &= ~port_bitmap; |
226 | |
227 | return sja1105_xfer_u32(priv, rw: SPI_WRITE, reg_addr: regs->port_control, |
228 | value: &inhibit_cmd, NULL); |
229 | } |
230 | |
231 | struct sja1105_status { |
232 | u64 configs; |
233 | u64 crcchkl; |
234 | u64 ids; |
235 | u64 crcchkg; |
236 | }; |
237 | |
238 | /* This is not reading the entire General Status area, which is also |
239 | * divergent between E/T and P/Q/R/S, but only the relevant bits for |
240 | * ensuring that the static config upload procedure was successful. |
241 | */ |
242 | static void sja1105_status_unpack(void *buf, struct sja1105_status *status) |
243 | { |
244 | /* So that addition translates to 4 bytes */ |
245 | u32 *p = buf; |
246 | |
247 | /* device_id is missing from the buffer, but we don't |
248 | * want to diverge from the manual definition of the |
249 | * register addresses, so we'll back off one step with |
250 | * the register pointer, and never access p[0]. |
251 | */ |
252 | p--; |
253 | sja1105_unpack(buf: p + 0x1, val: &status->configs, start: 31, end: 31, len: 4); |
254 | sja1105_unpack(buf: p + 0x1, val: &status->crcchkl, start: 30, end: 30, len: 4); |
255 | sja1105_unpack(buf: p + 0x1, val: &status->ids, start: 29, end: 29, len: 4); |
256 | sja1105_unpack(buf: p + 0x1, val: &status->crcchkg, start: 28, end: 28, len: 4); |
257 | } |
258 | |
259 | static int sja1105_status_get(struct sja1105_private *priv, |
260 | struct sja1105_status *status) |
261 | { |
262 | const struct sja1105_regs *regs = priv->info->regs; |
263 | u8 packed_buf[4]; |
264 | int rc; |
265 | |
266 | rc = sja1105_xfer_buf(priv, rw: SPI_READ, reg_addr: regs->status, buf: packed_buf, len: 4); |
267 | if (rc < 0) |
268 | return rc; |
269 | |
270 | sja1105_status_unpack(buf: packed_buf, status); |
271 | |
272 | return 0; |
273 | } |
274 | |
275 | /* Not const because unpacking priv->static_config into buffers and preparing |
276 | * for upload requires the recalculation of table CRCs and updating the |
277 | * structures with these. |
278 | */ |
279 | int static_config_buf_prepare_for_upload(struct sja1105_private *priv, |
280 | void *config_buf, int buf_len) |
281 | { |
282 | struct sja1105_static_config *config = &priv->static_config; |
283 | struct sja1105_table_header ; |
284 | sja1105_config_valid_t valid; |
285 | char *; |
286 | int crc_len; |
287 | |
288 | valid = sja1105_static_config_check_valid(config, |
289 | max_mem: priv->info->max_frame_mem); |
290 | if (valid != SJA1105_CONFIG_OK) { |
291 | dev_err(&priv->spidev->dev, |
292 | sja1105_static_config_error_msg[valid]); |
293 | return -EINVAL; |
294 | } |
295 | |
296 | /* Write Device ID and config tables to config_buf */ |
297 | sja1105_static_config_pack(buf: config_buf, config); |
298 | /* Recalculate CRC of the last header (right now 0xDEADBEEF). |
299 | * Don't include the CRC field itself. |
300 | */ |
301 | crc_len = buf_len - 4; |
302 | /* Read the whole table header */ |
303 | final_header_ptr = config_buf + buf_len - SJA1105_SIZE_TABLE_HEADER; |
304 | sja1105_table_header_packing(buf: final_header_ptr, hdr: &final_header, op: UNPACK); |
305 | /* Modify */ |
306 | final_header.crc = sja1105_crc32(buf: config_buf, len: crc_len); |
307 | /* Rewrite */ |
308 | sja1105_table_header_packing(buf: final_header_ptr, hdr: &final_header, op: PACK); |
309 | |
310 | return 0; |
311 | } |
312 | |
313 | #define RETRIES 10 |
314 | |
315 | int sja1105_static_config_upload(struct sja1105_private *priv) |
316 | { |
317 | struct sja1105_static_config *config = &priv->static_config; |
318 | const struct sja1105_regs *regs = priv->info->regs; |
319 | struct device *dev = &priv->spidev->dev; |
320 | struct dsa_switch *ds = priv->ds; |
321 | struct sja1105_status status; |
322 | int rc, retries = RETRIES; |
323 | u8 *config_buf; |
324 | int buf_len; |
325 | |
326 | buf_len = sja1105_static_config_get_length(config); |
327 | config_buf = kcalloc(n: buf_len, size: sizeof(char), GFP_KERNEL); |
328 | if (!config_buf) |
329 | return -ENOMEM; |
330 | |
331 | rc = static_config_buf_prepare_for_upload(priv, config_buf, buf_len); |
332 | if (rc < 0) { |
333 | dev_err(dev, "Invalid config, cannot upload\n" ); |
334 | rc = -EINVAL; |
335 | goto out; |
336 | } |
337 | /* Prevent PHY jabbering during switch reset by inhibiting |
338 | * Tx on all ports and waiting for current packet to drain. |
339 | * Otherwise, the PHY will see an unterminated Ethernet packet. |
340 | */ |
341 | rc = sja1105_inhibit_tx(priv, GENMASK_ULL(ds->num_ports - 1, 0), tx_inhibited: true); |
342 | if (rc < 0) { |
343 | dev_err(dev, "Failed to inhibit Tx on ports\n" ); |
344 | rc = -ENXIO; |
345 | goto out; |
346 | } |
347 | /* Wait for an eventual egress packet to finish transmission |
348 | * (reach IFG). It is guaranteed that a second one will not |
349 | * follow, and that switch cold reset is thus safe |
350 | */ |
351 | usleep_range(min: 500, max: 1000); |
352 | do { |
353 | /* Put the SJA1105 in programming mode */ |
354 | rc = priv->info->reset_cmd(priv->ds); |
355 | if (rc < 0) { |
356 | dev_err(dev, "Failed to reset switch, retrying...\n" ); |
357 | continue; |
358 | } |
359 | /* Wait for the switch to come out of reset */ |
360 | usleep_range(min: 1000, max: 5000); |
361 | /* Upload the static config to the device */ |
362 | rc = sja1105_xfer_buf(priv, rw: SPI_WRITE, reg_addr: regs->config, |
363 | buf: config_buf, len: buf_len); |
364 | if (rc < 0) { |
365 | dev_err(dev, "Failed to upload config, retrying...\n" ); |
366 | continue; |
367 | } |
368 | /* Check that SJA1105 responded well to the config upload */ |
369 | rc = sja1105_status_get(priv, status: &status); |
370 | if (rc < 0) |
371 | continue; |
372 | |
373 | if (status.ids == 1) { |
374 | dev_err(dev, "Mismatch between hardware and static config " |
375 | "device id. Wrote 0x%llx, wants 0x%llx\n" , |
376 | config->device_id, priv->info->device_id); |
377 | continue; |
378 | } |
379 | if (status.crcchkl == 1) { |
380 | dev_err(dev, "Switch reported invalid local CRC on " |
381 | "the uploaded config, retrying...\n" ); |
382 | continue; |
383 | } |
384 | if (status.crcchkg == 1) { |
385 | dev_err(dev, "Switch reported invalid global CRC on " |
386 | "the uploaded config, retrying...\n" ); |
387 | continue; |
388 | } |
389 | if (status.configs == 0) { |
390 | dev_err(dev, "Switch reported that configuration is " |
391 | "invalid, retrying...\n" ); |
392 | continue; |
393 | } |
394 | /* Success! */ |
395 | break; |
396 | } while (--retries); |
397 | |
398 | if (!retries) { |
399 | rc = -EIO; |
400 | dev_err(dev, "Failed to upload config to device, giving up\n" ); |
401 | goto out; |
402 | } else if (retries != RETRIES) { |
403 | dev_info(dev, "Succeeded after %d tried\n" , RETRIES - retries); |
404 | } |
405 | |
406 | out: |
407 | kfree(objp: config_buf); |
408 | return rc; |
409 | } |
410 | |
411 | static const struct sja1105_regs sja1105et_regs = { |
412 | .device_id = 0x0, |
413 | .prod_id = 0x100BC3, |
414 | .status = 0x1, |
415 | .port_control = 0x11, |
416 | .vl_status = 0x10000, |
417 | .config = 0x020000, |
418 | .rgu = 0x100440, |
419 | /* UM10944.pdf, Table 86, ACU Register overview */ |
420 | .pad_mii_tx = {0x100800, 0x100802, 0x100804, 0x100806, 0x100808}, |
421 | .pad_mii_rx = {0x100801, 0x100803, 0x100805, 0x100807, 0x100809}, |
422 | .rmii_pll1 = 0x10000A, |
423 | .cgu_idiv = {0x10000B, 0x10000C, 0x10000D, 0x10000E, 0x10000F}, |
424 | .stats[MAC] = {0x200, 0x202, 0x204, 0x206, 0x208}, |
425 | .stats[HL1] = {0x400, 0x410, 0x420, 0x430, 0x440}, |
426 | .stats[HL2] = {0x600, 0x610, 0x620, 0x630, 0x640}, |
427 | /* UM10944.pdf, Table 78, CGU Register overview */ |
428 | .mii_tx_clk = {0x100013, 0x10001A, 0x100021, 0x100028, 0x10002F}, |
429 | .mii_rx_clk = {0x100014, 0x10001B, 0x100022, 0x100029, 0x100030}, |
430 | .mii_ext_tx_clk = {0x100018, 0x10001F, 0x100026, 0x10002D, 0x100034}, |
431 | .mii_ext_rx_clk = {0x100019, 0x100020, 0x100027, 0x10002E, 0x100035}, |
432 | .rgmii_tx_clk = {0x100016, 0x10001D, 0x100024, 0x10002B, 0x100032}, |
433 | .rmii_ref_clk = {0x100015, 0x10001C, 0x100023, 0x10002A, 0x100031}, |
434 | .rmii_ext_tx_clk = {0x100018, 0x10001F, 0x100026, 0x10002D, 0x100034}, |
435 | .ptpegr_ts = {0xC0, 0xC2, 0xC4, 0xC6, 0xC8}, |
436 | .ptpschtm = 0x12, /* Spans 0x12 to 0x13 */ |
437 | .ptppinst = 0x14, |
438 | .ptppindur = 0x16, |
439 | .ptp_control = 0x17, |
440 | .ptpclkval = 0x18, /* Spans 0x18 to 0x19 */ |
441 | .ptpclkrate = 0x1A, |
442 | .ptpclkcorp = 0x1D, |
443 | .mdio_100base_tx = SJA1105_RSV_ADDR, |
444 | .mdio_100base_t1 = SJA1105_RSV_ADDR, |
445 | }; |
446 | |
447 | static const struct sja1105_regs sja1105pqrs_regs = { |
448 | .device_id = 0x0, |
449 | .prod_id = 0x100BC3, |
450 | .status = 0x1, |
451 | .port_control = 0x12, |
452 | .vl_status = 0x10000, |
453 | .config = 0x020000, |
454 | .rgu = 0x100440, |
455 | /* UM10944.pdf, Table 86, ACU Register overview */ |
456 | .pad_mii_tx = {0x100800, 0x100802, 0x100804, 0x100806, 0x100808}, |
457 | .pad_mii_rx = {0x100801, 0x100803, 0x100805, 0x100807, 0x100809}, |
458 | .pad_mii_id = {0x100810, 0x100811, 0x100812, 0x100813, 0x100814}, |
459 | .rmii_pll1 = 0x10000A, |
460 | .cgu_idiv = {0x10000B, 0x10000C, 0x10000D, 0x10000E, 0x10000F}, |
461 | .stats[MAC] = {0x200, 0x202, 0x204, 0x206, 0x208}, |
462 | .stats[HL1] = {0x400, 0x410, 0x420, 0x430, 0x440}, |
463 | .stats[HL2] = {0x600, 0x610, 0x620, 0x630, 0x640}, |
464 | .stats[ETHER] = {0x1400, 0x1418, 0x1430, 0x1448, 0x1460}, |
465 | /* UM11040.pdf, Table 114 */ |
466 | .mii_tx_clk = {0x100013, 0x100019, 0x10001F, 0x100025, 0x10002B}, |
467 | .mii_rx_clk = {0x100014, 0x10001A, 0x100020, 0x100026, 0x10002C}, |
468 | .mii_ext_tx_clk = {0x100017, 0x10001D, 0x100023, 0x100029, 0x10002F}, |
469 | .mii_ext_rx_clk = {0x100018, 0x10001E, 0x100024, 0x10002A, 0x100030}, |
470 | .rgmii_tx_clk = {0x100016, 0x10001C, 0x100022, 0x100028, 0x10002E}, |
471 | .rmii_ref_clk = {0x100015, 0x10001B, 0x100021, 0x100027, 0x10002D}, |
472 | .rmii_ext_tx_clk = {0x100017, 0x10001D, 0x100023, 0x100029, 0x10002F}, |
473 | .ptpegr_ts = {0xC0, 0xC4, 0xC8, 0xCC, 0xD0}, |
474 | .ptpschtm = 0x13, /* Spans 0x13 to 0x14 */ |
475 | .ptppinst = 0x15, |
476 | .ptppindur = 0x17, |
477 | .ptp_control = 0x18, |
478 | .ptpclkval = 0x19, |
479 | .ptpclkrate = 0x1B, |
480 | .ptpclkcorp = 0x1E, |
481 | .ptpsyncts = 0x1F, |
482 | .mdio_100base_tx = SJA1105_RSV_ADDR, |
483 | .mdio_100base_t1 = SJA1105_RSV_ADDR, |
484 | }; |
485 | |
486 | static const struct sja1105_regs sja1110_regs = { |
487 | .device_id = SJA1110_SPI_ADDR(0x0), |
488 | .prod_id = SJA1110_ACU_ADDR(0xf00), |
489 | .status = SJA1110_SPI_ADDR(0x4), |
490 | .port_control = SJA1110_SPI_ADDR(0x50), /* actually INHIB_TX */ |
491 | .vl_status = 0x10000, |
492 | .config = 0x020000, |
493 | .rgu = SJA1110_RGU_ADDR(0x100), /* Reset Control Register 0 */ |
494 | /* Ports 2 and 3 are capable of xMII, but there isn't anything to |
495 | * configure in the CGU/ACU for them. |
496 | */ |
497 | .pad_mii_tx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
498 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
499 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
500 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
501 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
502 | SJA1105_RSV_ADDR}, |
503 | .pad_mii_rx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
504 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
505 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
506 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
507 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
508 | SJA1105_RSV_ADDR}, |
509 | .pad_mii_id = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
510 | SJA1110_ACU_ADDR(0x18), SJA1110_ACU_ADDR(0x28), |
511 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
512 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
513 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
514 | SJA1105_RSV_ADDR}, |
515 | .rmii_pll1 = SJA1105_RSV_ADDR, |
516 | .cgu_idiv = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
517 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
518 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
519 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
520 | .stats[MAC] = {0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, |
521 | 0x20c, 0x20e, 0x210, 0x212, 0x214}, |
522 | .stats[HL1] = {0x400, 0x410, 0x420, 0x430, 0x440, 0x450, |
523 | 0x460, 0x470, 0x480, 0x490, 0x4a0}, |
524 | .stats[HL2] = {0x600, 0x610, 0x620, 0x630, 0x640, 0x650, |
525 | 0x660, 0x670, 0x680, 0x690, 0x6a0}, |
526 | .stats[ETHER] = {0x1400, 0x1418, 0x1430, 0x1448, 0x1460, 0x1478, |
527 | 0x1490, 0x14a8, 0x14c0, 0x14d8, 0x14f0}, |
528 | .mii_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
529 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
530 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
531 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
532 | .mii_rx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
533 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
534 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
535 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
536 | .mii_ext_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
537 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
538 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
539 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
540 | .mii_ext_rx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
541 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
542 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
543 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
544 | .rgmii_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
545 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
546 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
547 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
548 | .rmii_ref_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
549 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
550 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
551 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
552 | .rmii_ext_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
553 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
554 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
555 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
556 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
557 | SJA1105_RSV_ADDR}, |
558 | .ptpschtm = SJA1110_SPI_ADDR(0x54), |
559 | .ptppinst = SJA1110_SPI_ADDR(0x5c), |
560 | .ptppindur = SJA1110_SPI_ADDR(0x64), |
561 | .ptp_control = SJA1110_SPI_ADDR(0x68), |
562 | .ptpclkval = SJA1110_SPI_ADDR(0x6c), |
563 | .ptpclkrate = SJA1110_SPI_ADDR(0x74), |
564 | .ptpclkcorp = SJA1110_SPI_ADDR(0x80), |
565 | .ptpsyncts = SJA1110_SPI_ADDR(0x84), |
566 | .mdio_100base_tx = 0x1c2400, |
567 | .mdio_100base_t1 = 0x1c1000, |
568 | .pcs_base = {SJA1105_RSV_ADDR, 0x1c1400, 0x1c1800, 0x1c1c00, 0x1c2000, |
569 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, |
570 | SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, |
571 | }; |
572 | |
573 | const struct sja1105_info sja1105e_info = { |
574 | .device_id = SJA1105E_DEVICE_ID, |
575 | .part_no = SJA1105ET_PART_NO, |
576 | .static_ops = sja1105e_table_ops, |
577 | .dyn_ops = sja1105et_dyn_ops, |
578 | .tag_proto = DSA_TAG_PROTO_SJA1105, |
579 | .can_limit_mcast_flood = false, |
580 | .ptp_ts_bits = 24, |
581 | .ptpegr_ts_bytes = 4, |
582 | .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, |
583 | .num_ports = SJA1105_NUM_PORTS, |
584 | .num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT, |
585 | .reset_cmd = sja1105et_reset_cmd, |
586 | .fdb_add_cmd = sja1105et_fdb_add, |
587 | .fdb_del_cmd = sja1105et_fdb_del, |
588 | .ptp_cmd_packing = sja1105et_ptp_cmd_packing, |
589 | .rxtstamp = sja1105_rxtstamp, |
590 | .clocking_setup = sja1105_clocking_setup, |
591 | .regs = &sja1105et_regs, |
592 | .port_speed = { |
593 | [SJA1105_SPEED_AUTO] = 0, |
594 | [SJA1105_SPEED_10MBPS] = 3, |
595 | [SJA1105_SPEED_100MBPS] = 2, |
596 | [SJA1105_SPEED_1000MBPS] = 1, |
597 | [SJA1105_SPEED_2500MBPS] = 0, /* Not supported */ |
598 | }, |
599 | .supports_mii = {true, true, true, true, true}, |
600 | .supports_rmii = {true, true, true, true, true}, |
601 | .supports_rgmii = {true, true, true, true, true}, |
602 | .name = "SJA1105E" , |
603 | }; |
604 | |
605 | const struct sja1105_info sja1105t_info = { |
606 | .device_id = SJA1105T_DEVICE_ID, |
607 | .part_no = SJA1105ET_PART_NO, |
608 | .static_ops = sja1105t_table_ops, |
609 | .dyn_ops = sja1105et_dyn_ops, |
610 | .tag_proto = DSA_TAG_PROTO_SJA1105, |
611 | .can_limit_mcast_flood = false, |
612 | .ptp_ts_bits = 24, |
613 | .ptpegr_ts_bytes = 4, |
614 | .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, |
615 | .num_ports = SJA1105_NUM_PORTS, |
616 | .num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT, |
617 | .reset_cmd = sja1105et_reset_cmd, |
618 | .fdb_add_cmd = sja1105et_fdb_add, |
619 | .fdb_del_cmd = sja1105et_fdb_del, |
620 | .ptp_cmd_packing = sja1105et_ptp_cmd_packing, |
621 | .rxtstamp = sja1105_rxtstamp, |
622 | .clocking_setup = sja1105_clocking_setup, |
623 | .regs = &sja1105et_regs, |
624 | .port_speed = { |
625 | [SJA1105_SPEED_AUTO] = 0, |
626 | [SJA1105_SPEED_10MBPS] = 3, |
627 | [SJA1105_SPEED_100MBPS] = 2, |
628 | [SJA1105_SPEED_1000MBPS] = 1, |
629 | [SJA1105_SPEED_2500MBPS] = 0, /* Not supported */ |
630 | }, |
631 | .supports_mii = {true, true, true, true, true}, |
632 | .supports_rmii = {true, true, true, true, true}, |
633 | .supports_rgmii = {true, true, true, true, true}, |
634 | .name = "SJA1105T" , |
635 | }; |
636 | |
637 | const struct sja1105_info sja1105p_info = { |
638 | .device_id = SJA1105PR_DEVICE_ID, |
639 | .part_no = SJA1105P_PART_NO, |
640 | .static_ops = sja1105p_table_ops, |
641 | .dyn_ops = sja1105pqrs_dyn_ops, |
642 | .tag_proto = DSA_TAG_PROTO_SJA1105, |
643 | .can_limit_mcast_flood = true, |
644 | .ptp_ts_bits = 32, |
645 | .ptpegr_ts_bytes = 8, |
646 | .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, |
647 | .num_ports = SJA1105_NUM_PORTS, |
648 | .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, |
649 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
650 | .reset_cmd = sja1105pqrs_reset_cmd, |
651 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
652 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
653 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
654 | .rxtstamp = sja1105_rxtstamp, |
655 | .clocking_setup = sja1105_clocking_setup, |
656 | .regs = &sja1105pqrs_regs, |
657 | .port_speed = { |
658 | [SJA1105_SPEED_AUTO] = 0, |
659 | [SJA1105_SPEED_10MBPS] = 3, |
660 | [SJA1105_SPEED_100MBPS] = 2, |
661 | [SJA1105_SPEED_1000MBPS] = 1, |
662 | [SJA1105_SPEED_2500MBPS] = 0, /* Not supported */ |
663 | }, |
664 | .supports_mii = {true, true, true, true, true}, |
665 | .supports_rmii = {true, true, true, true, true}, |
666 | .supports_rgmii = {true, true, true, true, true}, |
667 | .name = "SJA1105P" , |
668 | }; |
669 | |
670 | const struct sja1105_info sja1105q_info = { |
671 | .device_id = SJA1105QS_DEVICE_ID, |
672 | .part_no = SJA1105Q_PART_NO, |
673 | .static_ops = sja1105q_table_ops, |
674 | .dyn_ops = sja1105pqrs_dyn_ops, |
675 | .tag_proto = DSA_TAG_PROTO_SJA1105, |
676 | .can_limit_mcast_flood = true, |
677 | .ptp_ts_bits = 32, |
678 | .ptpegr_ts_bytes = 8, |
679 | .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, |
680 | .num_ports = SJA1105_NUM_PORTS, |
681 | .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, |
682 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
683 | .reset_cmd = sja1105pqrs_reset_cmd, |
684 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
685 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
686 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
687 | .rxtstamp = sja1105_rxtstamp, |
688 | .clocking_setup = sja1105_clocking_setup, |
689 | .regs = &sja1105pqrs_regs, |
690 | .port_speed = { |
691 | [SJA1105_SPEED_AUTO] = 0, |
692 | [SJA1105_SPEED_10MBPS] = 3, |
693 | [SJA1105_SPEED_100MBPS] = 2, |
694 | [SJA1105_SPEED_1000MBPS] = 1, |
695 | [SJA1105_SPEED_2500MBPS] = 0, /* Not supported */ |
696 | }, |
697 | .supports_mii = {true, true, true, true, true}, |
698 | .supports_rmii = {true, true, true, true, true}, |
699 | .supports_rgmii = {true, true, true, true, true}, |
700 | .name = "SJA1105Q" , |
701 | }; |
702 | |
703 | const struct sja1105_info sja1105r_info = { |
704 | .device_id = SJA1105PR_DEVICE_ID, |
705 | .part_no = SJA1105R_PART_NO, |
706 | .static_ops = sja1105r_table_ops, |
707 | .dyn_ops = sja1105pqrs_dyn_ops, |
708 | .tag_proto = DSA_TAG_PROTO_SJA1105, |
709 | .can_limit_mcast_flood = true, |
710 | .ptp_ts_bits = 32, |
711 | .ptpegr_ts_bytes = 8, |
712 | .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, |
713 | .num_ports = SJA1105_NUM_PORTS, |
714 | .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, |
715 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
716 | .reset_cmd = sja1105pqrs_reset_cmd, |
717 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
718 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
719 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
720 | .rxtstamp = sja1105_rxtstamp, |
721 | .clocking_setup = sja1105_clocking_setup, |
722 | .pcs_mdio_read_c45 = sja1105_pcs_mdio_read_c45, |
723 | .pcs_mdio_write_c45 = sja1105_pcs_mdio_write_c45, |
724 | .regs = &sja1105pqrs_regs, |
725 | .port_speed = { |
726 | [SJA1105_SPEED_AUTO] = 0, |
727 | [SJA1105_SPEED_10MBPS] = 3, |
728 | [SJA1105_SPEED_100MBPS] = 2, |
729 | [SJA1105_SPEED_1000MBPS] = 1, |
730 | [SJA1105_SPEED_2500MBPS] = 0, /* Not supported */ |
731 | }, |
732 | .supports_mii = {true, true, true, true, true}, |
733 | .supports_rmii = {true, true, true, true, true}, |
734 | .supports_rgmii = {true, true, true, true, true}, |
735 | .supports_sgmii = {false, false, false, false, true}, |
736 | .name = "SJA1105R" , |
737 | }; |
738 | |
739 | const struct sja1105_info sja1105s_info = { |
740 | .device_id = SJA1105QS_DEVICE_ID, |
741 | .part_no = SJA1105S_PART_NO, |
742 | .static_ops = sja1105s_table_ops, |
743 | .dyn_ops = sja1105pqrs_dyn_ops, |
744 | .regs = &sja1105pqrs_regs, |
745 | .tag_proto = DSA_TAG_PROTO_SJA1105, |
746 | .can_limit_mcast_flood = true, |
747 | .ptp_ts_bits = 32, |
748 | .ptpegr_ts_bytes = 8, |
749 | .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, |
750 | .num_ports = SJA1105_NUM_PORTS, |
751 | .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, |
752 | .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, |
753 | .reset_cmd = sja1105pqrs_reset_cmd, |
754 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
755 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
756 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
757 | .rxtstamp = sja1105_rxtstamp, |
758 | .clocking_setup = sja1105_clocking_setup, |
759 | .pcs_mdio_read_c45 = sja1105_pcs_mdio_read_c45, |
760 | .pcs_mdio_write_c45 = sja1105_pcs_mdio_write_c45, |
761 | .port_speed = { |
762 | [SJA1105_SPEED_AUTO] = 0, |
763 | [SJA1105_SPEED_10MBPS] = 3, |
764 | [SJA1105_SPEED_100MBPS] = 2, |
765 | [SJA1105_SPEED_1000MBPS] = 1, |
766 | [SJA1105_SPEED_2500MBPS] = 0, /* Not supported */ |
767 | }, |
768 | .supports_mii = {true, true, true, true, true}, |
769 | .supports_rmii = {true, true, true, true, true}, |
770 | .supports_rgmii = {true, true, true, true, true}, |
771 | .supports_sgmii = {false, false, false, false, true}, |
772 | .name = "SJA1105S" , |
773 | }; |
774 | |
775 | const struct sja1105_info sja1110a_info = { |
776 | .device_id = SJA1110_DEVICE_ID, |
777 | .part_no = SJA1110A_PART_NO, |
778 | .static_ops = sja1110_table_ops, |
779 | .dyn_ops = sja1110_dyn_ops, |
780 | .regs = &sja1110_regs, |
781 | .tag_proto = DSA_TAG_PROTO_SJA1110, |
782 | .can_limit_mcast_flood = true, |
783 | .multiple_cascade_ports = true, |
784 | .fixed_cbs_mapping = true, |
785 | .ptp_ts_bits = 32, |
786 | .ptpegr_ts_bytes = 8, |
787 | .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, |
788 | .num_ports = SJA1110_NUM_PORTS, |
789 | .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, |
790 | .setup_rgmii_delay = sja1110_setup_rgmii_delay, |
791 | .reset_cmd = sja1110_reset_cmd, |
792 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
793 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
794 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
795 | .rxtstamp = sja1110_rxtstamp, |
796 | .txtstamp = sja1110_txtstamp, |
797 | .disable_microcontroller = sja1110_disable_microcontroller, |
798 | .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45, |
799 | .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45, |
800 | .port_speed = { |
801 | [SJA1105_SPEED_AUTO] = 0, |
802 | [SJA1105_SPEED_10MBPS] = 4, |
803 | [SJA1105_SPEED_100MBPS] = 3, |
804 | [SJA1105_SPEED_1000MBPS] = 2, |
805 | [SJA1105_SPEED_2500MBPS] = 1, |
806 | }, |
807 | .supports_mii = {true, true, true, true, false, |
808 | true, true, true, true, true, true}, |
809 | .supports_rmii = {false, false, true, true, false, |
810 | false, false, false, false, false, false}, |
811 | .supports_rgmii = {false, false, true, true, false, |
812 | false, false, false, false, false, false}, |
813 | .supports_sgmii = {false, true, true, true, true, |
814 | false, false, false, false, false, false}, |
815 | .supports_2500basex = {false, false, false, true, true, |
816 | false, false, false, false, false, false}, |
817 | .internal_phy = {SJA1105_NO_PHY, SJA1105_PHY_BASE_TX, |
818 | SJA1105_NO_PHY, SJA1105_NO_PHY, |
819 | SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, |
820 | SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, |
821 | SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, |
822 | SJA1105_PHY_BASE_T1}, |
823 | .name = "SJA1110A" , |
824 | }; |
825 | |
826 | const struct sja1105_info sja1110b_info = { |
827 | .device_id = SJA1110_DEVICE_ID, |
828 | .part_no = SJA1110B_PART_NO, |
829 | .static_ops = sja1110_table_ops, |
830 | .dyn_ops = sja1110_dyn_ops, |
831 | .regs = &sja1110_regs, |
832 | .tag_proto = DSA_TAG_PROTO_SJA1110, |
833 | .can_limit_mcast_flood = true, |
834 | .multiple_cascade_ports = true, |
835 | .fixed_cbs_mapping = true, |
836 | .ptp_ts_bits = 32, |
837 | .ptpegr_ts_bytes = 8, |
838 | .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, |
839 | .num_ports = SJA1110_NUM_PORTS, |
840 | .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, |
841 | .setup_rgmii_delay = sja1110_setup_rgmii_delay, |
842 | .reset_cmd = sja1110_reset_cmd, |
843 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
844 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
845 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
846 | .rxtstamp = sja1110_rxtstamp, |
847 | .txtstamp = sja1110_txtstamp, |
848 | .disable_microcontroller = sja1110_disable_microcontroller, |
849 | .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45, |
850 | .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45, |
851 | .port_speed = { |
852 | [SJA1105_SPEED_AUTO] = 0, |
853 | [SJA1105_SPEED_10MBPS] = 4, |
854 | [SJA1105_SPEED_100MBPS] = 3, |
855 | [SJA1105_SPEED_1000MBPS] = 2, |
856 | [SJA1105_SPEED_2500MBPS] = 1, |
857 | }, |
858 | .supports_mii = {true, true, true, true, false, |
859 | true, true, true, true, true, false}, |
860 | .supports_rmii = {false, false, true, true, false, |
861 | false, false, false, false, false, false}, |
862 | .supports_rgmii = {false, false, true, true, false, |
863 | false, false, false, false, false, false}, |
864 | .supports_sgmii = {false, false, false, true, true, |
865 | false, false, false, false, false, false}, |
866 | .supports_2500basex = {false, false, false, true, true, |
867 | false, false, false, false, false, false}, |
868 | .internal_phy = {SJA1105_NO_PHY, SJA1105_PHY_BASE_TX, |
869 | SJA1105_NO_PHY, SJA1105_NO_PHY, |
870 | SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, |
871 | SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, |
872 | SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, |
873 | SJA1105_NO_PHY}, |
874 | .name = "SJA1110B" , |
875 | }; |
876 | |
877 | const struct sja1105_info sja1110c_info = { |
878 | .device_id = SJA1110_DEVICE_ID, |
879 | .part_no = SJA1110C_PART_NO, |
880 | .static_ops = sja1110_table_ops, |
881 | .dyn_ops = sja1110_dyn_ops, |
882 | .regs = &sja1110_regs, |
883 | .tag_proto = DSA_TAG_PROTO_SJA1110, |
884 | .can_limit_mcast_flood = true, |
885 | .multiple_cascade_ports = true, |
886 | .fixed_cbs_mapping = true, |
887 | .ptp_ts_bits = 32, |
888 | .ptpegr_ts_bytes = 8, |
889 | .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, |
890 | .num_ports = SJA1110_NUM_PORTS, |
891 | .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, |
892 | .setup_rgmii_delay = sja1110_setup_rgmii_delay, |
893 | .reset_cmd = sja1110_reset_cmd, |
894 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
895 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
896 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
897 | .rxtstamp = sja1110_rxtstamp, |
898 | .txtstamp = sja1110_txtstamp, |
899 | .disable_microcontroller = sja1110_disable_microcontroller, |
900 | .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45, |
901 | .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45, |
902 | .port_speed = { |
903 | [SJA1105_SPEED_AUTO] = 0, |
904 | [SJA1105_SPEED_10MBPS] = 4, |
905 | [SJA1105_SPEED_100MBPS] = 3, |
906 | [SJA1105_SPEED_1000MBPS] = 2, |
907 | [SJA1105_SPEED_2500MBPS] = 1, |
908 | }, |
909 | .supports_mii = {true, true, true, true, false, |
910 | true, true, true, false, false, false}, |
911 | .supports_rmii = {false, false, true, true, false, |
912 | false, false, false, false, false, false}, |
913 | .supports_rgmii = {false, false, true, true, false, |
914 | false, false, false, false, false, false}, |
915 | .supports_sgmii = {false, false, false, false, true, |
916 | false, false, false, false, false, false}, |
917 | .supports_2500basex = {false, false, false, false, true, |
918 | false, false, false, false, false, false}, |
919 | .internal_phy = {SJA1105_NO_PHY, SJA1105_PHY_BASE_TX, |
920 | SJA1105_NO_PHY, SJA1105_NO_PHY, |
921 | SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, |
922 | SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, |
923 | SJA1105_NO_PHY, SJA1105_NO_PHY, |
924 | SJA1105_NO_PHY}, |
925 | .name = "SJA1110C" , |
926 | }; |
927 | |
928 | const struct sja1105_info sja1110d_info = { |
929 | .device_id = SJA1110_DEVICE_ID, |
930 | .part_no = SJA1110D_PART_NO, |
931 | .static_ops = sja1110_table_ops, |
932 | .dyn_ops = sja1110_dyn_ops, |
933 | .regs = &sja1110_regs, |
934 | .tag_proto = DSA_TAG_PROTO_SJA1110, |
935 | .can_limit_mcast_flood = true, |
936 | .multiple_cascade_ports = true, |
937 | .fixed_cbs_mapping = true, |
938 | .ptp_ts_bits = 32, |
939 | .ptpegr_ts_bytes = 8, |
940 | .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, |
941 | .num_ports = SJA1110_NUM_PORTS, |
942 | .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, |
943 | .setup_rgmii_delay = sja1110_setup_rgmii_delay, |
944 | .reset_cmd = sja1110_reset_cmd, |
945 | .fdb_add_cmd = sja1105pqrs_fdb_add, |
946 | .fdb_del_cmd = sja1105pqrs_fdb_del, |
947 | .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, |
948 | .rxtstamp = sja1110_rxtstamp, |
949 | .txtstamp = sja1110_txtstamp, |
950 | .disable_microcontroller = sja1110_disable_microcontroller, |
951 | .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45, |
952 | .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45, |
953 | .port_speed = { |
954 | [SJA1105_SPEED_AUTO] = 0, |
955 | [SJA1105_SPEED_10MBPS] = 4, |
956 | [SJA1105_SPEED_100MBPS] = 3, |
957 | [SJA1105_SPEED_1000MBPS] = 2, |
958 | [SJA1105_SPEED_2500MBPS] = 1, |
959 | }, |
960 | .supports_mii = {true, false, true, false, false, |
961 | true, true, true, false, false, false}, |
962 | .supports_rmii = {false, false, true, false, false, |
963 | false, false, false, false, false, false}, |
964 | .supports_rgmii = {false, false, true, false, false, |
965 | false, false, false, false, false, false}, |
966 | .supports_sgmii = {false, true, true, true, true, |
967 | false, false, false, false, false, false}, |
968 | .supports_2500basex = {false, false, false, true, true, |
969 | false, false, false, false, false, false}, |
970 | .internal_phy = {SJA1105_NO_PHY, SJA1105_NO_PHY, |
971 | SJA1105_NO_PHY, SJA1105_NO_PHY, |
972 | SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, |
973 | SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, |
974 | SJA1105_NO_PHY, SJA1105_NO_PHY, |
975 | SJA1105_NO_PHY}, |
976 | .name = "SJA1110D" , |
977 | }; |
978 | |