Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mscc-ocelot-add-support-for-SerDes-muxing-configuration'

Quentin Schulz says:

====================
mscc: ocelot: add support for SerDes muxing configuration

The Ocelot switch has currently an hardcoded SerDes muxing that suits only
a particular use case. Any other board setup will fail to work.

To prepare for upcoming boards' support that do not have the same muxing,
create a PHY driver that will handle all possible cases.

A SerDes can work in SGMII, QSGMII or PCIe and is also muxed to use a
given port depending on the selected mode or board design.

The SerDes configuration is in the middle of an address space (HSIO) that
is used to configure some parts in the MAC controller driver, that is why
we need to use a syscon so that we can write to the same address space from
different drivers safely using regmap.

This breaks backward compatibility but it's fine because there's only one
board at the moment that is using what's modified in this patch series.
This will break git bisect.

Even though this patch series is about SerDes __muxing__ configuration, the
DT node is named serdes for the simple reason that I couldn't find any
mention to SerDes anywhere else from the address space handled by this
driver.

v4:
- add reviewed-by,
- format the patch series with -M for identifying renamed files,
- add parent info in DT binding of the SerDes IP,
- move to macros SERDES[16]G(X) instead of multiple SERDES[16]G_[012345]
constants,
- move to SERDES[16]G_MAX being the last VALID macro of a type, so
migrate to <= conditions instead of < when iterating,
- create a SERDES_MUX_SGMII and SERDES_MUX_QSGMII macro so the muxing
configurations are a tad more readable,
- use a bunch of unsigned int instead of int,
- return -EOPNOTSUPP for SERDES6G/PCIe until it's supported,
- simplify condition when there is an error code returned by
devm_of_phy_get,

v3:
- add Paul Burton's Acked-By on MIPS patches so that the patch series can
be merged in the net tree in its entirety,

