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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'phy-for-4.21_v1' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next

Kishon writes:

phy: for 4.21

*) Change phy set_mode ops to take both mode and setmode as arguments
*) Add phy_configure() and phy_validate() API's mostly used for MIPI D-PHY
*) Add helpers to get default values of parameters define in MIPI D-PHY spec
*) Add driver for TI's CPSW Port PHY Interface Mode selection
*) Add driver for Cadence Sierra PHY used with USB and PCIe
*) Add driver for Freescale i.MX8MQ USB3 PHY
*) Fixes QMP PHY bindings to allow the clocks provided by the PHY to be
pointed at in device tree
*) Fix for using fully specified regions (in device tree) for configuring
the second lane in dual lane PHYs in QMP PHY
*) Add support for Allwinner H6 USB2 PHY in phy-sun4i-usb driver
*) Update phy-rcar-gen3-usb driver to follow the hardware manual
*) Add support for fine grained power management in mapphone-mdm6600 driver

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

* tag 'phy-for-4.21_v1' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy: (30 commits)
phy: qcom-qmp: Expose provided clocks to DT
dt-bindings: phy-qcom-qmp: Move #clock-cells to child
phy: qcom-qmp: Utilize fully-specified DT registers
dt-bindings: phy-qcom-qmp: Fix register underspecification
phy: ti: fix semicolon.cocci warnings
phy: dphy: Add configuration helpers
phy: Add MIPI D-PHY configuration options
phy: Add configuration interface
phy: Add MIPI D-PHY mode
phy: add driver for Freescale i.MX8MQ USB3 PHY
dt-bindings: phy: add binding for Freescale i.MX8MQ USB3 PHY
phy: Use of_node_name_eq for node name comparisons
net: ethernet: ti: cpsw: add support for port interface mode selection phy
dt-bindings: net: ti: cpsw: switch to use phy-gmii-sel phy
phy: ti: introduce phy-gmii-sel driver
dt-bindings: phy: add cpsw port interface mode selection phy bindings
phy: mvebu-cp110-comphy: fix spelling in structure name
phy: mapphone-mdm6600: Improve phy related runtime PM calls
phy: renesas: rcar-gen3-usb2: follow the hardware manual procedure
phy: cadence: Add driver for Sierra PHY
...

+2001 -163
+7 -1
Documentation/devicetree/bindings/net/cpsw.txt
··· 22 22 - cpsw-phy-sel : Specifies the phandle to the CPSW phy mode selection 23 23 device. See also cpsw-phy-sel.txt for it's binding. 24 24 Note that in legacy cases cpsw-phy-sel may be 25 - a child device instead of a phandle. 25 + a child device instead of a phandle 26 + (DEPRECATED, use phys property instead). 26 27 27 28 Optional properties: 28 29 - ti,hwmods : Must be "cpgmac0" ··· 45 44 Slave Properties: 46 45 Required properties: 47 46 - phy-mode : See ethernet.txt file in the same directory 47 + - phys : phandle on phy-gmii-sel PHY (see phy/ti-phy-gmii-sel.txt) 48 48 49 49 Optional properties: 50 50 - dual_emac_res_vlan : Specifies VID to be used to segregate the ports ··· 87 85 phy-mode = "rgmii-txid"; 88 86 /* Filled in by U-Boot */ 89 87 mac-address = [ 00 00 00 00 00 00 ]; 88 + phys = <&phy_gmii_sel 1 0>; 90 89 }; 91 90 cpsw_emac1: slave@1 { 92 91 phy_id = <&davinci_mdio>, <1>; 93 92 phy-mode = "rgmii-txid"; 94 93 /* Filled in by U-Boot */ 95 94 mac-address = [ 00 00 00 00 00 00 ]; 95 + phys = <&phy_gmii_sel 2 0>; 96 96 }; 97 97 }; 98 98 ··· 118 114 phy-mode = "rgmii-txid"; 119 115 /* Filled in by U-Boot */ 120 116 mac-address = [ 00 00 00 00 00 00 ]; 117 + phys = <&phy_gmii_sel 1 0>; 121 118 }; 122 119 cpsw_emac1: slave@1 { 123 120 phy_id = <&davinci_mdio>, <1>; 124 121 phy-mode = "rgmii-txid"; 125 122 /* Filled in by U-Boot */ 126 123 mac-address = [ 00 00 00 00 00 00 ]; 124 + phys = <&phy_gmii_sel 2 0>; 127 125 }; 128 126 };
+17
Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt
··· 1 + * Freescale i.MX8MQ USB3 PHY binding 2 + 3 + Required properties: 4 + - compatible: Should be "fsl,imx8mq-usb-phy" 5 + - #phys-cells: must be 0 (see phy-bindings.txt in this directory) 6 + - reg: The base address and length of the registers 7 + - clocks: phandles to the clocks for each clock listed in clock-names 8 + - clock-names: must contain "phy" 9 + 10 + Example: 11 + usb3_phy0: phy@381f0040 { 12 + compatible = "fsl,imx8mq-usb-phy"; 13 + reg = <0x381f0040 0x40>; 14 + clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>; 15 + clock-names = "phy"; 16 + #phy-cells = <0>; 17 + };
+67
Documentation/devicetree/bindings/phy/phy-cadence-sierra.txt
··· 1 + Cadence Sierra PHY 2 + ----------------------- 3 + 4 + Required properties: 5 + - compatible: cdns,sierra-phy-t0 6 + - clocks: Must contain an entry in clock-names. 7 + See ../clocks/clock-bindings.txt for details. 8 + - clock-names: Must be "phy_clk" 9 + - resets: Must contain an entry for each in reset-names. 10 + See ../reset/reset.txt for details. 11 + - reset-names: Must include "sierra_reset" and "sierra_apb". 12 + "sierra_reset" must control the reset line to the PHY. 13 + "sierra_apb" must control the reset line to the APB PHY 14 + interface. 15 + - reg: register range for the PHY. 16 + - #address-cells: Must be 1 17 + - #size-cells: Must be 0 18 + 19 + Optional properties: 20 + - cdns,autoconf: A boolean property whose presence indicates that the 21 + PHY registers will be configured by hardware. If not 22 + present, all sub-node optional properties must be 23 + provided. 24 + 25 + Sub-nodes: 26 + Each group of PHY lanes with a single master lane should be represented as 27 + a sub-node. Note that the actual configuration of each lane is determined by 28 + hardware strapping, and must match the configuration specified here. 29 + 30 + Sub-node required properties: 31 + - #phy-cells: Generic PHY binding; must be 0. 32 + - reg: The master lane number. This is the lowest numbered lane 33 + in the lane group. 34 + - resets: Must contain one entry which controls the reset line for the 35 + master lane of the sub-node. 36 + See ../reset/reset.txt for details. 37 + 38 + Sub-node optional properties: 39 + - cdns,num-lanes: Number of lanes in this group. From 1 to 4. The 40 + group is made up of consecutive lanes. 41 + - cdns,phy-type: Can be PHY_TYPE_PCIE or PHY_TYPE_USB3, depending on 42 + configuration of lanes. 43 + 44 + Example: 45 + pcie_phy4: pcie-phy@fd240000 { 46 + compatible = "cdns,sierra-phy-t0"; 47 + reg = <0x0 0xfd240000 0x0 0x40000>; 48 + resets = <&phyrst 0>, <&phyrst 1>; 49 + reset-names = "sierra_reset", "sierra_apb"; 50 + clocks = <&phyclock>; 51 + clock-names = "phy_clk"; 52 + #address-cells = <1>; 53 + #size-cells = <0>; 54 + pcie0_phy0: pcie-phy@0 { 55 + reg = <0>; 56 + resets = <&phyrst 2>; 57 + cdns,num-lanes = <2>; 58 + #phy-cells = <0>; 59 + cdns,phy-type = <PHY_TYPE_PCIE>; 60 + }; 61 + pcie0_phy1: pcie-phy@2 { 62 + reg = <2>; 63 + resets = <&phyrst 4>; 64 + cdns,num-lanes = <1>; 65 + #phy-cells = <0>; 66 + cdns,phy-type = <PHY_TYPE_PCIE>; 67 + };
+66 -13
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
··· 25 25 - For all others: 26 26 - The reg-names property shouldn't be defined. 27 27 28 - - #clock-cells: must be 1 29 - - Phy pll outputs a bunch of clocks for Tx, Rx and Pipe 30 - interface (for pipe based PHYs). These clock are then gate-controlled 31 - by gcc. 32 28 - #address-cells: must be 1 33 29 - #size-cells: must be 1 34 30 - ranges: must be present ··· 78 82 - Each device node of QMP phy is required to have as many child nodes as 79 83 the number of lanes the PHY has. 80 84 81 - Required properties for child node: 85 + Required properties for child nodes of PCIe PHYs (one child per lane): 82 86 - reg: list of offset and length pairs of register sets for PHY blocks - 83 - - index 0: tx 84 - - index 1: rx 85 - - index 2: pcs 86 - - index 3: pcs_misc (optional) 87 - 87 + tx, rx, pcs, and pcs_misc (optional). 88 88 - #phy-cells: must be 0 89 89 90 - Required properties child node of pcie and usb3 qmp phys: 90 + Required properties for a single "lanes" child node of non-PCIe PHYs: 91 + - reg: list of offset and length pairs of register sets for PHY blocks 92 + For 1-lane devices: 93 + tx, rx, pcs, and (optionally) pcs_misc 94 + For 2-lane devices: 95 + tx0, rx0, pcs, tx1, rx1, and (optionally) pcs_misc 96 + - #phy-cells: must be 0 97 + 98 + Required properties for child node of PCIe and USB3 qmp phys: 91 99 - clocks: a list of phandles and clock-specifier pairs, 92 100 one for each entry in clock-names. 93 101 - clock-names: Must contain following: 94 102 "pipe<lane-number>" for pipe clock specific to each lane. 95 103 - clock-output-names: Name of the PHY clock that will be the parent for 96 104 the above pipe clock. 97 - 98 105 For "qcom,ipq8074-qmp-pcie-phy": 99 106 - "pcie20_phy0_pipe_clk" Pipe Clock parent 100 107 (or) 101 108 "pcie20_phy1_pipe_clk" 109 + - #clock-cells: must be 0 110 + - Phy pll outputs pipe clocks for pipe based PHYs. These clocks are then 111 + gate-controlled by the gcc. 102 112 103 113 Required properties for child node of PHYs with lane reset, AKA: 104 114 "qcom,msm8996-qmp-pcie-phy" ··· 117 115 phy@34000 { 118 116 compatible = "qcom,msm8996-qmp-pcie-phy"; 119 117 reg = <0x34000 0x488>; 120 - #clock-cells = <1>; 121 118 #address-cells = <1>; 122 119 #size-cells = <1>; 123 120 ranges; ··· 138 137 reg = <0x35000 0x130>, 139 138 <0x35200 0x200>, 140 139 <0x35400 0x1dc>; 140 + #clock-cells = <0>; 141 141 #phy-cells = <0>; 142 142 143 143 clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; ··· 151 149 pciephy_1: lane@36000 { 152 150 ... 153 151 ... 152 + }; 153 + 154 + phy@88eb000 { 155 + compatible = "qcom,sdm845-qmp-usb3-uni-phy"; 156 + reg = <0x88eb000 0x18c>; 157 + #address-cells = <1>; 158 + #size-cells = <1>; 159 + ranges; 160 + 161 + clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>, 162 + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, 163 + <&gcc GCC_USB3_SEC_CLKREF_CLK>, 164 + <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>; 165 + clock-names = "aux", "cfg_ahb", "ref", "com_aux"; 166 + 167 + resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>, 168 + <&gcc GCC_USB3_PHY_SEC_BCR>; 169 + reset-names = "phy", "common"; 170 + 171 + lane@88eb200 { 172 + reg = <0x88eb200 0x128>, 173 + <0x88eb400 0x1fc>, 174 + <0x88eb800 0x218>, 175 + <0x88eb600 0x70>; 176 + #clock-cells = <0>; 177 + #phy-cells = <0>; 178 + clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; 179 + clock-names = "pipe0"; 180 + clock-output-names = "usb3_uni_phy_pipe_clk_src"; 181 + }; 182 + }; 183 + 184 + phy@1d87000 { 185 + compatible = "qcom,sdm845-qmp-ufs-phy"; 186 + reg = <0x1d87000 0x18c>; 187 + #address-cells = <1>; 188 + #size-cells = <1>; 189 + ranges; 190 + clock-names = "ref", 191 + "ref_aux"; 192 + clocks = <&gcc GCC_UFS_MEM_CLKREF_CLK>, 193 + <&gcc GCC_UFS_PHY_PHY_AUX_CLK>; 194 + 195 + lanes@1d87400 { 196 + reg = <0x1d87400 0x108>, 197 + <0x1d87600 0x1e0>, 198 + <0x1d87c00 0x1dc>, 199 + <0x1d87800 0x108>, 200 + <0x1d87a00 0x1e0>; 201 + #phy-cells = <0>; 202 + }; 154 203 };
+5 -3
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
··· 14 14 * allwinner,sun8i-r40-usb-phy 15 15 * allwinner,sun8i-v3s-usb-phy 16 16 * allwinner,sun50i-a64-usb-phy 17 + * allwinner,sun50i-h6-usb-phy 17 18 - reg : a list of offset + length pairs 18 19 - reg-names : 19 20 * "phy_ctrl" 20 - * "pmu0" for H3, V3s and A64 21 + * "pmu0" for H3, V3s, A64 or H6 21 22 * "pmu1" 22 23 * "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 23 - * "pmu3" for sun8i-h3 24 + * "pmu3" for sun8i-h3 or sun50i-h6 24 25 - #phy-cells : from the generic phy bindings, must be 1 25 26 - clocks : phandle + clock specifier for the phy clocks 26 27 - clock-names : ··· 30 29 * "usb0_phy", "usb1_phy" for sun8i 31 30 * "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t 32 31 * "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3 32 + * "usb0_phy" and "usb3_phy" for sun50i-h6 33 33 - resets : a list of phandle + reset specifier pairs 34 34 - reset-names : 35 35 * "usb0_reset" 36 36 * "usb1_reset" 37 37 * "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 38 - * "usb3_reset" for sun8i-h3 38 + * "usb3_reset" for sun8i-h3 and sun50i-h6 39 39 40 40 Optional properties: 41 41 - usb0_id_det-gpios : gpio phandle for reading the otg id pin value
+68
Documentation/devicetree/bindings/phy/ti-phy-gmii-sel.txt
··· 1 + CPSW Port's Interface Mode Selection PHY Tree Bindings 2 + ----------------------------------------------- 3 + 4 + TI am335x/am437x/dra7(am5)/dm814x CPSW3G Ethernet Subsystem supports 5 + two 10/100/1000 Ethernet ports with selectable G/MII, RMII, and RGMII interfaces. 6 + The interface mode is selected by configuring the MII mode selection register(s) 7 + (GMII_SEL) in the System Control Module chapter (SCM). GMII_SEL register(s) and 8 + bit fields placement in SCM are different between SoCs while fields meaning 9 + is the same. 10 + +--------------+ 11 + +-------------------------------+ |SCM | 12 + | CPSW | | +---------+ | 13 + | +--------------------------------+gmii_sel | | 14 + | | | | +---------+ | 15 + | +----v---+ +--------+ | +--------------+ 16 + | |Port 1..<--+-->GMII/MII<-------> 17 + | | | | | | | 18 + | +--------+ | +--------+ | 19 + | | | 20 + | | +--------+ | 21 + | | | RMII <-------> 22 + | +--> | | 23 + | | +--------+ | 24 + | | | 25 + | | +--------+ | 26 + | | | RGMII <-------> 27 + | +--> | | 28 + | +--------+ | 29 + +-------------------------------+ 30 + 31 + CPSW Port's Interface Mode Selection PHY describes MII interface mode between 32 + CPSW Port and Ethernet PHY which depends on Eth PHY and board configuration. 33 + 34 + CPSW Port's Interface Mode Selection PHY device should defined as child device 35 + of SCM node (scm_conf) and can be attached to each CPSW port node using standard 36 + PHY bindings (See phy/phy-bindings.txt). 37 + 38 + Required properties: 39 + - compatible : Should be "ti,am3352-phy-gmii-sel" for am335x platform 40 + "ti,dra7xx-phy-gmii-sel" for dra7xx/am57xx platform 41 + "ti,am43xx-phy-gmii-sel" for am43xx platform 42 + "ti,dm814-phy-gmii-sel" for dm814x platform 43 + - reg : Address and length of the register set for the device 44 + - #phy-cells : must be 2. 45 + cell 1 - CPSW port number (starting from 1) 46 + cell 2 - RMII refclk mode 47 + 48 + Examples: 49 + phy_gmii_sel: phy-gmii-sel { 50 + compatible = "ti,am3352-phy-gmii-sel"; 51 + reg = <0x650 0x4>; 52 + #phy-cells = <2>; 53 + }; 54 + 55 + mac: ethernet@4a100000 { 56 + compatible = "ti,am335x-cpsw","ti,cpsw"; 57 + ... 58 + 59 + cpsw_emac0: slave@4a100200 { 60 + ... 61 + phys = <&phy_gmii_sel 1 1>; 62 + }; 63 + 64 + cpsw_emac1: slave@4a100300 { 65 + ... 66 + phys = <&phy_gmii_sel 2 1>; 67 + }; 68 + };
+1
MAINTAINERS
··· 6261 6261 S: Supported 6262 6262 F: drivers/phy/ 6263 6263 F: include/linux/phy/ 6264 + F: Documentation/devicetree/bindings/phy/ 6264 6265 6265 6266 GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER 6266 6267 M: Wolfram Sang <wsa+renesas@sang-engineering.com>
+2 -17
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
··· 1165 1165 */ 1166 1166 static int mvpp22_comphy_init(struct mvpp2_port *port) 1167 1167 { 1168 - enum phy_mode mode; 1169 1168 int ret; 1170 1169 1171 1170 if (!port->comphy) 1172 1171 return 0; 1173 1172 1174 - switch (port->phy_interface) { 1175 - case PHY_INTERFACE_MODE_SGMII: 1176 - case PHY_INTERFACE_MODE_1000BASEX: 1177 - mode = PHY_MODE_SGMII; 1178 - break; 1179 - case PHY_INTERFACE_MODE_2500BASEX: 1180 - mode = PHY_MODE_2500SGMII; 1181 - break; 1182 - case PHY_INTERFACE_MODE_10GKR: 1183 - mode = PHY_MODE_10GKR; 1184 - break; 1185 - default: 1186 - return -EINVAL; 1187 - } 1188 - 1189 - ret = phy_set_mode(port->comphy, mode); 1173 + ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, 1174 + port->phy_interface); 1190 1175 if (ret) 1191 1176 return ret; 1192 1177
+2 -7
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; 476 475 int err; 477 476 478 477 /* Enable receiving frames on the port, and activate auto-learning of ··· 483 484 ANA_PORT_PORT_CFG, port->chip_port); 484 485 485 486 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); 487 + err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET, 488 + port->phy_mode); 492 489 if (err) { 493 490 netdev_err(dev, "Could not set mode of SerDes\n"); 494 491 return err;
+18 -1
drivers/net/ethernet/ti/cpsw.c
··· 26 26 #include <linux/netdevice.h> 27 27 #include <linux/net_tstamp.h> 28 28 #include <linux/phy.h> 29 + #include <linux/phy/phy.h> 29 30 #include <linux/workqueue.h> 30 31 #include <linux/delay.h> 31 32 #include <linux/pm_runtime.h> ··· 388 387 int phy_if; 389 388 u8 mac_addr[ETH_ALEN]; 390 389 u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */ 390 + struct phy *ifphy; 391 391 }; 392 392 393 393 struct cpsw_platform_data { ··· 1512 1510 phy_start(slave->phy); 1513 1511 1514 1512 /* Configure GMII_SEL register */ 1515 - cpsw_phy_sel(cpsw->dev, slave->phy->interface, slave->slave_num); 1513 + if (!IS_ERR(slave->data->ifphy)) 1514 + phy_set_mode_ext(slave->data->ifphy, PHY_MODE_ETHERNET, 1515 + slave->data->phy_if); 1516 + else 1517 + cpsw_phy_sel(cpsw->dev, slave->phy->interface, 1518 + slave->slave_num); 1516 1519 } 1517 1520 1518 1521 static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) ··· 3153 3146 /* This is no slave child node, continue */ 3154 3147 if (strcmp(slave_node->name, "slave")) 3155 3148 continue; 3149 + 3150 + slave_data->ifphy = devm_of_phy_get(&pdev->dev, slave_node, 3151 + NULL); 3152 + if (!IS_ENABLED(CONFIG_TI_CPSW_PHY_SEL) && 3153 + IS_ERR(slave_data->ifphy)) { 3154 + ret = PTR_ERR(slave_data->ifphy); 3155 + dev_err(&pdev->dev, 3156 + "%d: Error retrieving port phy: %d\n", i, ret); 3157 + return ret; 3158 + } 3156 3159 3157 3160 slave_data->phy_node = of_parse_phandle(slave_node, 3158 3161 "phy-handle", 0);
+9
drivers/phy/Kconfig
··· 15 15 phy users can obtain reference to the PHY. All the users of this 16 16 framework should select this config. 17 17 18 + config GENERIC_PHY_MIPI_DPHY 19 + bool 20 + help 21 + Generic MIPI D-PHY support. 22 + 23 + Provides a number of helpers a core functions for MIPI D-PHY 24 + drivers to us. 25 + 18 26 config PHY_LPC18XX_USB_OTG 19 27 tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" 20 28 depends on OF && (ARCH_LPC18XX || COMPILE_TEST) ··· 52 44 source "drivers/phy/amlogic/Kconfig" 53 45 source "drivers/phy/broadcom/Kconfig" 54 46 source "drivers/phy/cadence/Kconfig" 47 + source "drivers/phy/freescale/Kconfig" 55 48 source "drivers/phy/hisilicon/Kconfig" 56 49 source "drivers/phy/lantiq/Kconfig" 57 50 source "drivers/phy/marvell/Kconfig"
+2
drivers/phy/Makefile
··· 4 4 # 5 5 6 6 obj-$(CONFIG_GENERIC_PHY) += phy-core.o 7 + obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o 7 8 obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o 8 9 obj-$(CONFIG_PHY_XGENE) += phy-xgene.o 9 10 obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o ··· 17 16 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 18 17 obj-y += broadcom/ \ 19 18 cadence/ \ 19 + freescale/ \ 20 20 hisilicon/ \ 21 21 marvell/ \ 22 22 motorola/ \
+26 -3
drivers/phy/allwinner/phy-sun4i-usb.c
··· 115 115 sun8i_r40_phy, 116 116 sun8i_v3s_phy, 117 117 sun50i_a64_phy, 118 + sun50i_h6_phy, 118 119 }; 119 120 120 121 struct sun4i_usb_phy_cfg { ··· 127 126 bool dedicated_clocks; 128 127 bool enable_pmu_unk1; 129 128 bool phy0_dual_route; 129 + int missing_phys; 130 130 }; 131 131 132 132 struct sun4i_usb_phy_data { ··· 296 294 return ret; 297 295 } 298 296 299 - if (data->cfg->type == sun8i_a83t_phy) { 297 + if (data->cfg->type == sun8i_a83t_phy || 298 + data->cfg->type == sun50i_h6_phy) { 300 299 if (phy->index == 0) { 301 300 val = readl(data->base + data->cfg->phyctl_offset); 302 301 val |= PHY_CTL_VBUSVLDEXT; ··· 346 343 struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); 347 344 348 345 if (phy->index == 0) { 349 - if (data->cfg->type == sun8i_a83t_phy) { 346 + if (data->cfg->type == sun8i_a83t_phy || 347 + data->cfg->type == sun50i_h6_phy) { 350 348 void __iomem *phyctl = data->base + 351 349 data->cfg->phyctl_offset; 352 350 ··· 478 474 return 0; 479 475 } 480 476 481 - static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode) 477 + static int sun4i_usb_phy_set_mode(struct phy *_phy, 478 + enum phy_mode mode, int submode) 482 479 { 483 480 struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); 484 481 struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); ··· 651 646 if (args->args[0] >= data->cfg->num_phys) 652 647 return ERR_PTR(-ENODEV); 653 648 649 + if (data->cfg->missing_phys & BIT(args->args[0])) 650 + return ERR_PTR(-ENODEV); 651 + 654 652 return data->phys[args->args[0]].phy; 655 653 } 656 654 ··· 748 740 for (i = 0; i < data->cfg->num_phys; i++) { 749 741 struct sun4i_usb_phy *phy = data->phys + i; 750 742 char name[16]; 743 + 744 + if (data->cfg->missing_phys & BIT(i)) 745 + continue; 751 746 752 747 snprintf(name, sizeof(name), "usb%d_vbus", i); 753 748 phy->vbus = devm_regulator_get_optional(dev, name); ··· 963 952 .phy0_dual_route = true, 964 953 }; 965 954 955 + static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { 956 + .num_phys = 4, 957 + .type = sun50i_h6_phy, 958 + .disc_thresh = 3, 959 + .phyctl_offset = REG_PHYCTL_A33, 960 + .dedicated_clocks = true, 961 + .enable_pmu_unk1 = true, 962 + .phy0_dual_route = true, 963 + .missing_phys = BIT(1) | BIT(2), 964 + }; 965 + 966 966 static const struct of_device_id sun4i_usb_phy_of_match[] = { 967 967 { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, 968 968 { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, ··· 987 965 { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg }, 988 966 { .compatible = "allwinner,sun50i-a64-usb-phy", 989 967 .data = &sun50i_a64_cfg}, 968 + { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg }, 990 969 { }, 991 970 }; 992 971 MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
+3 -2
drivers/phy/amlogic/phy-meson-gxl-usb2.c
··· 152 152 return 0; 153 153 } 154 154 155 - static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode) 155 + static int phy_meson_gxl_usb2_set_mode(struct phy *phy, 156 + enum phy_mode mode, int submode) 156 157 { 157 158 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); 158 159 ··· 210 209 /* power on the PHY by taking it out of reset mode */ 211 210 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); 212 211 213 - ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode); 212 + ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode, 0); 214 213 if (ret) { 215 214 phy_meson_gxl_usb2_power_off(phy); 216 215
+3 -2
drivers/phy/amlogic/phy-meson-gxl-usb3.c
··· 119 119 return 0; 120 120 } 121 121 122 - static int phy_meson_gxl_usb3_set_mode(struct phy *phy, enum phy_mode mode) 122 + static int phy_meson_gxl_usb3_set_mode(struct phy *phy, 123 + enum phy_mode mode, int submode) 123 124 { 124 125 struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); 125 126 ··· 165 164 if (ret) 166 165 goto err_disable_clk_phy; 167 166 168 - ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode); 167 + ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode, 0); 169 168 if (ret) 170 169 goto err_disable_clk_peripheral; 171 170
+8 -1
drivers/phy/cadence/Kconfig
··· 1 1 # 2 - # Phy driver for Cadence MHDP DisplayPort controller 2 + # Phy drivers for Cadence PHYs 3 3 # 4 4 config PHY_CADENCE_DP 5 5 tristate "Cadence MHDP DisplayPort PHY driver" ··· 8 8 select GENERIC_PHY 9 9 help 10 10 Support for Cadence MHDP DisplayPort PHY. 11 + 12 + config PHY_CADENCE_SIERRA 13 + tristate "Cadence Sierra PHY Driver" 14 + depends on OF && HAS_IOMEM && RESET_CONTROLLER 15 + select GENERIC_PHY 16 + help 17 + Enable this to support the Cadence Sierra PHY driver
+1
drivers/phy/cadence/Makefile
··· 1 1 obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o 2 + obj-$(CONFIG_PHY_CADENCE_SIERRA) += phy-cadence-sierra.o
+395
drivers/phy/cadence/phy-cadence-sierra.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Cadence Sierra PHY Driver 4 + * 5 + * Copyright (c) 2018 Cadence Design Systems 6 + * Author: Alan Douglas <adouglas@cadence.com> 7 + * 8 + */ 9 + #include <linux/clk.h> 10 + #include <linux/delay.h> 11 + #include <linux/err.h> 12 + #include <linux/io.h> 13 + #include <linux/module.h> 14 + #include <linux/phy/phy.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/pm_runtime.h> 17 + #include <linux/regmap.h> 18 + #include <linux/reset.h> 19 + #include <linux/slab.h> 20 + #include <linux/of.h> 21 + #include <linux/of_platform.h> 22 + #include <dt-bindings/phy/phy.h> 23 + 24 + /* PHY register offsets */ 25 + #define SIERRA_PHY_PLL_CFG (0xc00e << 2) 26 + #define SIERRA_DET_STANDEC_A (0x4000 << 2) 27 + #define SIERRA_DET_STANDEC_B (0x4001 << 2) 28 + #define SIERRA_DET_STANDEC_C (0x4002 << 2) 29 + #define SIERRA_DET_STANDEC_D (0x4003 << 2) 30 + #define SIERRA_DET_STANDEC_E (0x4004 << 2) 31 + #define SIERRA_PSM_LANECAL (0x4008 << 2) 32 + #define SIERRA_PSM_DIAG (0x4015 << 2) 33 + #define SIERRA_PSC_TX_A0 (0x4028 << 2) 34 + #define SIERRA_PSC_TX_A1 (0x4029 << 2) 35 + #define SIERRA_PSC_TX_A2 (0x402A << 2) 36 + #define SIERRA_PSC_TX_A3 (0x402B << 2) 37 + #define SIERRA_PSC_RX_A0 (0x4030 << 2) 38 + #define SIERRA_PSC_RX_A1 (0x4031 << 2) 39 + #define SIERRA_PSC_RX_A2 (0x4032 << 2) 40 + #define SIERRA_PSC_RX_A3 (0x4033 << 2) 41 + #define SIERRA_PLLCTRL_SUBRATE (0x403A << 2) 42 + #define SIERRA_PLLCTRL_GEN_D (0x403E << 2) 43 + #define SIERRA_DRVCTRL_ATTEN (0x406A << 2) 44 + #define SIERRA_CLKPATHCTRL_TMR (0x4081 << 2) 45 + #define SIERRA_RX_CREQ_FLTR_A_MODE1 (0x4087 << 2) 46 + #define SIERRA_RX_CREQ_FLTR_A_MODE0 (0x4088 << 2) 47 + #define SIERRA_CREQ_CCLKDET_MODE01 (0x408E << 2) 48 + #define SIERRA_RX_CTLE_MAINTENANCE (0x4091 << 2) 49 + #define SIERRA_CREQ_FSMCLK_SEL (0x4092 << 2) 50 + #define SIERRA_CTLELUT_CTRL (0x4098 << 2) 51 + #define SIERRA_DFE_ECMP_RATESEL (0x40C0 << 2) 52 + #define SIERRA_DFE_SMP_RATESEL (0x40C1 << 2) 53 + #define SIERRA_DEQ_VGATUNE_CTRL (0x40E1 << 2) 54 + #define SIERRA_TMRVAL_MODE3 (0x416E << 2) 55 + #define SIERRA_TMRVAL_MODE2 (0x416F << 2) 56 + #define SIERRA_TMRVAL_MODE1 (0x4170 << 2) 57 + #define SIERRA_TMRVAL_MODE0 (0x4171 << 2) 58 + #define SIERRA_PICNT_MODE1 (0x4174 << 2) 59 + #define SIERRA_CPI_OUTBUF_RATESEL (0x417C << 2) 60 + #define SIERRA_LFPSFILT_NS (0x418A << 2) 61 + #define SIERRA_LFPSFILT_RD (0x418B << 2) 62 + #define SIERRA_LFPSFILT_MP (0x418C << 2) 63 + #define SIERRA_SDFILT_H2L_A (0x4191 << 2) 64 + 65 + #define SIERRA_MACRO_ID 0x00007364 66 + #define SIERRA_MAX_LANES 4 67 + 68 + struct cdns_sierra_inst { 69 + struct phy *phy; 70 + u32 phy_type; 71 + u32 num_lanes; 72 + u32 mlane; 73 + struct reset_control *lnk_rst; 74 + }; 75 + 76 + struct cdns_reg_pairs { 77 + u16 val; 78 + u32 off; 79 + }; 80 + 81 + struct cdns_sierra_data { 82 + u32 id_value; 83 + u32 pcie_regs; 84 + u32 usb_regs; 85 + struct cdns_reg_pairs *pcie_vals; 86 + struct cdns_reg_pairs *usb_vals; 87 + }; 88 + 89 + struct cdns_sierra_phy { 90 + struct device *dev; 91 + void __iomem *base; 92 + struct cdns_sierra_data *init_data; 93 + struct cdns_sierra_inst phys[SIERRA_MAX_LANES]; 94 + struct reset_control *phy_rst; 95 + struct reset_control *apb_rst; 96 + struct clk *clk; 97 + int nsubnodes; 98 + bool autoconf; 99 + }; 100 + 101 + static void cdns_sierra_phy_init(struct phy *gphy) 102 + { 103 + struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); 104 + struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent); 105 + int i, j; 106 + struct cdns_reg_pairs *vals; 107 + u32 num_regs; 108 + 109 + if (ins->phy_type == PHY_TYPE_PCIE) { 110 + num_regs = phy->init_data->pcie_regs; 111 + vals = phy->init_data->pcie_vals; 112 + } else if (ins->phy_type == PHY_TYPE_USB3) { 113 + num_regs = phy->init_data->usb_regs; 114 + vals = phy->init_data->usb_vals; 115 + } else { 116 + return; 117 + } 118 + for (i = 0; i < ins->num_lanes; i++) 119 + for (j = 0; j < num_regs ; j++) 120 + writel(vals[j].val, phy->base + 121 + vals[j].off + (i + ins->mlane) * 0x800); 122 + } 123 + 124 + static int cdns_sierra_phy_on(struct phy *gphy) 125 + { 126 + struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); 127 + 128 + /* Take the PHY lane group out of reset */ 129 + return reset_control_deassert(ins->lnk_rst); 130 + } 131 + 132 + static int cdns_sierra_phy_off(struct phy *gphy) 133 + { 134 + struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); 135 + 136 + return reset_control_assert(ins->lnk_rst); 137 + } 138 + 139 + static const struct phy_ops ops = { 140 + .power_on = cdns_sierra_phy_on, 141 + .power_off = cdns_sierra_phy_off, 142 + .owner = THIS_MODULE, 143 + }; 144 + 145 + static int cdns_sierra_get_optional(struct cdns_sierra_inst *inst, 146 + struct device_node *child) 147 + { 148 + if (of_property_read_u32(child, "reg", &inst->mlane)) 149 + return -EINVAL; 150 + 151 + if (of_property_read_u32(child, "cdns,num-lanes", &inst->num_lanes)) 152 + return -EINVAL; 153 + 154 + if (of_property_read_u32(child, "cdns,phy-type", &inst->phy_type)) 155 + return -EINVAL; 156 + 157 + return 0; 158 + } 159 + 160 + static const struct of_device_id cdns_sierra_id_table[]; 161 + 162 + static int cdns_sierra_phy_probe(struct platform_device *pdev) 163 + { 164 + struct cdns_sierra_phy *sp; 165 + struct phy_provider *phy_provider; 166 + struct device *dev = &pdev->dev; 167 + const struct of_device_id *match; 168 + struct resource *res; 169 + int i, ret, node = 0; 170 + struct device_node *dn = dev->of_node, *child; 171 + 172 + if (of_get_child_count(dn) == 0) 173 + return -ENODEV; 174 + 175 + sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL); 176 + if (!sp) 177 + return -ENOMEM; 178 + dev_set_drvdata(dev, sp); 179 + sp->dev = dev; 180 + 181 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 182 + sp->base = devm_ioremap_resource(dev, res); 183 + if (IS_ERR(sp->base)) { 184 + dev_err(dev, "missing \"reg\"\n"); 185 + return PTR_ERR(sp->base); 186 + } 187 + 188 + /* Get init data for this PHY */ 189 + match = of_match_device(cdns_sierra_id_table, dev); 190 + if (!match) 191 + return -EINVAL; 192 + sp->init_data = (struct cdns_sierra_data *)match->data; 193 + 194 + platform_set_drvdata(pdev, sp); 195 + 196 + sp->clk = devm_clk_get(dev, "phy_clk"); 197 + if (IS_ERR(sp->clk)) { 198 + dev_err(dev, "failed to get clock phy_clk\n"); 199 + return PTR_ERR(sp->clk); 200 + } 201 + 202 + sp->phy_rst = devm_reset_control_get(dev, "sierra_reset"); 203 + if (IS_ERR(sp->phy_rst)) { 204 + dev_err(dev, "failed to get reset\n"); 205 + return PTR_ERR(sp->phy_rst); 206 + } 207 + 208 + sp->apb_rst = devm_reset_control_get(dev, "sierra_apb"); 209 + if (IS_ERR(sp->apb_rst)) { 210 + dev_err(dev, "failed to get apb reset\n"); 211 + return PTR_ERR(sp->apb_rst); 212 + } 213 + 214 + ret = clk_prepare_enable(sp->clk); 215 + if (ret) 216 + return ret; 217 + 218 + /* Enable APB */ 219 + reset_control_deassert(sp->apb_rst); 220 + 221 + /* Check that PHY is present */ 222 + if (sp->init_data->id_value != readl(sp->base)) { 223 + ret = -EINVAL; 224 + goto clk_disable; 225 + } 226 + 227 + sp->autoconf = of_property_read_bool(dn, "cdns,autoconf"); 228 + 229 + for_each_available_child_of_node(dn, child) { 230 + struct phy *gphy; 231 + 232 + sp->phys[node].lnk_rst = 233 + of_reset_control_get_exclusive_by_index(child, 0); 234 + 235 + if (IS_ERR(sp->phys[node].lnk_rst)) { 236 + dev_err(dev, "failed to get reset %s\n", 237 + child->full_name); 238 + ret = PTR_ERR(sp->phys[node].lnk_rst); 239 + goto put_child2; 240 + } 241 + 242 + if (!sp->autoconf) { 243 + ret = cdns_sierra_get_optional(&sp->phys[node], child); 244 + if (ret) { 245 + dev_err(dev, "missing property in node %s\n", 246 + child->name); 247 + goto put_child; 248 + } 249 + } 250 + 251 + gphy = devm_phy_create(dev, child, &ops); 252 + 253 + if (IS_ERR(gphy)) { 254 + ret = PTR_ERR(gphy); 255 + goto put_child; 256 + } 257 + sp->phys[node].phy = gphy; 258 + phy_set_drvdata(gphy, &sp->phys[node]); 259 + 260 + /* Initialise the PHY registers, unless auto configured */ 261 + if (!sp->autoconf) 262 + cdns_sierra_phy_init(gphy); 263 + 264 + node++; 265 + } 266 + sp->nsubnodes = node; 267 + 268 + /* If more than one subnode, configure the PHY as multilink */ 269 + if (!sp->autoconf && sp->nsubnodes > 1) 270 + writel(2, sp->base + SIERRA_PHY_PLL_CFG); 271 + 272 + pm_runtime_enable(dev); 273 + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 274 + reset_control_deassert(sp->phy_rst); 275 + return PTR_ERR_OR_ZERO(phy_provider); 276 + 277 + put_child: 278 + node++; 279 + put_child2: 280 + for (i = 0; i < node; i++) 281 + reset_control_put(sp->phys[i].lnk_rst); 282 + of_node_put(child); 283 + clk_disable: 284 + clk_disable_unprepare(sp->clk); 285 + reset_control_assert(sp->apb_rst); 286 + return ret; 287 + } 288 + 289 + static int cdns_sierra_phy_remove(struct platform_device *pdev) 290 + { 291 + struct cdns_sierra_phy *phy = dev_get_drvdata(pdev->dev.parent); 292 + int i; 293 + 294 + reset_control_assert(phy->phy_rst); 295 + reset_control_assert(phy->apb_rst); 296 + pm_runtime_disable(&pdev->dev); 297 + 298 + /* 299 + * The device level resets will be put automatically. 300 + * Need to put the subnode resets here though. 301 + */ 302 + for (i = 0; i < phy->nsubnodes; i++) { 303 + reset_control_assert(phy->phys[i].lnk_rst); 304 + reset_control_put(phy->phys[i].lnk_rst); 305 + } 306 + return 0; 307 + } 308 + 309 + static struct cdns_reg_pairs cdns_usb_regs[] = { 310 + /* 311 + * Write USB configuration parameters to the PHY. 312 + * These values are specific to this specific hardware 313 + * configuration. 314 + */ 315 + {0xFE0A, SIERRA_DET_STANDEC_A}, 316 + {0x000F, SIERRA_DET_STANDEC_B}, 317 + {0x55A5, SIERRA_DET_STANDEC_C}, 318 + {0x69AD, SIERRA_DET_STANDEC_D}, 319 + {0x0241, SIERRA_DET_STANDEC_E}, 320 + {0x0110, SIERRA_PSM_LANECAL}, 321 + {0xCF00, SIERRA_PSM_DIAG}, 322 + {0x001F, SIERRA_PSC_TX_A0}, 323 + {0x0007, SIERRA_PSC_TX_A1}, 324 + {0x0003, SIERRA_PSC_TX_A2}, 325 + {0x0003, SIERRA_PSC_TX_A3}, 326 + {0x0FFF, SIERRA_PSC_RX_A0}, 327 + {0x0003, SIERRA_PSC_RX_A1}, 328 + {0x0003, SIERRA_PSC_RX_A2}, 329 + {0x0001, SIERRA_PSC_RX_A3}, 330 + {0x0001, SIERRA_PLLCTRL_SUBRATE}, 331 + {0x0406, SIERRA_PLLCTRL_GEN_D}, 332 + {0x0000, SIERRA_DRVCTRL_ATTEN}, 333 + {0x823E, SIERRA_CLKPATHCTRL_TMR}, 334 + {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1}, 335 + {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0}, 336 + {0x7B3C, SIERRA_CREQ_CCLKDET_MODE01}, 337 + {0x023C, SIERRA_RX_CTLE_MAINTENANCE}, 338 + {0x3232, SIERRA_CREQ_FSMCLK_SEL}, 339 + {0x8452, SIERRA_CTLELUT_CTRL}, 340 + {0x4121, SIERRA_DFE_ECMP_RATESEL}, 341 + {0x4121, SIERRA_DFE_SMP_RATESEL}, 342 + {0x9999, SIERRA_DEQ_VGATUNE_CTRL}, 343 + {0x0330, SIERRA_TMRVAL_MODE0}, 344 + {0x01FF, SIERRA_PICNT_MODE1}, 345 + {0x0009, SIERRA_CPI_OUTBUF_RATESEL}, 346 + {0x000F, SIERRA_LFPSFILT_NS}, 347 + {0x0009, SIERRA_LFPSFILT_RD}, 348 + {0x0001, SIERRA_LFPSFILT_MP}, 349 + {0x8013, SIERRA_SDFILT_H2L_A}, 350 + {0x0400, SIERRA_TMRVAL_MODE1}, 351 + }; 352 + 353 + static struct cdns_reg_pairs cdns_pcie_regs[] = { 354 + /* 355 + * Write PCIe configuration parameters to the PHY. 356 + * These values are specific to this specific hardware 357 + * configuration. 358 + */ 359 + {0x891f, SIERRA_DET_STANDEC_D}, 360 + {0x0053, SIERRA_DET_STANDEC_E}, 361 + {0x0400, SIERRA_TMRVAL_MODE2}, 362 + {0x0200, SIERRA_TMRVAL_MODE3}, 363 + }; 364 + 365 + static const struct cdns_sierra_data cdns_map_sierra = { 366 + SIERRA_MACRO_ID, 367 + ARRAY_SIZE(cdns_pcie_regs), 368 + ARRAY_SIZE(cdns_usb_regs), 369 + cdns_pcie_regs, 370 + cdns_usb_regs 371 + }; 372 + 373 + static const struct of_device_id cdns_sierra_id_table[] = { 374 + { 375 + .compatible = "cdns,sierra-phy-t0", 376 + .data = &cdns_map_sierra, 377 + }, 378 + {} 379 + }; 380 + MODULE_DEVICE_TABLE(of, cdns_sierra_id_table); 381 + 382 + static struct platform_driver cdns_sierra_driver = { 383 + .probe = cdns_sierra_phy_probe, 384 + .remove = cdns_sierra_phy_remove, 385 + .driver = { 386 + .name = "cdns-sierra-phy", 387 + .of_match_table = cdns_sierra_id_table, 388 + }, 389 + }; 390 + module_platform_driver(cdns_sierra_driver); 391 + 392 + MODULE_ALIAS("platform:cdns_sierra"); 393 + MODULE_AUTHOR("Cadence Design Systems"); 394 + MODULE_DESCRIPTION("CDNS sierra phy driver"); 395 + MODULE_LICENSE("GPL v2");
+5
drivers/phy/freescale/Kconfig
··· 1 + config PHY_FSL_IMX8MQ_USB 2 + tristate "Freescale i.MX8M USB3 PHY" 3 + depends on OF && HAS_IOMEM 4 + select GENERIC_PHY 5 + default SOC_IMX8MQ
+1
drivers/phy/freescale/Makefile
··· 1 + obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o
+127
drivers/phy/freescale/phy-fsl-imx8mq-usb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* Copyright (c) 2017 NXP. */ 3 + 4 + #include <linux/clk.h> 5 + #include <linux/io.h> 6 + #include <linux/module.h> 7 + #include <linux/phy/phy.h> 8 + #include <linux/platform_device.h> 9 + 10 + #define PHY_CTRL0 0x0 11 + #define PHY_CTRL0_REF_SSP_EN BIT(2) 12 + 13 + #define PHY_CTRL1 0x4 14 + #define PHY_CTRL1_RESET BIT(0) 15 + #define PHY_CTRL1_COMMONONN BIT(1) 16 + #define PHY_CTRL1_ATERESET BIT(3) 17 + #define PHY_CTRL1_VDATSRCENB0 BIT(19) 18 + #define PHY_CTRL1_VDATDETENB0 BIT(20) 19 + 20 + #define PHY_CTRL2 0x8 21 + #define PHY_CTRL2_TXENABLEN0 BIT(8) 22 + 23 + struct imx8mq_usb_phy { 24 + struct phy *phy; 25 + struct clk *clk; 26 + void __iomem *base; 27 + }; 28 + 29 + static int imx8mq_usb_phy_init(struct phy *phy) 30 + { 31 + struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); 32 + u32 value; 33 + 34 + value = readl(imx_phy->base + PHY_CTRL1); 35 + value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0 | 36 + PHY_CTRL1_COMMONONN); 37 + value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET; 38 + writel(value, imx_phy->base + PHY_CTRL1); 39 + 40 + value = readl(imx_phy->base + PHY_CTRL0); 41 + value |= PHY_CTRL0_REF_SSP_EN; 42 + writel(value, imx_phy->base + PHY_CTRL0); 43 + 44 + value = readl(imx_phy->base + PHY_CTRL2); 45 + value |= PHY_CTRL2_TXENABLEN0; 46 + writel(value, imx_phy->base + PHY_CTRL2); 47 + 48 + value = readl(imx_phy->base + PHY_CTRL1); 49 + value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); 50 + writel(value, imx_phy->base + PHY_CTRL1); 51 + 52 + return 0; 53 + } 54 + 55 + static int imx8mq_phy_power_on(struct phy *phy) 56 + { 57 + struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); 58 + 59 + return clk_prepare_enable(imx_phy->clk); 60 + } 61 + 62 + static int imx8mq_phy_power_off(struct phy *phy) 63 + { 64 + struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); 65 + 66 + clk_disable_unprepare(imx_phy->clk); 67 + 68 + return 0; 69 + } 70 + 71 + static struct phy_ops imx8mq_usb_phy_ops = { 72 + .init = imx8mq_usb_phy_init, 73 + .power_on = imx8mq_phy_power_on, 74 + .power_off = imx8mq_phy_power_off, 75 + .owner = THIS_MODULE, 76 + }; 77 + 78 + static int imx8mq_usb_phy_probe(struct platform_device *pdev) 79 + { 80 + struct phy_provider *phy_provider; 81 + struct device *dev = &pdev->dev; 82 + struct imx8mq_usb_phy *imx_phy; 83 + struct resource *res; 84 + 85 + imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL); 86 + if (!imx_phy) 87 + return -ENOMEM; 88 + 89 + imx_phy->clk = devm_clk_get(dev, "phy"); 90 + if (IS_ERR(imx_phy->clk)) { 91 + dev_err(dev, "failed to get imx8mq usb phy clock\n"); 92 + return PTR_ERR(imx_phy->clk); 93 + } 94 + 95 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 96 + imx_phy->base = devm_ioremap_resource(dev, res); 97 + if (IS_ERR(imx_phy->base)) 98 + return PTR_ERR(imx_phy->base); 99 + 100 + imx_phy->phy = devm_phy_create(dev, NULL, &imx8mq_usb_phy_ops); 101 + if (IS_ERR(imx_phy->phy)) 102 + return PTR_ERR(imx_phy->phy); 103 + 104 + phy_set_drvdata(imx_phy->phy, imx_phy); 105 + 106 + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 107 + 108 + return PTR_ERR_OR_ZERO(phy_provider); 109 + } 110 + 111 + static const struct of_device_id imx8mq_usb_phy_of_match[] = { 112 + {.compatible = "fsl,imx8mq-usb-phy",}, 113 + { }, 114 + }; 115 + MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); 116 + 117 + static struct platform_driver imx8mq_usb_phy_driver = { 118 + .probe = imx8mq_usb_phy_probe, 119 + .driver = { 120 + .name = "imx8mq-usb-phy", 121 + .of_match_table = imx8mq_usb_phy_of_match, 122 + } 123 + }; 124 + module_platform_driver(imx8mq_usb_phy_driver); 125 + 126 + MODULE_DESCRIPTION("FSL IMX8MQ USB PHY driver"); 127 + MODULE_LICENSE("GPL");
+55 -42
drivers/phy/marvell/phy-mvebu-cp110-comphy.c
··· 9 9 #include <linux/iopoll.h> 10 10 #include <linux/mfd/syscon.h> 11 11 #include <linux/module.h> 12 + #include <linux/phy.h> 12 13 #include <linux/phy/phy.h> 13 14 #include <linux/platform_device.h> 14 15 #include <linux/regmap.h> ··· 115 114 #define MVEBU_COMPHY_LANES 6 116 115 #define MVEBU_COMPHY_PORTS 3 117 116 118 - struct mvebu_comhy_conf { 117 + struct mvebu_comphy_conf { 119 118 enum phy_mode mode; 119 + int submode; 120 120 unsigned lane; 121 121 unsigned port; 122 122 u32 mux; 123 123 }; 124 124 125 - #define MVEBU_COMPHY_CONF(_lane, _port, _mode, _mux) \ 125 + #define MVEBU_COMPHY_CONF(_lane, _port, _submode, _mux) \ 126 126 { \ 127 127 .lane = _lane, \ 128 128 .port = _port, \ 129 - .mode = _mode, \ 129 + .mode = PHY_MODE_ETHERNET, \ 130 + .submode = _submode, \ 130 131 .mux = _mux, \ 131 132 } 132 133 133 - static const struct mvebu_comhy_conf mvebu_comphy_cp110_modes[] = { 134 + static const struct mvebu_comphy_conf mvebu_comphy_cp110_modes[] = { 134 135 /* lane 0 */ 135 - MVEBU_COMPHY_CONF(0, 1, PHY_MODE_SGMII, 0x1), 136 - MVEBU_COMPHY_CONF(0, 1, PHY_MODE_2500SGMII, 0x1), 136 + MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_SGMII, 0x1), 137 + MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1), 137 138 /* lane 1 */ 138 - MVEBU_COMPHY_CONF(1, 2, PHY_MODE_SGMII, 0x1), 139 - MVEBU_COMPHY_CONF(1, 2, PHY_MODE_2500SGMII, 0x1), 139 + MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_SGMII, 0x1), 140 + MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), 140 141 /* lane 2 */ 141 - MVEBU_COMPHY_CONF(2, 0, PHY_MODE_SGMII, 0x1), 142 - MVEBU_COMPHY_CONF(2, 0, PHY_MODE_2500SGMII, 0x1), 143 - MVEBU_COMPHY_CONF(2, 0, PHY_MODE_10GKR, 0x1), 142 + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_SGMII, 0x1), 143 + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_2500BASEX, 0x1), 144 + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_10GKR, 0x1), 144 145 /* lane 3 */ 145 - MVEBU_COMPHY_CONF(3, 1, PHY_MODE_SGMII, 0x2), 146 - MVEBU_COMPHY_CONF(3, 1, PHY_MODE_2500SGMII, 0x2), 146 + MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_SGMII, 0x2), 147 + MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_2500BASEX, 0x2), 147 148 /* lane 4 */ 148 - MVEBU_COMPHY_CONF(4, 0, PHY_MODE_SGMII, 0x2), 149 - MVEBU_COMPHY_CONF(4, 0, PHY_MODE_2500SGMII, 0x2), 150 - MVEBU_COMPHY_CONF(4, 0, PHY_MODE_10GKR, 0x2), 151 - MVEBU_COMPHY_CONF(4, 1, PHY_MODE_SGMII, 0x1), 149 + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_SGMII, 0x2), 150 + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_2500BASEX, 0x2), 151 + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_10GKR, 0x2), 152 + MVEBU_COMPHY_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1), 152 153 /* lane 5 */ 153 - MVEBU_COMPHY_CONF(5, 2, PHY_MODE_SGMII, 0x1), 154 - MVEBU_COMPHY_CONF(5, 2, PHY_MODE_2500SGMII, 0x1), 154 + MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_SGMII, 0x1), 155 + MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), 155 156 }; 156 157 157 158 struct mvebu_comphy_priv { ··· 166 163 struct mvebu_comphy_priv *priv; 167 164 unsigned id; 168 165 enum phy_mode mode; 166 + int submode; 169 167 int port; 170 168 }; 171 169 172 - static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) 170 + static int mvebu_comphy_get_mux(int lane, int port, 171 + enum phy_mode mode, int submode) 173 172 { 174 173 int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes); 175 174 ··· 182 177 for (i = 0; i < n; i++) { 183 178 if (mvebu_comphy_cp110_modes[i].lane == lane && 184 179 mvebu_comphy_cp110_modes[i].port == port && 185 - mvebu_comphy_cp110_modes[i].mode == mode) 180 + mvebu_comphy_cp110_modes[i].mode == mode && 181 + mvebu_comphy_cp110_modes[i].submode == submode) 186 182 break; 187 183 } 188 184 ··· 193 187 return mvebu_comphy_cp110_modes[i].mux; 194 188 } 195 189 196 - static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, 197 - enum phy_mode mode) 190 + static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane) 198 191 { 199 192 struct mvebu_comphy_priv *priv = lane->priv; 200 193 u32 val; ··· 211 206 MVEBU_COMPHY_SERDES_CFG0_HALF_BUS | 212 207 MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) | 213 208 MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf)); 214 - if (mode == PHY_MODE_10GKR) 209 + if (lane->submode == PHY_INTERFACE_MODE_10GKR) 215 210 val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) | 216 211 MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe); 217 - else if (mode == PHY_MODE_2500SGMII) 212 + else if (lane->submode == PHY_INTERFACE_MODE_2500BASEX) 218 213 val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x8) | 219 214 MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x8) | 220 215 MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; 221 - else if (mode == PHY_MODE_SGMII) 216 + else if (lane->submode == PHY_INTERFACE_MODE_SGMII) 222 217 val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) | 223 218 MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) | 224 219 MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; ··· 248 243 /* refclk selection */ 249 244 val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); 250 245 val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL; 251 - if (mode == PHY_MODE_10GKR) 246 + if (lane->submode == PHY_INTERFACE_MODE_10GKR) 252 247 val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE; 253 248 writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); 254 249 ··· 266 261 writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id)); 267 262 } 268 263 269 - static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane, 270 - enum phy_mode mode) 264 + static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane) 271 265 { 272 266 struct mvebu_comphy_priv *priv = lane->priv; 273 267 u32 val; ··· 307 303 return 0; 308 304 } 309 305 310 - static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode) 306 + static int mvebu_comphy_set_mode_sgmii(struct phy *phy) 311 307 { 312 308 struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); 313 309 struct mvebu_comphy_priv *priv = lane->priv; 314 310 u32 val; 315 311 316 - mvebu_comphy_ethernet_init_reset(lane, mode); 312 + mvebu_comphy_ethernet_init_reset(lane); 317 313 318 314 val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); 319 315 val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN; ··· 334 330 val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1); 335 331 writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id)); 336 332 337 - return mvebu_comphy_init_plls(lane, PHY_MODE_SGMII); 333 + return mvebu_comphy_init_plls(lane); 338 334 } 339 335 340 336 static int mvebu_comphy_set_mode_10gkr(struct phy *phy) ··· 343 339 struct mvebu_comphy_priv *priv = lane->priv; 344 340 u32 val; 345 341 346 - mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_10GKR); 342 + mvebu_comphy_ethernet_init_reset(lane); 347 343 348 344 val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); 349 345 val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL | ··· 473 469 val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a); 474 470 writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id)); 475 471 476 - return mvebu_comphy_init_plls(lane, PHY_MODE_10GKR); 472 + return mvebu_comphy_init_plls(lane); 477 473 } 478 474 479 475 static int mvebu_comphy_power_on(struct phy *phy) ··· 483 479 int ret, mux; 484 480 u32 val; 485 481 486 - mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode); 482 + mux = mvebu_comphy_get_mux(lane->id, lane->port, 483 + lane->mode, lane->submode); 487 484 if (mux < 0) 488 485 return -ENOTSUPP; 489 486 ··· 497 492 val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id); 498 493 regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); 499 494 500 - switch (lane->mode) { 501 - case PHY_MODE_SGMII: 502 - case PHY_MODE_2500SGMII: 503 - ret = mvebu_comphy_set_mode_sgmii(phy, lane->mode); 495 + switch (lane->submode) { 496 + case PHY_INTERFACE_MODE_SGMII: 497 + case PHY_INTERFACE_MODE_2500BASEX: 498 + ret = mvebu_comphy_set_mode_sgmii(phy); 504 499 break; 505 - case PHY_MODE_10GKR: 500 + case PHY_INTERFACE_MODE_10GKR: 506 501 ret = mvebu_comphy_set_mode_10gkr(phy); 507 502 break; 508 503 default: ··· 517 512 return ret; 518 513 } 519 514 520 - static int mvebu_comphy_set_mode(struct phy *phy, enum phy_mode mode) 515 + static int mvebu_comphy_set_mode(struct phy *phy, 516 + enum phy_mode mode, int submode) 521 517 { 522 518 struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); 523 519 524 - if (mvebu_comphy_get_mux(lane->id, lane->port, mode) < 0) 520 + if (mode != PHY_MODE_ETHERNET) 521 + return -EINVAL; 522 + 523 + if (submode == PHY_INTERFACE_MODE_1000BASEX) 524 + submode = PHY_INTERFACE_MODE_SGMII; 525 + 526 + if (mvebu_comphy_get_mux(lane->id, lane->port, mode, submode) < 0) 525 527 return -EINVAL; 526 528 527 529 lane->mode = mode; 530 + lane->submode = submode; 528 531 return 0; 529 532 } 530 533
+1 -1
drivers/phy/mediatek/phy-mtk-tphy.c
··· 971 971 return 0; 972 972 } 973 973 974 - static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) 974 + static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) 975 975 { 976 976 struct mtk_phy_instance *instance = phy_get_drvdata(phy); 977 977 struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
+1 -1
drivers/phy/mediatek/phy-mtk-xsphy.c
··· 426 426 return 0; 427 427 } 428 428 429 - static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) 429 + static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) 430 430 { 431 431 struct xsphy_instance *inst = phy_get_drvdata(phy); 432 432 struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent);
+51 -20
drivers/phy/motorola/phy-mapphone-mdm6600.c
··· 16 16 #include <linux/gpio/consumer.h> 17 17 #include <linux/of_platform.h> 18 18 #include <linux/phy/phy.h> 19 + #include <linux/pinctrl/consumer.h> 19 20 20 21 #define PHY_MDM6600_PHY_DELAY_MS 4000 /* PHY enable 2.2s to 3.5s */ 21 22 #define PHY_MDM6600_ENABLED_DELAY_MS 8000 /* 8s more total for MDM6600 */ ··· 121 120 { 122 121 struct phy_mdm6600 *ddata = phy_get_drvdata(x); 123 122 struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; 123 + int error; 124 124 125 125 if (!ddata->enabled) 126 126 return -ENODEV; 127 127 128 + error = pinctrl_pm_select_default_state(ddata->dev); 129 + if (error) 130 + dev_warn(ddata->dev, "%s: error with default_state: %i\n", 131 + __func__, error); 132 + 128 133 gpiod_set_value_cansleep(enable_gpio, 1); 134 + 135 + /* Allow aggressive PM for USB, it's only needed for n_gsm port */ 136 + if (pm_runtime_enabled(&x->dev)) 137 + phy_pm_runtime_put(x); 129 138 130 139 return 0; 131 140 } ··· 144 133 { 145 134 struct phy_mdm6600 *ddata = phy_get_drvdata(x); 146 135 struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; 136 + int error; 147 137 148 138 if (!ddata->enabled) 149 139 return -ENODEV; 150 140 141 + /* Paired with phy_pm_runtime_put() in phy_mdm6600_power_on() */ 142 + if (pm_runtime_enabled(&x->dev)) { 143 + error = phy_pm_runtime_get(x); 144 + if (error < 0 && error != -EINPROGRESS) 145 + dev_warn(ddata->dev, "%s: phy_pm_runtime_get: %i\n", 146 + __func__, error); 147 + } 148 + 151 149 gpiod_set_value_cansleep(enable_gpio, 0); 150 + 151 + error = pinctrl_pm_select_sleep_state(ddata->dev); 152 + if (error) 153 + dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", 154 + __func__, error); 152 155 153 156 return 0; 154 157 } ··· 554 529 ddata->dev = &pdev->dev; 555 530 platform_set_drvdata(pdev, ddata); 556 531 532 + /* Active state selected in phy_mdm6600_power_on() */ 533 + error = pinctrl_pm_select_sleep_state(ddata->dev); 534 + if (error) 535 + dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", 536 + __func__, error); 537 + 557 538 error = phy_mdm6600_init_lines(ddata); 558 539 if (error) 559 540 return error; 560 541 561 542 phy_mdm6600_init_irq(ddata); 562 - 563 - ddata->generic_phy = devm_phy_create(ddata->dev, NULL, &gpio_usb_ops); 564 - if (IS_ERR(ddata->generic_phy)) { 565 - error = PTR_ERR(ddata->generic_phy); 566 - goto cleanup; 567 - } 568 - 569 - phy_set_drvdata(ddata->generic_phy, ddata); 570 - 571 - ddata->phy_provider = 572 - devm_of_phy_provider_register(ddata->dev, 573 - of_phy_simple_xlate); 574 - if (IS_ERR(ddata->phy_provider)) { 575 - error = PTR_ERR(ddata->phy_provider); 576 - goto cleanup; 577 - } 578 - 579 543 schedule_delayed_work(&ddata->bootup_work, 0); 580 544 581 545 /* ··· 588 574 if (error < 0) { 589 575 dev_warn(ddata->dev, "failed to wake modem: %i\n", error); 590 576 pm_runtime_put_noidle(ddata->dev); 577 + goto cleanup; 591 578 } 579 + 580 + ddata->generic_phy = devm_phy_create(ddata->dev, NULL, &gpio_usb_ops); 581 + if (IS_ERR(ddata->generic_phy)) { 582 + error = PTR_ERR(ddata->generic_phy); 583 + goto idle; 584 + } 585 + 586 + phy_set_drvdata(ddata->generic_phy, ddata); 587 + 588 + ddata->phy_provider = 589 + devm_of_phy_provider_register(ddata->dev, 590 + of_phy_simple_xlate); 591 + if (IS_ERR(ddata->phy_provider)) 592 + error = PTR_ERR(ddata->phy_provider); 593 + 594 + idle: 592 595 pm_runtime_mark_last_busy(ddata->dev); 593 596 pm_runtime_put_autosuspend(ddata->dev); 594 597 595 - return 0; 596 - 597 598 cleanup: 598 - phy_mdm6600_device_power_off(ddata); 599 + if (error < 0) 600 + phy_mdm6600_device_power_off(ddata); 601 + 599 602 return error; 600 603 } 601 604
+17 -7
drivers/phy/mscc/phy-ocelot-serdes.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/of.h> 13 13 #include <linux/of_platform.h> 14 + #include <linux/phy.h> 14 15 #include <linux/phy/phy.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/regmap.h> ··· 105 104 u8 idx; 106 105 u8 port; 107 106 enum phy_mode mode; 107 + int submode; 108 108 u32 mask; 109 109 u32 mux; 110 110 }; 111 111 112 - #define SERDES_MUX(_idx, _port, _mode, _mask, _mux) { \ 112 + #define SERDES_MUX(_idx, _port, _mode, _submode, _mask, _mux) { \ 113 113 .idx = _idx, \ 114 114 .port = _port, \ 115 115 .mode = _mode, \ 116 + .submode = _submode, \ 116 117 .mask = _mask, \ 117 118 .mux = _mux, \ 118 119 } 119 120 120 - #define SERDES_MUX_SGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_SGMII, m, c) 121 - #define SERDES_MUX_QSGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_QSGMII, m, c) 121 + #define SERDES_MUX_SGMII(i, p, m, c) \ 122 + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c) 123 + #define SERDES_MUX_QSGMII(i, p, m, c) \ 124 + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c) 122 125 123 126 static const struct serdes_mux ocelot_serdes_muxes[] = { 124 127 SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0), ··· 159 154 SERDES_MUX_SGMII(SERDES6G(1), 8, 0, 0), 160 155 SERDES_MUX_SGMII(SERDES6G(2), 10, HSIO_HW_CFG_PCIE_ENA | 161 156 HSIO_HW_CFG_DEV2G5_10_MODE, 0), 162 - SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, HSIO_HW_CFG_PCIE_ENA, 157 + SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, 0, HSIO_HW_CFG_PCIE_ENA, 163 158 HSIO_HW_CFG_PCIE_ENA), 164 159 }; 165 160 166 - static int serdes_set_mode(struct phy *phy, enum phy_mode mode) 161 + static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) 167 162 { 168 163 struct serdes_macro *macro = phy_get_drvdata(phy); 169 164 unsigned int i; 170 165 int ret; 171 166 167 + /* As of now only PHY_MODE_ETHERNET is supported */ 168 + if (mode != PHY_MODE_ETHERNET) 169 + return -EOPNOTSUPP; 170 + 172 171 for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) { 173 172 if (macro->idx != ocelot_serdes_muxes[i].idx || 174 - mode != ocelot_serdes_muxes[i].mode) 173 + mode != ocelot_serdes_muxes[i].mode || 174 + submode != ocelot_serdes_muxes[i].submode) 175 175 continue; 176 176 177 - if (mode != PHY_MODE_QSGMII && 177 + if (submode != PHY_INTERFACE_MODE_QSGMII && 178 178 macro->port != ocelot_serdes_muxes[i].port) 179 179 continue; 180 180
+166
drivers/phy/phy-core-mipi-dphy.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2013 NVIDIA Corporation 4 + * Copyright (C) 2018 Cadence Design Systems Inc. 5 + */ 6 + 7 + #include <linux/errno.h> 8 + #include <linux/export.h> 9 + #include <linux/kernel.h> 10 + #include <linux/time64.h> 11 + 12 + #include <linux/phy/phy.h> 13 + #include <linux/phy/phy-mipi-dphy.h> 14 + 15 + #define PSEC_PER_SEC 1000000000000LL 16 + 17 + /* 18 + * Minimum D-PHY timings based on MIPI D-PHY specification. Derived 19 + * from the valid ranges specified in Section 6.9, Table 14, Page 41 20 + * of the D-PHY specification (v2.1). 21 + */ 22 + int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, 23 + unsigned int bpp, 24 + unsigned int lanes, 25 + struct phy_configure_opts_mipi_dphy *cfg) 26 + { 27 + unsigned long long hs_clk_rate; 28 + unsigned long long ui; 29 + 30 + if (!cfg) 31 + return -EINVAL; 32 + 33 + hs_clk_rate = pixel_clock * bpp; 34 + do_div(hs_clk_rate, lanes); 35 + 36 + ui = ALIGN(PSEC_PER_SEC, hs_clk_rate); 37 + do_div(ui, hs_clk_rate); 38 + 39 + cfg->clk_miss = 0; 40 + cfg->clk_post = 60000 + 52 * ui; 41 + cfg->clk_pre = 8000; 42 + cfg->clk_prepare = 38000; 43 + cfg->clk_settle = 95000; 44 + cfg->clk_term_en = 0; 45 + cfg->clk_trail = 60000; 46 + cfg->clk_zero = 262000; 47 + cfg->d_term_en = 0; 48 + cfg->eot = 0; 49 + cfg->hs_exit = 100000; 50 + cfg->hs_prepare = 40000 + 4 * ui; 51 + cfg->hs_zero = 105000 + 6 * ui; 52 + cfg->hs_settle = 85000 + 6 * ui; 53 + cfg->hs_skip = 40000; 54 + 55 + /* 56 + * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40) 57 + * contains this formula as: 58 + * 59 + * T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui) 60 + * 61 + * where n = 1 for forward-direction HS mode and n = 4 for reverse- 62 + * direction HS mode. There's only one setting and this function does 63 + * not parameterize on anything other that ui, so this code will 64 + * assumes that reverse-direction HS mode is supported and uses n = 4. 65 + */ 66 + cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui); 67 + 68 + cfg->init = 100000000; 69 + cfg->lpx = 60000; 70 + cfg->ta_get = 5 * cfg->lpx; 71 + cfg->ta_go = 4 * cfg->lpx; 72 + cfg->ta_sure = 2 * cfg->lpx; 73 + cfg->wakeup = 1000000000; 74 + 75 + cfg->hs_clk_rate = hs_clk_rate; 76 + cfg->lanes = lanes; 77 + 78 + return 0; 79 + } 80 + EXPORT_SYMBOL(phy_mipi_dphy_get_default_config); 81 + 82 + /* 83 + * Validate D-PHY configuration according to MIPI D-PHY specification 84 + * (v1.2, Section Section 6.9 "Global Operation Timing Parameters"). 85 + */ 86 + int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg) 87 + { 88 + unsigned long long ui; 89 + 90 + if (!cfg) 91 + return -EINVAL; 92 + 93 + ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate); 94 + do_div(ui, cfg->hs_clk_rate); 95 + 96 + if (cfg->clk_miss > 60000) 97 + return -EINVAL; 98 + 99 + if (cfg->clk_post < (60000 + 52 * ui)) 100 + return -EINVAL; 101 + 102 + if (cfg->clk_pre < 8000) 103 + return -EINVAL; 104 + 105 + if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000) 106 + return -EINVAL; 107 + 108 + if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000) 109 + return -EINVAL; 110 + 111 + if (cfg->clk_term_en > 38000) 112 + return -EINVAL; 113 + 114 + if (cfg->clk_trail < 60000) 115 + return -EINVAL; 116 + 117 + if ((cfg->clk_prepare + cfg->clk_zero) < 300000) 118 + return -EINVAL; 119 + 120 + if (cfg->d_term_en > (35000 + 4 * ui)) 121 + return -EINVAL; 122 + 123 + if (cfg->eot > (105000 + 12 * ui)) 124 + return -EINVAL; 125 + 126 + if (cfg->hs_exit < 100000) 127 + return -EINVAL; 128 + 129 + if (cfg->hs_prepare < (40000 + 4 * ui) || 130 + cfg->hs_prepare > (85000 + 6 * ui)) 131 + return -EINVAL; 132 + 133 + if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui)) 134 + return -EINVAL; 135 + 136 + if ((cfg->hs_settle < (85000 + 6 * ui)) || 137 + (cfg->hs_settle > (145000 + 10 * ui))) 138 + return -EINVAL; 139 + 140 + if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui)) 141 + return -EINVAL; 142 + 143 + if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui)) 144 + return -EINVAL; 145 + 146 + if (cfg->init < 100000000) 147 + return -EINVAL; 148 + 149 + if (cfg->lpx < 50000) 150 + return -EINVAL; 151 + 152 + if (cfg->ta_get != (5 * cfg->lpx)) 153 + return -EINVAL; 154 + 155 + if (cfg->ta_go != (4 * cfg->lpx)) 156 + return -EINVAL; 157 + 158 + if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx)) 159 + return -EINVAL; 160 + 161 + if (cfg->wakeup < 1000000000) 162 + return -EINVAL; 163 + 164 + return 0; 165 + } 166 + EXPORT_SYMBOL(phy_mipi_dphy_config_validate);
+67 -3
drivers/phy/phy-core.c
··· 360 360 } 361 361 EXPORT_SYMBOL_GPL(phy_power_off); 362 362 363 - int phy_set_mode(struct phy *phy, enum phy_mode mode) 363 + int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) 364 364 { 365 365 int ret; 366 366 ··· 368 368 return 0; 369 369 370 370 mutex_lock(&phy->mutex); 371 - ret = phy->ops->set_mode(phy, mode); 371 + ret = phy->ops->set_mode(phy, mode, submode); 372 372 if (!ret) 373 373 phy->attrs.mode = mode; 374 374 mutex_unlock(&phy->mutex); 375 375 376 376 return ret; 377 377 } 378 - EXPORT_SYMBOL_GPL(phy_set_mode); 378 + EXPORT_SYMBOL_GPL(phy_set_mode_ext); 379 379 380 380 int phy_reset(struct phy *phy) 381 381 { ··· 406 406 return ret; 407 407 } 408 408 EXPORT_SYMBOL_GPL(phy_calibrate); 409 + 410 + /** 411 + * phy_configure() - Changes the phy parameters 412 + * @phy: the phy returned by phy_get() 413 + * @opts: New configuration to apply 414 + * 415 + * Used to change the PHY parameters. phy_init() must have been called 416 + * on the phy. The configuration will be applied on the current phy 417 + * mode, that can be changed using phy_set_mode(). 418 + * 419 + * Returns: 0 if successful, an negative error code otherwise 420 + */ 421 + int phy_configure(struct phy *phy, union phy_configure_opts *opts) 422 + { 423 + int ret; 424 + 425 + if (!phy) 426 + return -EINVAL; 427 + 428 + if (!phy->ops->configure) 429 + return -EOPNOTSUPP; 430 + 431 + mutex_lock(&phy->mutex); 432 + ret = phy->ops->configure(phy, opts); 433 + mutex_unlock(&phy->mutex); 434 + 435 + return ret; 436 + } 437 + EXPORT_SYMBOL_GPL(phy_configure); 438 + 439 + /** 440 + * phy_validate() - Checks the phy parameters 441 + * @phy: the phy returned by phy_get() 442 + * @mode: phy_mode the configuration is applicable to. 443 + * @submode: PHY submode the configuration is applicable to. 444 + * @opts: Configuration to check 445 + * 446 + * Used to check that the current set of parameters can be handled by 447 + * the phy. Implementations are free to tune the parameters passed as 448 + * arguments if needed by some implementation detail or 449 + * constraints. It will not change any actual configuration of the 450 + * PHY, so calling it as many times as deemed fit will have no side 451 + * effect. 452 + * 453 + * Returns: 0 if successful, an negative error code otherwise 454 + */ 455 + int phy_validate(struct phy *phy, enum phy_mode mode, int submode, 456 + union phy_configure_opts *opts) 457 + { 458 + int ret; 459 + 460 + if (!phy) 461 + return -EINVAL; 462 + 463 + if (!phy->ops->validate) 464 + return -EOPNOTSUPP; 465 + 466 + mutex_lock(&phy->mutex); 467 + ret = phy->ops->validate(phy, mode, submode, opts); 468 + mutex_unlock(&phy->mutex); 469 + 470 + return ret; 471 + } 472 + EXPORT_SYMBOL_GPL(phy_validate); 409 473 410 474 /** 411 475 * _of_phy_get() - lookup and obtain a reference to a phy by phandle
+62 -15
drivers/phy/qualcomm/phy-qcom-qmp.c
··· 72 72 73 73 #define MAX_PROP_NAME 32 74 74 75 + /* Define the assumed distance between lanes for underspecified device trees. */ 76 + #define QMP_PHY_LEGACY_LANE_STRIDE 0x400 77 + 75 78 struct qmp_phy_init_tbl { 76 79 unsigned int offset; 77 80 unsigned int val; ··· 736 733 bool has_phy_dp_com_ctrl; 737 734 /* true, if PHY has secondary tx/rx lanes to be configured */ 738 735 bool is_dual_lane_phy; 739 - /* Register offset of secondary tx/rx lanes for USB DP combo PHY */ 740 - unsigned int tx_b_lane_offset; 741 - unsigned int rx_b_lane_offset; 742 736 743 737 /* true, if PCS block has no separate SW_RESET register */ 744 738 bool no_pcs_sw_reset; ··· 748 748 * @tx: iomapped memory space for lane's tx 749 749 * @rx: iomapped memory space for lane's rx 750 750 * @pcs: iomapped memory space for lane's pcs 751 + * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) 752 + * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) 751 753 * @pcs_misc: iomapped memory space for lane's pcs_misc 752 754 * @pipe_clk: pipe lock 753 755 * @index: lane index ··· 761 759 void __iomem *tx; 762 760 void __iomem *rx; 763 761 void __iomem *pcs; 762 + void __iomem *tx2; 763 + void __iomem *rx2; 764 764 void __iomem *pcs_misc; 765 765 struct clk *pipe_clk; 766 766 unsigned int index; ··· 979 975 980 976 .has_phy_dp_com_ctrl = true, 981 977 .is_dual_lane_phy = true, 982 - .tx_b_lane_offset = 0x400, 983 - .rx_b_lane_offset = 0x400, 984 978 }; 985 979 986 980 static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { ··· 1033 1031 .mask_pcs_ready = PCS_READY, 1034 1032 1035 1033 .is_dual_lane_phy = true, 1036 - .tx_b_lane_offset = 0x400, 1037 - .rx_b_lane_offset = 0x400, 1038 - 1039 1034 .no_pcs_sw_reset = true, 1040 1035 }; 1041 1036 ··· 1237 1238 qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); 1238 1239 /* Configuration for other LANE for USB-DP combo PHY */ 1239 1240 if (cfg->is_dual_lane_phy) 1240 - qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs, 1241 + qcom_qmp_phy_configure(qphy->tx2, cfg->regs, 1241 1242 cfg->tx_tbl, cfg->tx_tbl_num); 1242 1243 1243 1244 qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num); 1244 1245 if (cfg->is_dual_lane_phy) 1245 - qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs, 1246 + qcom_qmp_phy_configure(qphy->rx2, cfg->regs, 1246 1247 cfg->rx_tbl, cfg->rx_tbl_num); 1247 1248 1248 1249 qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ··· 1364 1365 return ret; 1365 1366 } 1366 1367 1367 - static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode) 1368 + static int qcom_qmp_phy_set_mode(struct phy *phy, 1369 + enum phy_mode mode, int submode) 1368 1370 { 1369 1371 struct qmp_phy *qphy = phy_get_drvdata(phy); 1370 1372 struct qcom_qmp *qmp = qphy->qmp; ··· 1542 1542 return devm_clk_bulk_get(dev, num, qmp->clks); 1543 1543 } 1544 1544 1545 + static void phy_pipe_clk_release_provider(void *res) 1546 + { 1547 + of_clk_del_provider(res); 1548 + } 1549 + 1545 1550 /* 1546 1551 * Register a fixed rate pipe clock. 1547 1552 * ··· 1593 1588 fixed->fixed_rate = 125000000; 1594 1589 fixed->hw.init = &init; 1595 1590 1596 - return devm_clk_hw_register(qmp->dev, &fixed->hw); 1591 + ret = devm_clk_hw_register(qmp->dev, &fixed->hw); 1592 + if (ret) 1593 + return ret; 1594 + 1595 + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); 1596 + if (ret) 1597 + return ret; 1598 + 1599 + /* 1600 + * Roll a devm action because the clock provider is the child node, but 1601 + * the child node is not actually a device. 1602 + */ 1603 + ret = devm_add_action(qmp->dev, phy_pipe_clk_release_provider, np); 1604 + if (ret) 1605 + phy_pipe_clk_release_provider(np); 1606 + 1607 + return ret; 1597 1608 } 1598 1609 1599 1610 static const struct phy_ops qcom_qmp_phy_gen_ops = { ··· 1635 1614 1636 1615 /* 1637 1616 * Get memory resources for each phy lane: 1638 - * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; and 1639 - * pcs_misc (optional) -> 3. 1617 + * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. 1618 + * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 1619 + * For single lane PHYs: pcs_misc (optional) -> 3. 1640 1620 */ 1641 1621 qphy->tx = of_iomap(np, 0); 1642 1622 if (!qphy->tx) ··· 1651 1629 if (!qphy->pcs) 1652 1630 return -ENOMEM; 1653 1631 1654 - qphy->pcs_misc = of_iomap(np, 3); 1632 + /* 1633 + * If this is a dual-lane PHY, then there should be registers for the 1634 + * second lane. Some old device trees did not specify this, so fall 1635 + * back to old legacy behavior of assuming they can be reached at an 1636 + * offset from the first lane. 1637 + */ 1638 + if (qmp->cfg->is_dual_lane_phy) { 1639 + qphy->tx2 = of_iomap(np, 3); 1640 + qphy->rx2 = of_iomap(np, 4); 1641 + if (!qphy->tx2 || !qphy->rx2) { 1642 + dev_warn(dev, 1643 + "Underspecified device tree, falling back to legacy register regions\n"); 1644 + 1645 + /* In the old version, pcs_misc is at index 3. */ 1646 + qphy->pcs_misc = qphy->tx2; 1647 + qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; 1648 + qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; 1649 + 1650 + } else { 1651 + qphy->pcs_misc = of_iomap(np, 5); 1652 + } 1653 + 1654 + } else { 1655 + qphy->pcs_misc = of_iomap(np, 3); 1656 + } 1657 + 1655 1658 if (!qphy->pcs_misc) 1656 1659 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); 1657 1660
+2 -1
drivers/phy/qualcomm/phy-qcom-qusb2.c
··· 425 425 HSTX_TRIM_MASK); 426 426 } 427 427 428 - static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) 428 + static int qusb2_phy_set_mode(struct phy *phy, 429 + enum phy_mode mode, int submode) 429 430 { 430 431 struct qusb2_phy *qphy = phy_get_drvdata(phy); 431 432
+2 -1
drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
··· 65 65 } 66 66 67 67 static 68 - int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, enum phy_mode mode) 68 + int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, 69 + enum phy_mode mode, int submode) 69 70 { 70 71 struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); 71 72
+2 -1
drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
··· 84 84 } 85 85 86 86 static 87 - int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, enum phy_mode mode) 87 + int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, 88 + enum phy_mode mode, int submode) 88 89 { 89 90 struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); 90 91
+2 -1
drivers/phy/qualcomm/phy-qcom-usb-hs.c
··· 42 42 struct notifier_block vbus_notify; 43 43 }; 44 44 45 - static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode) 45 + static int qcom_usb_hs_phy_set_mode(struct phy *phy, 46 + enum phy_mode mode, int submode) 46 47 { 47 48 struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); 48 49 u8 addr;
+11 -6
drivers/phy/renesas/phy-rcar-gen3-usb2.c
··· 307 307 void __iomem *usb2_base = ch->base; 308 308 u32 val; 309 309 310 + /* Should not use functions of read-modify-write a register */ 311 + val = readl(usb2_base + USB2_LINECTRL1); 312 + val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN | 313 + USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD; 314 + writel(val, usb2_base + USB2_LINECTRL1); 315 + 310 316 val = readl(usb2_base + USB2_VBCTRL); 311 317 writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); 312 - writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); 313 - rcar_gen3_control_otg_irq(ch, 1); 314 318 val = readl(usb2_base + USB2_ADPCTRL); 315 319 writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); 316 - val = readl(usb2_base + USB2_LINECTRL1); 317 - rcar_gen3_set_linectrl(ch, 0, 0); 318 - writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN, 319 - usb2_base + USB2_LINECTRL1); 320 + 321 + msleep(20); 322 + 323 + writel(0xffffffff, usb2_base + USB2_OBINTSTA); 324 + writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); 320 325 321 326 rcar_gen3_device_recognition(ch); 322 327 }
+3 -3
drivers/phy/rockchip/phy-rockchip-inno-usb2.c
··· 1168 1168 struct phy *phy; 1169 1169 1170 1170 /* This driver aims to support both otg-port and host-port */ 1171 - if (of_node_cmp(child_np->name, "host-port") && 1172 - of_node_cmp(child_np->name, "otg-port")) 1171 + if (!of_node_name_eq(child_np, "host-port") && 1172 + !of_node_name_eq(child_np, "otg-port")) 1173 1173 goto next_child; 1174 1174 1175 1175 phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops); ··· 1183 1183 phy_set_drvdata(rport->phy, rport); 1184 1184 1185 1185 /* initialize otg/host port separately */ 1186 - if (!of_node_cmp(child_np->name, "host-port")) { 1186 + if (of_node_name_eq(child_np, "host-port")) { 1187 1187 ret = rockchip_usb2phy_host_port_init(rphy, rport, 1188 1188 child_np); 1189 1189 if (ret)
+2 -2
drivers/phy/rockchip/phy-rockchip-typec.c
··· 1176 1176 for_each_available_child_of_node(np, child_np) { 1177 1177 struct phy *phy; 1178 1178 1179 - if (!of_node_cmp(child_np->name, "dp-port")) 1179 + if (of_node_name_eq(child_np, "dp-port")) 1180 1180 phy = devm_phy_create(dev, child_np, 1181 1181 &rockchip_dp_phy_ops); 1182 - else if (!of_node_cmp(child_np->name, "usb3-port")) 1182 + else if (of_node_name_eq(child_np, "usb3-port")) 1183 1183 phy = devm_phy_create(dev, child_np, 1184 1184 &rockchip_usb3_phy_ops); 1185 1185 else
+10
drivers/phy/ti/Kconfig
··· 76 76 family chips (including the TWL5030 and TPS659x0 devices). 77 77 This transceiver supports high and full speed devices plus, 78 78 in host mode, low speed. 79 + 80 + config PHY_TI_GMII_SEL 81 + tristate 82 + default y if TI_CPSW=y 83 + depends on TI_CPSW || COMPILE_TEST 84 + select GENERIC_PHY 85 + default m 86 + help 87 + This driver supports configuring of the TI CPSW Port mode depending on 88 + the Ethernet PHY connected to the CPSW Port.
+1
drivers/phy/ti/Makefile
··· 6 6 obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o 7 7 obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o 8 8 obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o 9 + obj-$(CONFIG_PHY_TI_GMII_SEL) += phy-gmii-sel.o
+2 -1
drivers/phy/ti/phy-da8xx-usb.c
··· 93 93 return 0; 94 94 } 95 95 96 - static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode) 96 + static int da8xx_usb20_phy_set_mode(struct phy *phy, 97 + enum phy_mode mode, int submode) 97 98 { 98 99 struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); 99 100 u32 val;
+349
drivers/phy/ti/phy-gmii-sel.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Texas Instruments CPSW Port's PHY Interface Mode selection Driver 4 + * 5 + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ 6 + * 7 + * Based on cpsw-phy-sel.c driver created by Mugunthan V N <mugunthanvnm@ti.com> 8 + */ 9 + 10 + #include <linux/platform_device.h> 11 + #include <linux/module.h> 12 + #include <linux/mfd/syscon.h> 13 + #include <linux/of.h> 14 + #include <linux/of_net.h> 15 + #include <linux/phy.h> 16 + #include <linux/phy/phy.h> 17 + #include <linux/regmap.h> 18 + 19 + /* AM33xx SoC specific definitions for the CONTROL port */ 20 + #define AM33XX_GMII_SEL_MODE_MII 0 21 + #define AM33XX_GMII_SEL_MODE_RMII 1 22 + #define AM33XX_GMII_SEL_MODE_RGMII 2 23 + 24 + enum { 25 + PHY_GMII_SEL_PORT_MODE, 26 + PHY_GMII_SEL_RGMII_ID_MODE, 27 + PHY_GMII_SEL_RMII_IO_CLK_EN, 28 + PHY_GMII_SEL_LAST, 29 + }; 30 + 31 + struct phy_gmii_sel_phy_priv { 32 + struct phy_gmii_sel_priv *priv; 33 + u32 id; 34 + struct phy *if_phy; 35 + int rmii_clock_external; 36 + int phy_if_mode; 37 + struct regmap_field *fields[PHY_GMII_SEL_LAST]; 38 + }; 39 + 40 + struct phy_gmii_sel_soc_data { 41 + u32 num_ports; 42 + u32 features; 43 + const struct reg_field (*regfields)[PHY_GMII_SEL_LAST]; 44 + }; 45 + 46 + struct phy_gmii_sel_priv { 47 + struct device *dev; 48 + const struct phy_gmii_sel_soc_data *soc_data; 49 + struct regmap *regmap; 50 + struct phy_provider *phy_provider; 51 + struct phy_gmii_sel_phy_priv *if_phys; 52 + }; 53 + 54 + static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) 55 + { 56 + struct phy_gmii_sel_phy_priv *if_phy = phy_get_drvdata(phy); 57 + const struct phy_gmii_sel_soc_data *soc_data = if_phy->priv->soc_data; 58 + struct device *dev = if_phy->priv->dev; 59 + struct regmap_field *regfield; 60 + int ret, rgmii_id = 0; 61 + u32 gmii_sel_mode = 0; 62 + 63 + if (mode != PHY_MODE_ETHERNET) 64 + return -EINVAL; 65 + 66 + switch (submode) { 67 + case PHY_INTERFACE_MODE_RMII: 68 + gmii_sel_mode = AM33XX_GMII_SEL_MODE_RMII; 69 + break; 70 + 71 + case PHY_INTERFACE_MODE_RGMII: 72 + gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII; 73 + break; 74 + 75 + case PHY_INTERFACE_MODE_RGMII_ID: 76 + case PHY_INTERFACE_MODE_RGMII_RXID: 77 + case PHY_INTERFACE_MODE_RGMII_TXID: 78 + gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII; 79 + rgmii_id = 1; 80 + break; 81 + 82 + case PHY_INTERFACE_MODE_MII: 83 + mode = AM33XX_GMII_SEL_MODE_MII; 84 + break; 85 + 86 + default: 87 + dev_warn(dev, 88 + "port%u: unsupported mode: \"%s\". Defaulting to MII.\n", 89 + if_phy->id, phy_modes(rgmii_id)); 90 + return -EINVAL; 91 + } 92 + 93 + if_phy->phy_if_mode = submode; 94 + 95 + dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n", 96 + __func__, if_phy->id, mode, rgmii_id, 97 + if_phy->rmii_clock_external); 98 + 99 + regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE]; 100 + ret = regmap_field_write(regfield, gmii_sel_mode); 101 + if (ret) { 102 + dev_err(dev, "port%u: set mode fail %d", if_phy->id, ret); 103 + return ret; 104 + } 105 + 106 + if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE) && 107 + if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]) { 108 + regfield = if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]; 109 + ret = regmap_field_write(regfield, rgmii_id); 110 + if (ret) 111 + return ret; 112 + } 113 + 114 + if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && 115 + if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]) { 116 + regfield = if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]; 117 + ret = regmap_field_write(regfield, 118 + if_phy->rmii_clock_external); 119 + } 120 + 121 + return 0; 122 + } 123 + 124 + static const 125 + struct reg_field phy_gmii_sel_fields_am33xx[][PHY_GMII_SEL_LAST] = { 126 + { 127 + [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x650, 0, 1), 128 + [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x650, 4, 4), 129 + [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD(0x650, 6, 6), 130 + }, 131 + { 132 + [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x650, 2, 3), 133 + [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x650, 5, 5), 134 + [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD(0x650, 7, 7), 135 + }, 136 + }; 137 + 138 + static const 139 + struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am33xx = { 140 + .num_ports = 2, 141 + .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | 142 + BIT(PHY_GMII_SEL_RMII_IO_CLK_EN), 143 + .regfields = phy_gmii_sel_fields_am33xx, 144 + }; 145 + 146 + static const 147 + struct reg_field phy_gmii_sel_fields_dra7[][PHY_GMII_SEL_LAST] = { 148 + { 149 + [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 0, 1), 150 + [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), 151 + [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), 152 + }, 153 + { 154 + [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 4, 5), 155 + [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), 156 + [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), 157 + }, 158 + }; 159 + 160 + static const 161 + struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dra7 = { 162 + .num_ports = 2, 163 + .regfields = phy_gmii_sel_fields_dra7, 164 + }; 165 + 166 + static const 167 + struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = { 168 + .num_ports = 2, 169 + .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE), 170 + .regfields = phy_gmii_sel_fields_am33xx, 171 + }; 172 + 173 + static const struct of_device_id phy_gmii_sel_id_table[] = { 174 + { 175 + .compatible = "ti,am3352-phy-gmii-sel", 176 + .data = &phy_gmii_sel_soc_am33xx, 177 + }, 178 + { 179 + .compatible = "ti,dra7xx-phy-gmii-sel", 180 + .data = &phy_gmii_sel_soc_dra7, 181 + }, 182 + { 183 + .compatible = "ti,am43xx-phy-gmii-sel", 184 + .data = &phy_gmii_sel_soc_am33xx, 185 + }, 186 + { 187 + .compatible = "ti,dm814-phy-gmii-sel", 188 + .data = &phy_gmii_sel_soc_dm814, 189 + }, 190 + {} 191 + }; 192 + MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table); 193 + 194 + static const struct phy_ops phy_gmii_sel_ops = { 195 + .set_mode = phy_gmii_sel_mode, 196 + .owner = THIS_MODULE, 197 + }; 198 + 199 + static struct phy *phy_gmii_sel_of_xlate(struct device *dev, 200 + struct of_phandle_args *args) 201 + { 202 + struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev); 203 + int phy_id = args->args[0]; 204 + 205 + if (args->args_count < 1) 206 + return ERR_PTR(-EINVAL); 207 + if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && 208 + args->args_count < 2) 209 + return ERR_PTR(-EINVAL); 210 + if (!priv || !priv->if_phys) 211 + return ERR_PTR(-ENODEV); 212 + if (phy_id > priv->soc_data->num_ports) 213 + return ERR_PTR(-EINVAL); 214 + if (phy_id != priv->if_phys[phy_id - 1].id) 215 + return ERR_PTR(-EINVAL); 216 + 217 + phy_id--; 218 + if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)) 219 + priv->if_phys[phy_id].rmii_clock_external = args->args[1]; 220 + dev_dbg(dev, "%s id:%u ext:%d\n", __func__, 221 + priv->if_phys[phy_id].id, args->args[1]); 222 + 223 + return priv->if_phys[phy_id].if_phy; 224 + } 225 + 226 + static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv) 227 + { 228 + const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; 229 + struct device *dev = priv->dev; 230 + struct phy_gmii_sel_phy_priv *if_phys; 231 + int i, num_ports, ret; 232 + 233 + num_ports = priv->soc_data->num_ports; 234 + 235 + if_phys = devm_kcalloc(priv->dev, num_ports, 236 + sizeof(*if_phys), GFP_KERNEL); 237 + if (!if_phys) 238 + return -ENOMEM; 239 + dev_dbg(dev, "%s %d\n", __func__, num_ports); 240 + 241 + for (i = 0; i < num_ports; i++) { 242 + const struct reg_field *field; 243 + struct regmap_field *regfield; 244 + 245 + if_phys[i].id = i + 1; 246 + if_phys[i].priv = priv; 247 + 248 + field = &soc_data->regfields[i][PHY_GMII_SEL_PORT_MODE]; 249 + dev_dbg(dev, "%s field %x %d %d\n", __func__, 250 + field->reg, field->msb, field->lsb); 251 + 252 + regfield = devm_regmap_field_alloc(dev, priv->regmap, *field); 253 + if (IS_ERR(regfield)) 254 + return PTR_ERR(regfield); 255 + if_phys[i].fields[PHY_GMII_SEL_PORT_MODE] = regfield; 256 + 257 + field = &soc_data->regfields[i][PHY_GMII_SEL_RGMII_ID_MODE]; 258 + if (field->reg != (~0)) { 259 + regfield = devm_regmap_field_alloc(dev, 260 + priv->regmap, 261 + *field); 262 + if (IS_ERR(regfield)) 263 + return PTR_ERR(regfield); 264 + if_phys[i].fields[PHY_GMII_SEL_RGMII_ID_MODE] = 265 + regfield; 266 + } 267 + 268 + field = &soc_data->regfields[i][PHY_GMII_SEL_RMII_IO_CLK_EN]; 269 + if (field->reg != (~0)) { 270 + regfield = devm_regmap_field_alloc(dev, 271 + priv->regmap, 272 + *field); 273 + if (IS_ERR(regfield)) 274 + return PTR_ERR(regfield); 275 + if_phys[i].fields[PHY_GMII_SEL_RMII_IO_CLK_EN] = 276 + regfield; 277 + } 278 + 279 + if_phys[i].if_phy = devm_phy_create(dev, 280 + priv->dev->of_node, 281 + &phy_gmii_sel_ops); 282 + if (IS_ERR(if_phys[i].if_phy)) { 283 + ret = PTR_ERR(if_phys[i].if_phy); 284 + dev_err(dev, "Failed to create phy%d %d\n", i, ret); 285 + return ret; 286 + } 287 + phy_set_drvdata(if_phys[i].if_phy, &if_phys[i]); 288 + } 289 + 290 + priv->if_phys = if_phys; 291 + return 0; 292 + } 293 + 294 + static int phy_gmii_sel_probe(struct platform_device *pdev) 295 + { 296 + struct device *dev = &pdev->dev; 297 + struct device_node *node = dev->of_node; 298 + const struct of_device_id *of_id; 299 + struct phy_gmii_sel_priv *priv; 300 + int ret; 301 + 302 + of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node); 303 + if (!of_id) 304 + return -EINVAL; 305 + 306 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 307 + if (!priv) 308 + return -ENOMEM; 309 + 310 + priv->dev = &pdev->dev; 311 + priv->soc_data = of_id->data; 312 + 313 + priv->regmap = syscon_node_to_regmap(node->parent); 314 + if (IS_ERR(priv->regmap)) { 315 + ret = PTR_ERR(priv->regmap); 316 + dev_err(dev, "Failed to get syscon %d\n", ret); 317 + return ret; 318 + } 319 + 320 + ret = phy_gmii_sel_init_ports(priv); 321 + if (ret) 322 + return ret; 323 + 324 + dev_set_drvdata(&pdev->dev, priv); 325 + 326 + priv->phy_provider = 327 + devm_of_phy_provider_register(dev, 328 + phy_gmii_sel_of_xlate); 329 + if (IS_ERR(priv->phy_provider)) { 330 + ret = PTR_ERR(priv->phy_provider); 331 + dev_err(dev, "Failed to create phy provider %d\n", ret); 332 + return ret; 333 + } 334 + 335 + return 0; 336 + } 337 + 338 + static struct platform_driver phy_gmii_sel_driver = { 339 + .probe = phy_gmii_sel_probe, 340 + .driver = { 341 + .name = "phy-gmii-sel", 342 + .of_match_table = phy_gmii_sel_id_table, 343 + }, 344 + }; 345 + module_platform_driver(phy_gmii_sel_driver); 346 + 347 + MODULE_LICENSE("GPL v2"); 348 + MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>"); 349 + MODULE_DESCRIPTION("TI CPSW Port's PHY Interface Mode selection Driver");
+1 -1
drivers/phy/ti/phy-tusb1210.c
··· 53 53 return 0; 54 54 } 55 55 56 - static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode) 56 + static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode) 57 57 { 58 58 struct tusb1210 *tusb = phy_get_drvdata(phy); 59 59 int ret;
+285
include/linux/phy/phy-mipi-dphy.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2018 Cadence Design Systems Inc. 4 + */ 5 + 6 + #ifndef __PHY_MIPI_DPHY_H_ 7 + #define __PHY_MIPI_DPHY_H_ 8 + 9 + #include <video/videomode.h> 10 + 11 + /** 12 + * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set 13 + * 14 + * This structure is used to represent the configuration state of a 15 + * MIPI D-PHY phy. 16 + */ 17 + struct phy_configure_opts_mipi_dphy { 18 + /** 19 + * @clk_miss: 20 + * 21 + * Timeout, in picoseconds, for receiver to detect absence of 22 + * Clock transitions and disable the Clock Lane HS-RX. 23 + * 24 + * Maximum value: 60000 ps 25 + */ 26 + unsigned int clk_miss; 27 + 28 + /** 29 + * @clk_post: 30 + * 31 + * Time, in picoseconds, that the transmitter continues to 32 + * send HS clock after the last associated Data Lane has 33 + * transitioned to LP Mode. Interval is defined as the period 34 + * from the end of @hs_trail to the beginning of @clk_trail. 35 + * 36 + * Minimum value: 60000 ps + 52 * @hs_clk_rate period in ps 37 + */ 38 + unsigned int clk_post; 39 + 40 + /** 41 + * @clk_pre: 42 + * 43 + * Time, in UI, that the HS clock shall be driven by 44 + * the transmitter prior to any associated Data Lane beginning 45 + * the transition from LP to HS mode. 46 + * 47 + * Minimum value: 8 UI 48 + */ 49 + unsigned int clk_pre; 50 + 51 + /** 52 + * @clk_prepare: 53 + * 54 + * Time, in picoseconds, that the transmitter drives the Clock 55 + * Lane LP-00 Line state immediately before the HS-0 Line 56 + * state starting the HS transmission. 57 + * 58 + * Minimum value: 38000 ps 59 + * Maximum value: 95000 ps 60 + */ 61 + unsigned int clk_prepare; 62 + 63 + /** 64 + * @clk_settle: 65 + * 66 + * Time interval, in picoseconds, during which the HS receiver 67 + * should ignore any Clock Lane HS transitions, starting from 68 + * the beginning of @clk_prepare. 69 + * 70 + * Minimum value: 95000 ps 71 + * Maximum value: 300000 ps 72 + */ 73 + unsigned int clk_settle; 74 + 75 + /** 76 + * @clk_term_en: 77 + * 78 + * Time, in picoseconds, for the Clock Lane receiver to enable 79 + * the HS line termination. 80 + * 81 + * Maximum value: 38000 ps 82 + */ 83 + unsigned int clk_term_en; 84 + 85 + /** 86 + * @clk_trail: 87 + * 88 + * Time, in picoseconds, that the transmitter drives the HS-0 89 + * state after the last payload clock bit of a HS transmission 90 + * burst. 91 + * 92 + * Minimum value: 60000 ps 93 + */ 94 + unsigned int clk_trail; 95 + 96 + /** 97 + * @clk_zero: 98 + * 99 + * Time, in picoseconds, that the transmitter drives the HS-0 100 + * state prior to starting the Clock. 101 + */ 102 + unsigned int clk_zero; 103 + 104 + /** 105 + * @d_term_en: 106 + * 107 + * Time, in picoseconds, for the Data Lane receiver to enable 108 + * the HS line termination. 109 + * 110 + * Maximum value: 35000 ps + 4 * @hs_clk_rate period in ps 111 + */ 112 + unsigned int d_term_en; 113 + 114 + /** 115 + * @eot: 116 + * 117 + * Transmitted time interval, in picoseconds, from the start 118 + * of @hs_trail or @clk_trail, to the start of the LP- 11 119 + * state following a HS burst. 120 + * 121 + * Maximum value: 105000 ps + 12 * @hs_clk_rate period in ps 122 + */ 123 + unsigned int eot; 124 + 125 + /** 126 + * @hs_exit: 127 + * 128 + * Time, in picoseconds, that the transmitter drives LP-11 129 + * following a HS burst. 130 + * 131 + * Minimum value: 100000 ps 132 + */ 133 + unsigned int hs_exit; 134 + 135 + /** 136 + * @hs_prepare: 137 + * 138 + * Time, in picoseconds, that the transmitter drives the Data 139 + * Lane LP-00 Line state immediately before the HS-0 Line 140 + * state starting the HS transmission. 141 + * 142 + * Minimum value: 40000 ps + 4 * @hs_clk_rate period in ps 143 + * Maximum value: 85000 ps + 6 * @hs_clk_rate period in ps 144 + */ 145 + unsigned int hs_prepare; 146 + 147 + /** 148 + * @hs_settle: 149 + * 150 + * Time interval, in picoseconds, during which the HS receiver 151 + * shall ignore any Data Lane HS transitions, starting from 152 + * the beginning of @hs_prepare. 153 + * 154 + * Minimum value: 85000 ps + 6 * @hs_clk_rate period in ps 155 + * Maximum value: 145000 ps + 10 * @hs_clk_rate period in ps 156 + */ 157 + unsigned int hs_settle; 158 + 159 + /** 160 + * @hs_skip: 161 + * 162 + * Time interval, in picoseconds, during which the HS-RX 163 + * should ignore any transitions on the Data Lane, following a 164 + * HS burst. The end point of the interval is defined as the 165 + * beginning of the LP-11 state following the HS burst. 166 + * 167 + * Minimum value: 40000 ps 168 + * Maximum value: 55000 ps + 4 * @hs_clk_rate period in ps 169 + */ 170 + unsigned int hs_skip; 171 + 172 + /** 173 + * @hs_trail: 174 + * 175 + * Time, in picoseconds, that the transmitter drives the 176 + * flipped differential state after last payload data bit of a 177 + * HS transmission burst 178 + * 179 + * Minimum value: max(8 * @hs_clk_rate period in ps, 180 + * 60000 ps + 4 * @hs_clk_rate period in ps) 181 + */ 182 + unsigned int hs_trail; 183 + 184 + /** 185 + * @hs_zero: 186 + * 187 + * Time, in picoseconds, that the transmitter drives the HS-0 188 + * state prior to transmitting the Sync sequence. 189 + */ 190 + unsigned int hs_zero; 191 + 192 + /** 193 + * @init: 194 + * 195 + * Time, in picoseconds for the initialization period to 196 + * complete. 197 + * 198 + * Minimum value: 100000000 ps 199 + */ 200 + unsigned int init; 201 + 202 + /** 203 + * @lpx: 204 + * 205 + * Transmitted length, in picoseconds, of any Low-Power state 206 + * period. 207 + * 208 + * Minimum value: 50000 ps 209 + */ 210 + unsigned int lpx; 211 + 212 + /** 213 + * @ta_get: 214 + * 215 + * Time, in picoseconds, that the new transmitter drives the 216 + * Bridge state (LP-00) after accepting control during a Link 217 + * Turnaround. 218 + * 219 + * Value: 5 * @lpx 220 + */ 221 + unsigned int ta_get; 222 + 223 + /** 224 + * @ta_go: 225 + * 226 + * Time, in picoseconds, that the transmitter drives the 227 + * Bridge state (LP-00) before releasing control during a Link 228 + * Turnaround. 229 + * 230 + * Value: 4 * @lpx 231 + */ 232 + unsigned int ta_go; 233 + 234 + /** 235 + * @ta_sure: 236 + * 237 + * Time, in picoseconds, that the new transmitter waits after 238 + * the LP-10 state before transmitting the Bridge state 239 + * (LP-00) during a Link Turnaround. 240 + * 241 + * Minimum value: @lpx 242 + * Maximum value: 2 * @lpx 243 + */ 244 + unsigned int ta_sure; 245 + 246 + /** 247 + * @wakeup: 248 + * 249 + * Time, in picoseconds, that a transmitter drives a Mark-1 250 + * state prior to a Stop state in order to initiate an exit 251 + * from ULPS. 252 + * 253 + * Minimum value: 1000000000 ps 254 + */ 255 + unsigned int wakeup; 256 + 257 + /** 258 + * @hs_clk_rate: 259 + * 260 + * Clock rate, in Hertz, of the high-speed clock. 261 + */ 262 + unsigned long hs_clk_rate; 263 + 264 + /** 265 + * @lp_clk_rate: 266 + * 267 + * Clock rate, in Hertz, of the low-power clock. 268 + */ 269 + unsigned long lp_clk_rate; 270 + 271 + /** 272 + * @lanes: 273 + * 274 + * Number of active data lanes used for the transmissions. 275 + */ 276 + unsigned char lanes; 277 + }; 278 + 279 + int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, 280 + unsigned int bpp, 281 + unsigned int lanes, 282 + struct phy_configure_opts_mipi_dphy *cfg); 283 + int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg); 284 + 285 + #endif /* __PHY_MIPI_DPHY_H_ */
+76 -7
include/linux/phy/phy.h
··· 20 20 #include <linux/pm_runtime.h> 21 21 #include <linux/regulator/consumer.h> 22 22 23 + #include <linux/phy/phy-mipi-dphy.h> 24 + 23 25 struct phy; 24 26 25 27 enum phy_mode { ··· 37 35 PHY_MODE_USB_DEVICE_HS, 38 36 PHY_MODE_USB_DEVICE_SS, 39 37 PHY_MODE_USB_OTG, 40 - PHY_MODE_SGMII, 41 - PHY_MODE_2500SGMII, 42 - PHY_MODE_QSGMII, 43 - PHY_MODE_10GKR, 44 38 PHY_MODE_UFS_HS_A, 45 39 PHY_MODE_UFS_HS_B, 46 40 PHY_MODE_PCIE, 41 + PHY_MODE_ETHERNET, 42 + PHY_MODE_MIPI_DPHY, 43 + }; 44 + 45 + /** 46 + * union phy_configure_opts - Opaque generic phy configuration 47 + * 48 + * @mipi_dphy: Configuration set applicable for phys supporting 49 + * the MIPI_DPHY phy mode. 50 + */ 51 + union phy_configure_opts { 52 + struct phy_configure_opts_mipi_dphy mipi_dphy; 47 53 }; 48 54 49 55 /** ··· 70 60 int (*exit)(struct phy *phy); 71 61 int (*power_on)(struct phy *phy); 72 62 int (*power_off)(struct phy *phy); 73 - int (*set_mode)(struct phy *phy, enum phy_mode mode); 63 + int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode); 64 + 65 + /** 66 + * @configure: 67 + * 68 + * Optional. 69 + * 70 + * Used to change the PHY parameters. phy_init() must have 71 + * been called on the phy. 72 + * 73 + * Returns: 0 if successful, an negative error code otherwise 74 + */ 75 + int (*configure)(struct phy *phy, union phy_configure_opts *opts); 76 + 77 + /** 78 + * @validate: 79 + * 80 + * Optional. 81 + * 82 + * Used to check that the current set of parameters can be 83 + * handled by the phy. Implementations are free to tune the 84 + * parameters passed as arguments if needed by some 85 + * implementation detail or constraints. It must not change 86 + * any actual configuration of the PHY, so calling it as many 87 + * times as deemed fit by the consumer must have no side 88 + * effect. 89 + * 90 + * Returns: 0 if the configuration can be applied, an negative 91 + * error code otherwise 92 + */ 93 + int (*validate)(struct phy *phy, enum phy_mode mode, int submode, 94 + union phy_configure_opts *opts); 74 95 int (*reset)(struct phy *phy); 75 96 int (*calibrate)(struct phy *phy); 76 97 struct module *owner; ··· 205 164 int phy_exit(struct phy *phy); 206 165 int phy_power_on(struct phy *phy); 207 166 int phy_power_off(struct phy *phy); 208 - int phy_set_mode(struct phy *phy, enum phy_mode mode); 167 + int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode); 168 + #define phy_set_mode(phy, mode) \ 169 + phy_set_mode_ext(phy, mode, 0) 170 + int phy_configure(struct phy *phy, union phy_configure_opts *opts); 171 + int phy_validate(struct phy *phy, enum phy_mode mode, int submode, 172 + union phy_configure_opts *opts); 173 + 209 174 static inline enum phy_mode phy_get_mode(struct phy *phy) 210 175 { 211 176 return phy->attrs.mode; ··· 325 278 return -ENOSYS; 326 279 } 327 280 328 - static inline int phy_set_mode(struct phy *phy, enum phy_mode mode) 281 + static inline int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, 282 + int submode) 329 283 { 330 284 if (!phy) 331 285 return 0; 332 286 return -ENOSYS; 333 287 } 288 + 289 + #define phy_set_mode(phy, mode) \ 290 + phy_set_mode_ext(phy, mode, 0) 334 291 335 292 static inline enum phy_mode phy_get_mode(struct phy *phy) 336 293 { ··· 352 301 { 353 302 if (!phy) 354 303 return 0; 304 + return -ENOSYS; 305 + } 306 + 307 + static inline int phy_configure(struct phy *phy, 308 + union phy_configure_opts *opts) 309 + { 310 + if (!phy) 311 + return 0; 312 + 313 + return -ENOSYS; 314 + } 315 + 316 + static inline int phy_validate(struct phy *phy, enum phy_mode mode, int submode, 317 + union phy_configure_opts *opts) 318 + { 319 + if (!phy) 320 + return 0; 321 + 355 322 return -ENOSYS; 356 323 } 357 324