v2:
- use a switch case for setting the phy_mode in the SerDes driver as
suggested by Andrew,
- stop replacing the value of the error pointer in the SerDes driver,
- use a dev_dbg for the deferring of the probe in the SerDes driver,
- use constants in the Device Tree to select the SerDes macro in use with
a port,
- adapt the SerDes driver to use those constants,
- add a header file in include/dt-bindings for the constants,
- fix space/tab issue,
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+559 -180
+16
Documentation/devicetree/bindings/mips/mscc.txt
··· 41 41 compatible = "mscc,ocelot-cpu-syscon", "syscon"; 42 42 reg = <0x70000000 0x2c>; 43 43 }; 44 + 45 + o HSIO regs: 46 + 47 + The SoC has a few registers (HSIO) handling miscellaneous functionalities: 48 + configuration and status of PLL5, RCOMP, SyncE, SerDes configurations and 49 + status, SerDes muxing and a thermal sensor. 50 + 51 + Required properties: 52 + - compatible: Should be "mscc,ocelot-hsio", "syscon", "simple-mfd" 53 + - reg : Should contain registers location and length 54 + 55 + Example: 56 + syscon@10d0000 { 57 + compatible = "mscc,ocelot-hsio", "syscon", "simple-mfd"; 58 + reg = <0x10d0000 0x10000>; 59 + };
+3 -6
Documentation/devicetree/bindings/net/mscc-ocelot.txt
··· 12 12 - "sys" 13 13 - "rew" 14 14 - "qs" 15 - - "hsio" 16 15 - "qsys" 17 16 - "ana" 18 17 - "portX" with X from 0 to the number of last port index available on that ··· 44 45 reg = <0x1010000 0x10000>, 45 46 <0x1030000 0x10000>, 46 47 <0x1080000 0x100>, 47 - <0x10d0000 0x10000>, 48 48 <0x11e0000 0x100>, 49 49 <0x11f0000 0x100>, 50 50 <0x1200000 0x100>, ··· 57 59 <0x1280000 0x100>, 58 60 <0x1800000 0x80000>, 59 61 <0x1880000 0x10000>; 60 - reg-names = "sys", "rew", "qs", "hsio", "port0", 61 - "port1", "port2", "port3", "port4", "port5", 62 - "port6", "port7", "port8", "port9", "port10", 63 - "qsys", "ana"; 62 + reg-names = "sys", "rew", "qs", "port0", "port1", "port2", 63 + "port3", "port4", "port5", "port6", "port7", 64 + "port8", "port9", "port10", "qsys", "ana"; 64 65 interrupts = <21 22>; 65 66 interrupt-names = "xtr", "inj"; 66 67
+43
Documentation/devicetree/bindings/phy/phy-ocelot-serdes.txt
··· 1 + Microsemi Ocelot SerDes muxing driver 2 + ------------------------------------- 3 + 4 + On Microsemi Ocelot, there is a handful of registers in HSIO address 5 + space for setting up the SerDes to switch port muxing. 6 + 7 + A SerDes X can be "muxed" to work with switch port Y or Z for example. 8 + One specific SerDes can also be used as a PCIe interface. 9 + 10 + Hence, a SerDes represents an interface, be it an Ethernet or a PCIe one. 11 + 12 + There are two kinds of SerDes: SERDES1G supports 10/100Mbps in 13 + half/full-duplex and 1000Mbps in full-duplex mode while SERDES6G supports 14 + 10/100Mbps in half/full-duplex and 1000/2500Mbps in full-duplex mode. 15 + 16 + Also, SERDES6G number (aka "macro") 0 is the only interface supporting 17 + QSGMII. 18 + 19 + This is a child of the HSIO syscon ("mscc,ocelot-hsio", see 20 + Documentation/devicetree/bindings/mips/mscc.txt) on the Microsemi Ocelot. 21 + 22 + Required properties: 23 + 24 + - compatible: should be "mscc,vsc7514-serdes" 25 + - #phy-cells : from the generic phy bindings, must be 2. 26 + The first number defines the input port to use for a given 27 + SerDes macro. The second defines the macro to use. They are 28 + defined in dt-bindings/phy/phy-ocelot-serdes.h 29 + 30 + Example: 31 + 32 + serdes: serdes { 33 + compatible = "mscc,vsc7514-serdes"; 34 + #phy-cells = <2>; 35 + }; 36 + 37 + ethernet { 38 + port1 { 39 + phy-handle = <&phy_foo>; 40 + /* Link SERDES1G_5 to port1 */ 41 + phys = <&serdes 1 SERDES1G_5>; 42 + }; 43 + };
+14 -5
arch/mips/boot/dts/mscc/ocelot.dtsi
··· 107 107 reg = <0x1010000 0x10000>, 108 108 <0x1030000 0x10000>, 109 109 <0x1080000 0x100>, 110 - <0x10d0000 0x10000>, 111 110 <0x11e0000 0x100>, 112 111 <0x11f0000 0x100>, 113 112 <0x1200000 0x100>, ··· 120 121 <0x1280000 0x100>, 121 122 <0x1800000 0x80000>, 122 123 <0x1880000 0x10000>; 123 - reg-names = "sys", "rew", "qs", "hsio", "port0", 124 - "port1", "port2", "port3", "port4", "port5", 125 - "port6", "port7", "port8", "port9", "port10", 126 - "qsys", "ana"; 124 + reg-names = "sys", "rew", "qs", "port0", "port1", 125 + "port2", "port3", "port4", "port5", "port6", 126 + "port7", "port8", "port9", "port10", "qsys", 127 + "ana"; 127 128 interrupts = <21 22>; 128 129 interrupt-names = "xtr", "inj"; 129 130 ··· 229 230 pinctrl-names = "default"; 230 231 pinctrl-0 = <&miim1>; 231 232 status = "disabled"; 233 + }; 234 + 235 + hsio: syscon@10d0000 { 236 + compatible = "mscc,ocelot-hsio", "syscon", "simple-mfd"; 237 + reg = <0x10d0000 0x10000>; 238 + 239 + serdes: serdes { 240 + compatible = "mscc,vsc7514-serdes"; 241 + #phy-cells = <2>; 242 + }; 232 243 }; 233 244 }; 234 245 };
+2
drivers/net/ethernet/mscc/Kconfig
··· 23 23 config MSCC_OCELOT_SWITCH_OCELOT 24 24 tristate "Ocelot switch driver on Ocelot" 25 25 depends on MSCC_OCELOT_SWITCH 26 + depends on GENERIC_PHY 27 + depends on OF_NET 26 28 help 27 29 This driver supports the Ocelot network switch device as present on 28 30 the Ocelot SoCs.
+15 -1
drivers/net/ethernet/mscc/ocelot.c
··· 472 472 { 473 473 struct ocelot_port *port = netdev_priv(dev); 474 474 struct ocelot *ocelot = port->ocelot; 475 + enum phy_mode phy_mode; 475 476 int err; 476 477 477 478 /* Enable receiving frames on the port, and activate auto-learning of ··· 483 482 ANA_PORT_PORT_CFG_PORTID_VAL(port->chip_port), 484 483 ANA_PORT_PORT_CFG, port->chip_port); 485 484 485 + if (port->serdes) { 486 + if (port->phy_mode == PHY_INTERFACE_MODE_SGMII) 487 + phy_mode = PHY_MODE_SGMII; 488 + else 489 + phy_mode = PHY_MODE_QSGMII; 490 + 491 + err = phy_set_mode(port->serdes, phy_mode); 492 + if (err) { 493 + netdev_err(dev, "Could not set mode of SerDes\n"); 494 + return err; 495 + } 496 + } 497 + 486 498 err = phy_connect_direct(dev, port->phy, &ocelot_port_adjust_link, 487 - PHY_INTERFACE_MODE_NA); 499 + port->phy_mode); 488 500 if (err) { 489 501 netdev_err(dev, "Could not attach to PHY\n"); 490 502 return err;
+5 -74
drivers/net/ethernet/mscc/ocelot.h
··· 11 11 #include <linux/bitops.h> 12 12 #include <linux/etherdevice.h> 13 13 #include <linux/if_vlan.h> 14 + #include <linux/phy.h> 15 + #include <linux/phy/phy.h> 14 16 #include <linux/platform_device.h> 15 17 #include <linux/regmap.h> 16 18 17 19 #include "ocelot_ana.h" 18 20 #include "ocelot_dev.h" 19 - #include "ocelot_hsio.h" 20 21 #include "ocelot_qsys.h" 21 22 #include "ocelot_rew.h" 22 23 #include "ocelot_sys.h" ··· 334 333 SYS_CM_DATA_RD, 335 334 SYS_CM_OP, 336 335 SYS_CM_DATA, 337 - HSIO_PLL5G_CFG0 = HSIO << TARGET_OFFSET, 338 - HSIO_PLL5G_CFG1, 339 - HSIO_PLL5G_CFG2, 340 - HSIO_PLL5G_CFG3, 341 - HSIO_PLL5G_CFG4, 342 - HSIO_PLL5G_CFG5, 343 - HSIO_PLL5G_CFG6, 344 - HSIO_PLL5G_STATUS0, 345 - HSIO_PLL5G_STATUS1, 346 - HSIO_PLL5G_BIST_CFG0, 347 - HSIO_PLL5G_BIST_CFG1, 348 - HSIO_PLL5G_BIST_CFG2, 349 - HSIO_PLL5G_BIST_STAT0, 350 - HSIO_PLL5G_BIST_STAT1, 351 - HSIO_RCOMP_CFG0, 352 - HSIO_RCOMP_STATUS, 353 - HSIO_SYNC_ETH_CFG, 354 - HSIO_SYNC_ETH_PLL_CFG, 355 - HSIO_S1G_DES_CFG, 356 - HSIO_S1G_IB_CFG, 357 - HSIO_S1G_OB_CFG, 358 - HSIO_S1G_SER_CFG, 359 - HSIO_S1G_COMMON_CFG, 360 - HSIO_S1G_PLL_CFG, 361 - HSIO_S1G_PLL_STATUS, 362 - HSIO_S1G_DFT_CFG0, 363 - HSIO_S1G_DFT_CFG1, 364 - HSIO_S1G_DFT_CFG2, 365 - HSIO_S1G_TP_CFG, 366 - HSIO_S1G_RC_PLL_BIST_CFG, 367 - HSIO_S1G_MISC_CFG, 368 - HSIO_S1G_DFT_STATUS, 369 - HSIO_S1G_MISC_STATUS, 370 - HSIO_MCB_S1G_ADDR_CFG, 371 - HSIO_S6G_DIG_CFG, 372 - HSIO_S6G_DFT_CFG0, 373 - HSIO_S6G_DFT_CFG1, 374 - HSIO_S6G_DFT_CFG2, 375 - HSIO_S6G_TP_CFG0, 376 - HSIO_S6G_TP_CFG1, 377 - HSIO_S6G_RC_PLL_BIST_CFG, 378 - HSIO_S6G_MISC_CFG, 379 - HSIO_S6G_OB_ANEG_CFG, 380 - HSIO_S6G_DFT_STATUS, 381 - HSIO_S6G_ERR_CNT, 382 - HSIO_S6G_MISC_STATUS, 383 - HSIO_S6G_DES_CFG, 384 - HSIO_S6G_IB_CFG, 385 - HSIO_S6G_IB_CFG1, 386 - HSIO_S6G_IB_CFG2, 387 - HSIO_S6G_IB_CFG3, 388 - HSIO_S6G_IB_CFG4, 389 - HSIO_S6G_IB_CFG5, 390 - HSIO_S6G_OB_CFG, 391 - HSIO_S6G_OB_CFG1, 392 - HSIO_S6G_SER_CFG, 393 - HSIO_S6G_COMMON_CFG, 394 - HSIO_S6G_PLL_CFG, 395 - HSIO_S6G_ACJTAG_CFG, 396 - HSIO_S6G_GP_CFG, 397 - HSIO_S6G_IB_STATUS0, 398 - HSIO_S6G_IB_STATUS1, 399 - HSIO_S6G_ACJTAG_STATUS, 400 - HSIO_S6G_PLL_STATUS, 401 - HSIO_S6G_REVID, 402 - HSIO_MCB_S6G_ADDR_CFG, 403 - HSIO_HW_CFG, 404 - HSIO_HW_QSGMII_CFG, 405 - HSIO_HW_QSGMII_STAT, 406 - HSIO_CLK_CFG, 407 - HSIO_TEMP_SENSOR_CTRL, 408 - HSIO_TEMP_SENSOR_CFG, 409 - HSIO_TEMP_SENSOR_STAT, 410 336 }; 411 337 412 338 enum ocelot_regfield { ··· 455 527 u8 vlan_aware; 456 528 457 529 u64 *stats; 530 + 531 + phy_interface_t phy_mode; 532 + struct phy *serdes; 458 533 }; 459 534 460 535 u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset);
+50 -11
drivers/net/ethernet/mscc/ocelot_board.c
··· 6 6 */ 7 7 #include <linux/interrupt.h> 8 8 #include <linux/module.h> 9 + #include <linux/of_net.h> 9 10 #include <linux/netdevice.h> 10 11 #include <linux/of_mdio.h> 11 12 #include <linux/of_platform.h> 13 + #include <linux/mfd/syscon.h> 12 14 #include <linux/skbuff.h> 13 15 14 16 #include "ocelot.h" ··· 170 168 struct device_node *np = pdev->dev.of_node; 171 169 struct device_node *ports, *portnp; 172 170 struct ocelot *ocelot; 171 + struct regmap *hsio; 173 172 u32 val; 174 173 175 174 struct { ··· 182 179 { QSYS, "qsys" }, 183 180 { ANA, "ana" }, 184 181 { QS, "qs" }, 185 - { HSIO, "hsio" }, 186 182 }; 187 183 188 184 if (!np && !pdev->dev.platform_data) ··· 203 201 204 202 ocelot->targets[res[i].id] = target; 205 203 } 204 + 205 + hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio"); 206 + if (IS_ERR(hsio)) { 207 + dev_err(&pdev->dev, "missing hsio syscon\n"); 208 + return PTR_ERR(hsio); 209 + } 210 + 211 + ocelot->targets[HSIO] = hsio; 206 212 207 213 err = ocelot_chip_init(ocelot); 208 214 if (err) ··· 254 244 INIT_LIST_HEAD(&ocelot->multicast); 255 245 ocelot_init(ocelot); 256 246 257 - ocelot_rmw(ocelot, HSIO_HW_CFG_DEV1G_4_MODE | 258 - HSIO_HW_CFG_DEV1G_6_MODE | 259 - HSIO_HW_CFG_DEV1G_9_MODE, 260 - HSIO_HW_CFG_DEV1G_4_MODE | 261 - HSIO_HW_CFG_DEV1G_6_MODE | 262 - HSIO_HW_CFG_DEV1G_9_MODE, 263 - HSIO_HW_CFG); 264 - 265 247 for_each_available_child_of_node(ports, portnp) { 266 248 struct device_node *phy_node; 267 249 struct phy_device *phy; 268 250 struct resource *res; 251 + struct phy *serdes; 252 + enum phy_mode phy_mode; 269 253 void __iomem *regs; 270 254 char res_name[8]; 271 255 u32 port; ··· 284 280 continue; 285 281 286 282 err = ocelot_probe_port(ocelot, port, regs, phy); 287 - if (err) { 288 - dev_err(&pdev->dev, "failed to probe ports\n"); 283 + if (err) 284 + return err; 285 + 286 + err = of_get_phy_mode(portnp); 287 + if (err < 0) 288 + ocelot->ports[port]->phy_mode = PHY_INTERFACE_MODE_NA; 289 + else 290 + ocelot->ports[port]->phy_mode = err; 291 + 292 + switch (ocelot->ports[port]->phy_mode) { 293 + case PHY_INTERFACE_MODE_NA: 294 + continue; 295 + case PHY_INTERFACE_MODE_SGMII: 296 + phy_mode = PHY_MODE_SGMII; 297 + break; 298 + case PHY_INTERFACE_MODE_QSGMII: 299 + phy_mode = PHY_MODE_QSGMII; 300 + break; 301 + default: 302 + dev_err(ocelot->dev, 303 + "invalid phy mode for port%d, (Q)SGMII only\n", 304 + port); 305 + return -EINVAL; 306 + } 307 + 308 + serdes = devm_of_phy_get(ocelot->dev, portnp, NULL); 309 + if (IS_ERR(serdes)) { 310 + err = PTR_ERR(serdes); 311 + if (err == -EPROBE_DEFER) 312 + dev_dbg(ocelot->dev, "deferring probe\n"); 313 + else 314 + dev_err(ocelot->dev, 315 + "missing SerDes phys for port%d\n", 316 + port); 317 + 289 318 goto err_probe_ports; 290 319 } 320 + 321 + ocelot->ports[port]->serdes = serdes; 291 322 } 292 323 293 324 register_netdevice_notifier(&ocelot_netdevice_nb);
+74
drivers/net/ethernet/mscc/ocelot_hsio.h include/soc/mscc/ocelot_hsio.h
··· 8 8 #ifndef _MSCC_OCELOT_HSIO_H_ 9 9 #define _MSCC_OCELOT_HSIO_H_ 10 10 11 + #define HSIO_PLL5G_CFG0 0x0000 12 + #define HSIO_PLL5G_CFG1 0x0004 13 + #define HSIO_PLL5G_CFG2 0x0008 14 + #define HSIO_PLL5G_CFG3 0x000c 15 + #define HSIO_PLL5G_CFG4 0x0010 16 + #define HSIO_PLL5G_CFG5 0x0014 17 + #define HSIO_PLL5G_CFG6 0x0018 18 + #define HSIO_PLL5G_STATUS0 0x001c 19 + #define HSIO_PLL5G_STATUS1 0x0020 20 + #define HSIO_PLL5G_BIST_CFG0 0x0024 21 + #define HSIO_PLL5G_BIST_CFG1 0x0028 22 + #define HSIO_PLL5G_BIST_CFG2 0x002c 23 + #define HSIO_PLL5G_BIST_STAT0 0x0030 24 + #define HSIO_PLL5G_BIST_STAT1 0x0034 25 + #define HSIO_RCOMP_CFG0 0x0038 26 + #define HSIO_RCOMP_STATUS 0x003c 27 + #define HSIO_SYNC_ETH_CFG 0x0040 28 + #define HSIO_SYNC_ETH_PLL_CFG 0x0048 29 + #define HSIO_S1G_DES_CFG 0x004c 30 + #define HSIO_S1G_IB_CFG 0x0050 31 + #define HSIO_S1G_OB_CFG 0x0054 32 + #define HSIO_S1G_SER_CFG 0x0058 33 + #define HSIO_S1G_COMMON_CFG 0x005c 34 + #define HSIO_S1G_PLL_CFG 0x0060 35 + #define HSIO_S1G_PLL_STATUS 0x0064 36 + #define HSIO_S1G_DFT_CFG0 0x0068 37 + #define HSIO_S1G_DFT_CFG1 0x006c 38 + #define HSIO_S1G_DFT_CFG2 0x0070 39 + #define HSIO_S1G_TP_CFG 0x0074 40 + #define HSIO_S1G_RC_PLL_BIST_CFG 0x0078 41 + #define HSIO_S1G_MISC_CFG 0x007c 42 + #define HSIO_S1G_DFT_STATUS 0x0080 43 + #define HSIO_S1G_MISC_STATUS 0x0084 44 + #define HSIO_MCB_S1G_ADDR_CFG 0x0088 45 + #define HSIO_S6G_DIG_CFG 0x008c 46 + #define HSIO_S6G_DFT_CFG0 0x0090 47 + #define HSIO_S6G_DFT_CFG1 0x0094 48 + #define HSIO_S6G_DFT_CFG2 0x0098 49 + #define HSIO_S6G_TP_CFG0 0x009c 50 + #define HSIO_S6G_TP_CFG1 0x00a0 51 + #define HSIO_S6G_RC_PLL_BIST_CFG 0x00a4 52 + #define HSIO_S6G_MISC_CFG 0x00a8 53 + #define HSIO_S6G_OB_ANEG_CFG 0x00ac 54 + #define HSIO_S6G_DFT_STATUS 0x00b0 55 + #define HSIO_S6G_ERR_CNT 0x00b4 56 + #define HSIO_S6G_MISC_STATUS 0x00b8 57 + #define HSIO_S6G_DES_CFG 0x00bc 58 + #define HSIO_S6G_IB_CFG 0x00c0 59 + #define HSIO_S6G_IB_CFG1 0x00c4 60 + #define HSIO_S6G_IB_CFG2 0x00c8 61 + #define HSIO_S6G_IB_CFG3 0x00cc 62 + #define HSIO_S6G_IB_CFG4 0x00d0 63 + #define HSIO_S6G_IB_CFG5 0x00d4 64 + #define HSIO_S6G_OB_CFG 0x00d8 65 + #define HSIO_S6G_OB_CFG1 0x00dc 66 + #define HSIO_S6G_SER_CFG 0x00e0 67 + #define HSIO_S6G_COMMON_CFG 0x00e4 68 + #define HSIO_S6G_PLL_CFG 0x00e8 69 + #define HSIO_S6G_ACJTAG_CFG 0x00ec 70 + #define HSIO_S6G_GP_CFG 0x00f0 71 + #define HSIO_S6G_IB_STATUS0 0x00f4 72 + #define HSIO_S6G_IB_STATUS1 0x00f8 73 + #define HSIO_S6G_ACJTAG_STATUS 0x00fc 74 + #define HSIO_S6G_PLL_STATUS 0x0100 75 + #define HSIO_S6G_REVID 0x0104 76 + #define HSIO_MCB_S6G_ADDR_CFG 0x0108 77 + #define HSIO_HW_CFG 0x010c 78 + #define HSIO_HW_QSGMII_CFG 0x0110 79 + #define HSIO_HW_QSGMII_STAT 0x0114 80 + #define HSIO_CLK_CFG 0x0118 81 + #define HSIO_TEMP_SENSOR_CTRL 0x011c 82 + #define HSIO_TEMP_SENSOR_CFG 0x0120 83 + #define HSIO_TEMP_SENSOR_STAT 0x0124 84 + 11 85 #define HSIO_PLL5G_CFG0_ENA_ROT BIT(31) 12 86 #define HSIO_PLL5G_CFG0_ENA_LANE BIT(30) 13 87 #define HSIO_PLL5G_CFG0_ENA_CLKTREE BIT(29)
+10 -83
drivers/net/ethernet/mscc/ocelot_regs.c
··· 5 5 * Copyright (c) 2017 Microsemi Corporation 6 6 */ 7 7 #include "ocelot.h" 8 + #include <soc/mscc/ocelot_hsio.h> 8 9 9 10 static const u32 ocelot_ana_regmap[] = { 10 11 REG(ANA_ADVLEARN, 0x009000), ··· 101 100 REG(QS_INJ_STATUS, 0x00003c), 102 101 REG(QS_INJ_ERR, 0x000040), 103 102 REG(QS_INH_DBG, 0x000048), 104 - }; 105 - 106 - static const u32 ocelot_hsio_regmap[] = { 107 - REG(HSIO_PLL5G_CFG0, 0x000000), 108 - REG(HSIO_PLL5G_CFG1, 0x000004), 109 - REG(HSIO_PLL5G_CFG2, 0x000008), 110 - REG(HSIO_PLL5G_CFG3, 0x00000c), 111 - REG(HSIO_PLL5G_CFG4, 0x000010), 112 - REG(HSIO_PLL5G_CFG5, 0x000014), 113 - REG(HSIO_PLL5G_CFG6, 0x000018), 114 - REG(HSIO_PLL5G_STATUS0, 0x00001c), 115 - REG(HSIO_PLL5G_STATUS1, 0x000020), 116 - REG(HSIO_PLL5G_BIST_CFG0, 0x000024), 117 - REG(HSIO_PLL5G_BIST_CFG1, 0x000028), 118 - REG(HSIO_PLL5G_BIST_CFG2, 0x00002c), 119 - REG(HSIO_PLL5G_BIST_STAT0, 0x000030), 120 - REG(HSIO_PLL5G_BIST_STAT1, 0x000034), 121 - REG(HSIO_RCOMP_CFG0, 0x000038), 122 - REG(HSIO_RCOMP_STATUS, 0x00003c), 123 - REG(HSIO_SYNC_ETH_CFG, 0x000040), 124 - REG(HSIO_SYNC_ETH_PLL_CFG, 0x000048), 125 - REG(HSIO_S1G_DES_CFG, 0x00004c), 126 - REG(HSIO_S1G_IB_CFG, 0x000050), 127 - REG(HSIO_S1G_OB_CFG, 0x000054), 128 - REG(HSIO_S1G_SER_CFG, 0x000058), 129 - REG(HSIO_S1G_COMMON_CFG, 0x00005c), 130 - REG(HSIO_S1G_PLL_CFG, 0x000060), 131 - REG(HSIO_S1G_PLL_STATUS, 0x000064), 132 - REG(HSIO_S1G_DFT_CFG0, 0x000068), 133 - REG(HSIO_S1G_DFT_CFG1, 0x00006c), 134 - REG(HSIO_S1G_DFT_CFG2, 0x000070), 135 - REG(HSIO_S1G_TP_CFG, 0x000074), 136 - REG(HSIO_S1G_RC_PLL_BIST_CFG, 0x000078), 137 - REG(HSIO_S1G_MISC_CFG, 0x00007c), 138 - REG(HSIO_S1G_DFT_STATUS, 0x000080), 139 - REG(HSIO_S1G_MISC_STATUS, 0x000084), 140 - REG(HSIO_MCB_S1G_ADDR_CFG, 0x000088), 141 - REG(HSIO_S6G_DIG_CFG, 0x00008c), 142 - REG(HSIO_S6G_DFT_CFG0, 0x000090), 143 - REG(HSIO_S6G_DFT_CFG1, 0x000094), 144 - REG(HSIO_S6G_DFT_CFG2, 0x000098), 145 - REG(HSIO_S6G_TP_CFG0, 0x00009c), 146 - REG(HSIO_S6G_TP_CFG1, 0x0000a0), 147 - REG(HSIO_S6G_RC_PLL_BIST_CFG, 0x0000a4), 148 - REG(HSIO_S6G_MISC_CFG, 0x0000a8), 149 - REG(HSIO_S6G_OB_ANEG_CFG, 0x0000ac), 150 - REG(HSIO_S6G_DFT_STATUS, 0x0000b0), 151 - REG(HSIO_S6G_ERR_CNT, 0x0000b4), 152 - REG(HSIO_S6G_MISC_STATUS, 0x0000b8), 153 - REG(HSIO_S6G_DES_CFG, 0x0000bc), 154 - REG(HSIO_S6G_IB_CFG, 0x0000c0), 155 - REG(HSIO_S6G_IB_CFG1, 0x0000c4), 156 - REG(HSIO_S6G_IB_CFG2, 0x0000c8), 157 - REG(HSIO_S6G_IB_CFG3, 0x0000cc), 158 - REG(HSIO_S6G_IB_CFG4, 0x0000d0), 159 - REG(HSIO_S6G_IB_CFG5, 0x0000d4), 160 - REG(HSIO_S6G_OB_CFG, 0x0000d8), 161 - REG(HSIO_S6G_OB_CFG1, 0x0000dc), 162 - REG(HSIO_S6G_SER_CFG, 0x0000e0), 163 - REG(HSIO_S6G_COMMON_CFG, 0x0000e4), 164 - REG(HSIO_S6G_PLL_CFG, 0x0000e8), 165 - REG(HSIO_S6G_ACJTAG_CFG, 0x0000ec), 166 - REG(HSIO_S6G_GP_CFG, 0x0000f0), 167 - REG(HSIO_S6G_IB_STATUS0, 0x0000f4), 168 - REG(HSIO_S6G_IB_STATUS1, 0x0000f8), 169 - REG(HSIO_S6G_ACJTAG_STATUS, 0x0000fc), 170 - REG(HSIO_S6G_PLL_STATUS, 0x000100), 171 - REG(HSIO_S6G_REVID, 0x000104), 172 - REG(HSIO_MCB_S6G_ADDR_CFG, 0x000108), 173 - REG(HSIO_HW_CFG, 0x00010c), 174 - REG(HSIO_HW_QSGMII_CFG, 0x000110), 175 - REG(HSIO_HW_QSGMII_STAT, 0x000114), 176 - REG(HSIO_CLK_CFG, 0x000118), 177 - REG(HSIO_TEMP_SENSOR_CTRL, 0x00011c), 178 - REG(HSIO_TEMP_SENSOR_CFG, 0x000120), 179 - REG(HSIO_TEMP_SENSOR_STAT, 0x000124), 180 103 }; 181 104 182 105 static const u32 ocelot_qsys_regmap[] = { ··· 227 302 static const u32 *ocelot_regmap[] = { 228 303 [ANA] = ocelot_ana_regmap, 229 304 [QS] = ocelot_qs_regmap, 230 - [HSIO] = ocelot_hsio_regmap, 231 305 [QSYS] = ocelot_qsys_regmap, 232 306 [REW] = ocelot_rew_regmap, 233 307 [SYS] = ocelot_sys_regmap, ··· 377 453 /* Configure PLL5. This will need a proper CCF driver 378 454 * The values are coming from the VTSS API for Ocelot 379 455 */ 380 - ocelot_write(ocelot, HSIO_PLL5G_CFG4_IB_CTRL(0x7600) | 381 - HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8), HSIO_PLL5G_CFG4); 382 - ocelot_write(ocelot, HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) | 456 + regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4, 457 + HSIO_PLL5G_CFG4_IB_CTRL(0x7600) | 458 + HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8)); 459 + regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0, 460 + HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) | 383 461 HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) | 384 462 HSIO_PLL5G_CFG0_ENA_BIAS | 385 463 HSIO_PLL5G_CFG0_ENA_VCO_BUF | ··· 391 465 HSIO_PLL5G_CFG0_SELBGV820(4) | 392 466 HSIO_PLL5G_CFG0_DIV4 | 393 467 HSIO_PLL5G_CFG0_ENA_CLKTREE | 394 - HSIO_PLL5G_CFG0_ENA_LANE, HSIO_PLL5G_CFG0); 395 - ocelot_write(ocelot, HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET | 468 + HSIO_PLL5G_CFG0_ENA_LANE); 469 + regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2, 470 + HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET | 396 471 HSIO_PLL5G_CFG2_EN_RESET_OVERRUN | 397 472 HSIO_PLL5G_CFG2_GAIN_TEST(0x8) | 398 473 HSIO_PLL5G_CFG2_ENA_AMPCTRL | 399 474 HSIO_PLL5G_CFG2_PWD_AMPCTRL_N | 400 - HSIO_PLL5G_CFG2_AMPC_SEL(0x10), HSIO_PLL5G_CFG2); 475 + HSIO_PLL5G_CFG2_AMPC_SEL(0x10)); 401 476 } 402 477 403 478 int ocelot_chip_init(struct ocelot *ocelot)
+1
drivers/phy/Kconfig
··· 48 48 source "drivers/phy/marvell/Kconfig" 49 49 source "drivers/phy/mediatek/Kconfig" 50 50 source "drivers/phy/motorola/Kconfig" 51 + source "drivers/phy/mscc/Kconfig" 51 52 source "drivers/phy/qualcomm/Kconfig" 52 53 source "drivers/phy/ralink/Kconfig" 53 54 source "drivers/phy/renesas/Kconfig"
+1
drivers/phy/Makefile
··· 18 18 hisilicon/ \ 19 19 marvell/ \ 20 20 motorola/ \ 21 + mscc/ \ 21 22 qualcomm/ \ 22 23 ralink/ \ 23 24 samsung/ \
+11
drivers/phy/mscc/Kconfig
··· 1 + # 2 + # Phy drivers for Microsemi devices 3 + # 4 + 5 + config PHY_OCELOT_SERDES 6 + tristate "SerDes PHY driver for Microsemi Ocelot" 7 + select GENERIC_PHY 8 + depends on OF 9 + depends on MFD_SYSCON 10 + help 11 + Enable this for supporting SerDes muxing with Microsemi Ocelot.
+5
drivers/phy/mscc/Makefile
··· 1 + # 2 + # Makefile for the Microsemi phy drivers. 3 + # 4 + 5 + obj-$(CONFIG_PHY_OCELOT_SERDES) := phy-ocelot-serdes.o
+295
drivers/phy/mscc/phy-ocelot-serdes.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 + /* 3 + * SerDes PHY driver for Microsemi Ocelot 4 + * 5 + * Copyright (c) 2018 Microsemi 6 + * 7 + */ 8 + 9 + #include <linux/err.h> 10 + #include <linux/mfd/syscon.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/of_platform.h> 14 + #include <linux/phy/phy.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/regmap.h> 17 + #include <soc/mscc/ocelot_hsio.h> 18 + #include <dt-bindings/phy/phy-ocelot-serdes.h> 19 + 20 + struct serdes_ctrl { 21 + struct regmap *regs; 22 + struct device *dev; 23 + struct phy *phys[SERDES_MAX]; 24 + }; 25 + 26 + struct serdes_macro { 27 + u8 idx; 28 + /* Not used when in QSGMII or PCIe mode */ 29 + int port; 30 + struct serdes_ctrl *ctrl; 31 + }; 32 + 33 + #define MCB_S1G_CFG_TIMEOUT 50 34 + 35 + static int __serdes_write_mcb_s1g(struct regmap *regmap, u8 macro, u32 op) 36 + { 37 + unsigned int regval; 38 + 39 + regmap_write(regmap, HSIO_MCB_S1G_ADDR_CFG, op | 40 + HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR(BIT(macro))); 41 + 42 + return regmap_read_poll_timeout(regmap, HSIO_MCB_S1G_ADDR_CFG, regval, 43 + (regval & op) != op, 100, 44 + MCB_S1G_CFG_TIMEOUT * 1000); 45 + } 46 + 47 + static int serdes_commit_mcb_s1g(struct regmap *regmap, u8 macro) 48 + { 49 + return __serdes_write_mcb_s1g(regmap, macro, 50 + HSIO_MCB_S1G_ADDR_CFG_SERDES1G_WR_ONE_SHOT); 51 + } 52 + 53 + static int serdes_update_mcb_s1g(struct regmap *regmap, u8 macro) 54 + { 55 + return __serdes_write_mcb_s1g(regmap, macro, 56 + HSIO_MCB_S1G_ADDR_CFG_SERDES1G_RD_ONE_SHOT); 57 + } 58 + 59 + static int serdes_init_s1g(struct regmap *regmap, u8 serdes) 60 + { 61 + int ret; 62 + 63 + ret = serdes_update_mcb_s1g(regmap, serdes); 64 + if (ret) 65 + return ret; 66 + 67 + regmap_update_bits(regmap, HSIO_S1G_COMMON_CFG, 68 + HSIO_S1G_COMMON_CFG_SYS_RST | 69 + HSIO_S1G_COMMON_CFG_ENA_LANE | 70 + HSIO_S1G_COMMON_CFG_ENA_ELOOP | 71 + HSIO_S1G_COMMON_CFG_ENA_FLOOP, 72 + HSIO_S1G_COMMON_CFG_ENA_LANE); 73 + 74 + regmap_update_bits(regmap, HSIO_S1G_PLL_CFG, 75 + HSIO_S1G_PLL_CFG_PLL_FSM_ENA | 76 + HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_M, 77 + HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA(200) | 78 + HSIO_S1G_PLL_CFG_PLL_FSM_ENA); 79 + 80 + regmap_update_bits(regmap, HSIO_S1G_MISC_CFG, 81 + HSIO_S1G_MISC_CFG_DES_100FX_CPMD_ENA | 82 + HSIO_S1G_MISC_CFG_LANE_RST, 83 + HSIO_S1G_MISC_CFG_LANE_RST); 84 + 85 + ret = serdes_commit_mcb_s1g(regmap, serdes); 86 + if (ret) 87 + return ret; 88 + 89 + regmap_update_bits(regmap, HSIO_S1G_COMMON_CFG, 90 + HSIO_S1G_COMMON_CFG_SYS_RST, 91 + HSIO_S1G_COMMON_CFG_SYS_RST); 92 + 93 + regmap_update_bits(regmap, HSIO_S1G_MISC_CFG, 94 + HSIO_S1G_MISC_CFG_LANE_RST, 0); 95 + 96 + ret = serdes_commit_mcb_s1g(regmap, serdes); 97 + if (ret) 98 + return ret; 99 + 100 + return 0; 101 + } 102 + 103 + struct serdes_mux { 104 + u8 idx; 105 + u8 port; 106 + enum phy_mode mode; 107 + u32 mask; 108 + u32 mux; 109 + }; 110 + 111 + #define SERDES_MUX(_idx, _port, _mode, _mask, _mux) { \ 112 + .idx = _idx, \ 113 + .port = _port, \ 114 + .mode = _mode, \ 115 + .mask = _mask, \ 116 + .mux = _mux, \ 117 + } 118 + 119 + #define SERDES_MUX_SGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_SGMII, m, c) 120 + #define SERDES_MUX_QSGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_QSGMII, m, c) 121 + 122 + static const struct serdes_mux ocelot_serdes_muxes[] = { 123 + SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0), 124 + SERDES_MUX_SGMII(SERDES1G(1), 1, HSIO_HW_CFG_DEV1G_5_MODE, 0), 125 + SERDES_MUX_SGMII(SERDES1G(1), 5, HSIO_HW_CFG_QSGMII_ENA | 126 + HSIO_HW_CFG_DEV1G_5_MODE, HSIO_HW_CFG_DEV1G_5_MODE), 127 + SERDES_MUX_SGMII(SERDES1G(2), 2, HSIO_HW_CFG_DEV1G_4_MODE, 0), 128 + SERDES_MUX_SGMII(SERDES1G(2), 4, HSIO_HW_CFG_QSGMII_ENA | 129 + HSIO_HW_CFG_DEV1G_4_MODE, HSIO_HW_CFG_DEV1G_4_MODE), 130 + SERDES_MUX_SGMII(SERDES1G(3), 3, HSIO_HW_CFG_DEV1G_6_MODE, 0), 131 + SERDES_MUX_SGMII(SERDES1G(3), 6, HSIO_HW_CFG_QSGMII_ENA | 132 + HSIO_HW_CFG_DEV1G_6_MODE, HSIO_HW_CFG_DEV1G_6_MODE), 133 + SERDES_MUX_SGMII(SERDES1G(4), 4, HSIO_HW_CFG_QSGMII_ENA | 134 + HSIO_HW_CFG_DEV1G_4_MODE | HSIO_HW_CFG_DEV1G_9_MODE, 135 + 0), 136 + SERDES_MUX_SGMII(SERDES1G(4), 9, HSIO_HW_CFG_DEV1G_4_MODE | 137 + HSIO_HW_CFG_DEV1G_9_MODE, HSIO_HW_CFG_DEV1G_4_MODE | 138 + HSIO_HW_CFG_DEV1G_9_MODE), 139 + SERDES_MUX_SGMII(SERDES1G(5), 5, HSIO_HW_CFG_QSGMII_ENA | 140 + HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE, 141 + 0), 142 + SERDES_MUX_SGMII(SERDES1G(5), 10, HSIO_HW_CFG_PCIE_ENA | 143 + HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE, 144 + HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE), 145 + SERDES_MUX_QSGMII(SERDES6G(0), 4, HSIO_HW_CFG_QSGMII_ENA, 146 + HSIO_HW_CFG_QSGMII_ENA), 147 + SERDES_MUX_QSGMII(SERDES6G(0), 5, HSIO_HW_CFG_QSGMII_ENA, 148 + HSIO_HW_CFG_QSGMII_ENA), 149 + SERDES_MUX_QSGMII(SERDES6G(0), 6, HSIO_HW_CFG_QSGMII_ENA, 150 + HSIO_HW_CFG_QSGMII_ENA), 151 + SERDES_MUX_SGMII(SERDES6G(0), 7, HSIO_HW_CFG_QSGMII_ENA, 0), 152 + SERDES_MUX_QSGMII(SERDES6G(0), 7, HSIO_HW_CFG_QSGMII_ENA, 153 + HSIO_HW_CFG_QSGMII_ENA), 154 + SERDES_MUX_SGMII(SERDES6G(1), 8, 0, 0), 155 + SERDES_MUX_SGMII(SERDES6G(2), 10, HSIO_HW_CFG_PCIE_ENA | 156 + HSIO_HW_CFG_DEV2G5_10_MODE, 0), 157 + SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, HSIO_HW_CFG_PCIE_ENA, 158 + HSIO_HW_CFG_PCIE_ENA), 159 + }; 160 + 161 + static int serdes_set_mode(struct phy *phy, enum phy_mode mode) 162 + { 163 + struct serdes_macro *macro = phy_get_drvdata(phy); 164 + unsigned int i; 165 + int ret; 166 + 167 + for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) { 168 + if (macro->idx != ocelot_serdes_muxes[i].idx || 169 + mode != ocelot_serdes_muxes[i].mode) 170 + continue; 171 + 172 + if (mode != PHY_MODE_QSGMII && 173 + macro->port != ocelot_serdes_muxes[i].port) 174 + continue; 175 + 176 + ret = regmap_update_bits(macro->ctrl->regs, HSIO_HW_CFG, 177 + ocelot_serdes_muxes[i].mask, 178 + ocelot_serdes_muxes[i].mux); 179 + if (ret) 180 + return ret; 181 + 182 + if (macro->idx <= SERDES1G_MAX) 183 + return serdes_init_s1g(macro->ctrl->regs, macro->idx); 184 + 185 + /* SERDES6G and PCIe not supported yet */ 186 + return -EOPNOTSUPP; 187 + } 188 + 189 + return -EINVAL; 190 + } 191 + 192 + static const struct phy_ops serdes_ops = { 193 + .set_mode = serdes_set_mode, 194 + .owner = THIS_MODULE, 195 + }; 196 + 197 + static struct phy *serdes_simple_xlate(struct device *dev, 198 + struct of_phandle_args *args) 199 + { 200 + struct serdes_ctrl *ctrl = dev_get_drvdata(dev); 201 + unsigned int port, idx, i; 202 + 203 + if (args->args_count != 2) 204 + return ERR_PTR(-EINVAL); 205 + 206 + port = args->args[0]; 207 + idx = args->args[1]; 208 + 209 + for (i = 0; i <= SERDES_MAX; i++) { 210 + struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]); 211 + 212 + if (idx != macro->idx) 213 + continue; 214 + 215 + /* SERDES6G(0) is the only SerDes capable of QSGMII */ 216 + if (idx != SERDES6G(0) && macro->port >= 0) 217 + return ERR_PTR(-EBUSY); 218 + 219 + macro->port = port; 220 + return ctrl->phys[i]; 221 + } 222 + 223 + return ERR_PTR(-ENODEV); 224 + } 225 + 226 + static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx, struct phy **phy) 227 + { 228 + struct serdes_macro *macro; 229 + 230 + *phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops); 231 + if (IS_ERR(*phy)) 232 + return PTR_ERR(*phy); 233 + 234 + macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL); 235 + if (!macro) 236 + return -ENOMEM; 237 + 238 + macro->idx = idx; 239 + macro->ctrl = ctrl; 240 + macro->port = -1; 241 + 242 + phy_set_drvdata(*phy, macro); 243 + 244 + return 0; 245 + } 246 + 247 + static int serdes_probe(struct platform_device *pdev) 248 + { 249 + struct phy_provider *provider; 250 + struct serdes_ctrl *ctrl; 251 + unsigned int i; 252 + int ret; 253 + 254 + ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); 255 + if (!ctrl) 256 + return -ENOMEM; 257 + 258 + ctrl->dev = &pdev->dev; 259 + ctrl->regs = syscon_node_to_regmap(pdev->dev.parent->of_node); 260 + if (!ctrl->regs) 261 + return -ENODEV; 262 + 263 + for (i = 0; i <= SERDES_MAX; i++) { 264 + ret = serdes_phy_create(ctrl, i, &ctrl->phys[i]); 265 + if (ret) 266 + return ret; 267 + } 268 + 269 + dev_set_drvdata(&pdev->dev, ctrl); 270 + 271 + provider = devm_of_phy_provider_register(ctrl->dev, 272 + serdes_simple_xlate); 273 + 274 + return PTR_ERR_OR_ZERO(provider); 275 + } 276 + 277 + static const struct of_device_id serdes_ids[] = { 278 + { .compatible = "mscc,vsc7514-serdes", }, 279 + {}, 280 + }; 281 + MODULE_DEVICE_TABLE(of, serdes_ids); 282 + 283 + static struct platform_driver mscc_ocelot_serdes = { 284 + .probe = serdes_probe, 285 + .driver = { 286 + .name = "mscc,ocelot-serdes", 287 + .of_match_table = of_match_ptr(serdes_ids), 288 + }, 289 + }; 290 + 291 + module_platform_driver(mscc_ocelot_serdes); 292 + 293 + MODULE_AUTHOR("Quentin Schulz <quentin.schulz@bootlin.com>"); 294 + MODULE_DESCRIPTION("SerDes driver for Microsemi Ocelot"); 295 + MODULE_LICENSE("Dual MIT/GPL");
+12
include/dt-bindings/phy/phy-ocelot-serdes.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ 2 + /* Copyright (c) 2018 Microsemi Corporation */ 3 + #ifndef __PHY_OCELOT_SERDES_H__ 4 + #define __PHY_OCELOT_SERDES_H__ 5 + 6 + #define SERDES1G(x) (x) 7 + #define SERDES1G_MAX SERDES1G(5) 8 + #define SERDES6G(x) (SERDES1G_MAX + 1 + (x)) 9 + #define SERDES6G_MAX SERDES6G(2) 10 + #define SERDES_MAX SERDES6G_MAX 11 + 12 + #endif
+2
include/linux/phy/phy.h
··· 37 37 PHY_MODE_USB_OTG, 38 38 PHY_MODE_SGMII, 39 39 PHY_MODE_2500SGMII, 40 + PHY_MODE_QSGMII, 40 41 PHY_MODE_10GKR, 41 42 PHY_MODE_UFS_HS_A, 42 43 PHY_MODE_UFS_HS_B, 44 + PHY_MODE_PCIE, 43 45 }; 44 46 45 47 /**