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

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

phy: for 5.3

*) Add a new PHY driver for Qualcomm PCIe2 PHY
*) Add a new PHY driver for Mixel DPHY present in i.MX8
*) Fix Qualcomm QMP UFS PHY driver from incorrectly reporting that
PHY enable failed
*) Fix _BUG_ on Amlogic G12A USB3 + PCIE Combo PHY Driver due to
calling a sleeping function from invalid context
*) Fix WARN_ON dump on rcar-gen3-usb2 PHY driver caused due to
imbalance powered flag
*) Fix .cocci and sparse warnings

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

* tag 'phy-for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy:
phy: qcom-qmp: Raise qcom_qmp_phy_enable() polling delay
phy: meson-g12a-usb3-pcie: disable locking for cr_regmap
phy: Add driver for mixel mipi dphy found on NXP's i.MX8 SoCs
dt-bindings: phy: Add documentation for mixel dphy
dt-bindings: phy-pxa-usb: add bindings
phy: renesas: rcar-gen3-usb2: fix imbalance powered flag
phy: qcom-qmp: Drop useless msm8998_pciephy_cfg setting
phy: qcom-qmp: Correct READY_STATUS poll break condition
phy: ti: am654-serdes: Make serdes_am654_xlate() static
phy: usb: phy-brcm-usb: Fix platform_no_drv_owner.cocci warnings
phy: samsung: Use struct_size() in devm_kzalloc()
phy: qcom: Add Qualcomm PCIe2 PHY driver
dt-bindings: phy: Add binding for Qualcomm PCIe2 PHY

+960 -13
+29
Documentation/devicetree/bindings/phy/mixel,mipi-dsi-phy.txt
··· 1 + Mixel DSI PHY for i.MX8 2 + 3 + The Mixel MIPI-DSI PHY IP block is e.g. found on i.MX8 platforms (along the 4 + MIPI-DSI IP from Northwest Logic). It represents the physical layer for the 5 + electrical signals for DSI. 6 + 7 + Required properties: 8 + - compatible: Must be: 9 + - "fsl,imx8mq-mipi-dphy" 10 + - clocks: Must contain an entry for each entry in clock-names. 11 + - clock-names: Must contain the following entries: 12 + - "phy_ref": phandle and specifier referring to the DPHY ref clock 13 + - reg: the register range of the PHY controller 14 + - #phy-cells: number of cells in PHY, as defined in 15 + Documentation/devicetree/bindings/phy/phy-bindings.txt 16 + this must be <0> 17 + 18 + Optional properties: 19 + - power-domains: phandle to power domain 20 + 21 + Example: 22 + dphy: dphy@30a0030 { 23 + compatible = "fsl,imx8mq-mipi-dphy"; 24 + clocks = <&clk IMX8MQ_CLK_DSI_PHY_REF>; 25 + clock-names = "phy_ref"; 26 + reg = <0x30a00300 0x100>; 27 + power-domains = <&pd_mipi0>; 28 + #phy-cells = <0>; 29 + };
+18
Documentation/devicetree/bindings/phy/phy-pxa-usb.txt
··· 1 + Marvell PXA USB PHY 2 + ------------------- 3 + 4 + Required properties: 5 + - compatible: one of: "marvell,mmp2-usb-phy", "marvell,pxa910-usb-phy", 6 + "marvell,pxa168-usb-phy", 7 + - #phy-cells: must be 0 8 + 9 + Example: 10 + usb-phy: usbphy@d4207000 { 11 + compatible = "marvell,mmp2-usb-phy"; 12 + reg = <0xd4207000 0x40>; 13 + #phy-cells = <0>; 14 + status = "okay"; 15 + }; 16 + 17 + This document explains the device tree binding. For general 18 + information about PHY subsystem refer to Documentation/phy.txt
+42
Documentation/devicetree/bindings/phy/qcom-pcie2-phy.txt
··· 1 + Qualcomm PCIe2 PHY controller 2 + ============================= 3 + 4 + The Qualcomm PCIe2 PHY is a Synopsys based phy found in a number of Qualcomm 5 + platforms. 6 + 7 + Required properties: 8 + - compatible: compatible list, should be: 9 + "qcom,qcs404-pcie2-phy", "qcom,pcie2-phy" 10 + 11 + - reg: offset and length of the PHY register set. 12 + - #phy-cells: must be 0. 13 + 14 + - clocks: a clock-specifier pair for the "pipe" clock 15 + 16 + - vdda-vp-supply: phandle to low voltage regulator 17 + - vdda-vph-supply: phandle to high voltage regulator 18 + 19 + - resets: reset-specifier pairs for the "phy" and "pipe" resets 20 + - reset-names: list of resets, should contain: 21 + "phy" and "pipe" 22 + 23 + - clock-output-names: name of the outgoing clock signal from the PHY PLL 24 + - #clock-cells: must be 0 25 + 26 + Example: 27 + phy@7786000 { 28 + compatible = "qcom,qcs404-pcie2-phy", "qcom,pcie2-phy"; 29 + reg = <0x07786000 0xb8>; 30 + 31 + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; 32 + resets = <&gcc GCC_PCIEPHY_0_PHY_BCR>, 33 + <&gcc GCC_PCIE_0_PIPE_ARES>; 34 + reset-names = "phy", "pipe"; 35 + 36 + vdda-vp-supply = <&vreg_l3_1p05>; 37 + vdda-vph-supply = <&vreg_l5_1p8>; 38 + 39 + clock-output-names = "pcie_0_pipe_clk"; 40 + #clock-cells = <0>; 41 + #phy-cells = <0>; 42 + };
+1 -1
drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
··· 188 188 .reg_read = phy_g12a_usb3_pcie_cr_bus_read, 189 189 .reg_write = phy_g12a_usb3_pcie_cr_bus_write, 190 190 .max_register = 0xffff, 191 - .fast_io = true, 191 + .disable_locking = true, 192 192 }; 193 193 194 194 static int phy_g12a_usb3_init(struct phy *phy)
-1
drivers/phy/broadcom/phy-brcm-usb.c
··· 443 443 .remove = brcm_usb_phy_remove, 444 444 .driver = { 445 445 .name = "brcmstb-usb-phy", 446 - .owner = THIS_MODULE, 447 446 .pm = &brcm_usb_phy_pm_ops, 448 447 .of_match_table = brcm_usb_dt_ids, 449 448 },
+10
drivers/phy/freescale/Kconfig
··· 4 4 depends on OF && HAS_IOMEM 5 5 select GENERIC_PHY 6 6 default ARCH_MXC && ARM64 7 + 8 + config PHY_MIXEL_MIPI_DPHY 9 + tristate "Mixel MIPI DSI PHY support" 10 + depends on OF && HAS_IOMEM 11 + select GENERIC_PHY 12 + select GENERIC_PHY_MIPI_DPHY 13 + select REGMAP_MMIO 14 + help 15 + Enable this to add support for the Mixel DSI PHY as found 16 + on NXP's i.MX8 family of SOCs.
+1
drivers/phy/freescale/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o 3 + obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
+497
drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2017,2018 NXP 4 + * Copyright 2019 Purism SPC 5 + */ 6 + 7 + #include <linux/clk.h> 8 + #include <linux/clk-provider.h> 9 + #include <linux/delay.h> 10 + #include <linux/io.h> 11 + #include <linux/kernel.h> 12 + #include <linux/module.h> 13 + #include <linux/of.h> 14 + #include <linux/of_platform.h> 15 + #include <linux/phy/phy.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/regmap.h> 18 + 19 + /* DPHY registers */ 20 + #define DPHY_PD_DPHY 0x00 21 + #define DPHY_M_PRG_HS_PREPARE 0x04 22 + #define DPHY_MC_PRG_HS_PREPARE 0x08 23 + #define DPHY_M_PRG_HS_ZERO 0x0c 24 + #define DPHY_MC_PRG_HS_ZERO 0x10 25 + #define DPHY_M_PRG_HS_TRAIL 0x14 26 + #define DPHY_MC_PRG_HS_TRAIL 0x18 27 + #define DPHY_PD_PLL 0x1c 28 + #define DPHY_TST 0x20 29 + #define DPHY_CN 0x24 30 + #define DPHY_CM 0x28 31 + #define DPHY_CO 0x2c 32 + #define DPHY_LOCK 0x30 33 + #define DPHY_LOCK_BYP 0x34 34 + #define DPHY_REG_BYPASS_PLL 0x4C 35 + 36 + #define MBPS(x) ((x) * 1000000) 37 + 38 + #define DATA_RATE_MAX_SPEED MBPS(1500) 39 + #define DATA_RATE_MIN_SPEED MBPS(80) 40 + 41 + #define PLL_LOCK_SLEEP 10 42 + #define PLL_LOCK_TIMEOUT 1000 43 + 44 + #define CN_BUF 0xcb7a89c0 45 + #define CO_BUF 0x63 46 + #define CM(x) ( \ 47 + ((x) < 32) ? 0xe0 | ((x) - 16) : \ 48 + ((x) < 64) ? 0xc0 | ((x) - 32) : \ 49 + ((x) < 128) ? 0x80 | ((x) - 64) : \ 50 + ((x) - 128)) 51 + #define CN(x) (((x) == 1) ? 0x1f : (((CN_BUF) >> ((x) - 1)) & 0x1f)) 52 + #define CO(x) ((CO_BUF) >> (8 - (x)) & 0x03) 53 + 54 + /* PHY power on is active low */ 55 + #define PWR_ON 0 56 + #define PWR_OFF 1 57 + 58 + enum mixel_dphy_devtype { 59 + MIXEL_IMX8MQ, 60 + }; 61 + 62 + struct mixel_dphy_devdata { 63 + u8 reg_tx_rcal; 64 + u8 reg_auto_pd_en; 65 + u8 reg_rxlprp; 66 + u8 reg_rxcdrp; 67 + u8 reg_rxhs_settle; 68 + }; 69 + 70 + static const struct mixel_dphy_devdata mixel_dphy_devdata[] = { 71 + [MIXEL_IMX8MQ] = { 72 + .reg_tx_rcal = 0x38, 73 + .reg_auto_pd_en = 0x3c, 74 + .reg_rxlprp = 0x40, 75 + .reg_rxcdrp = 0x44, 76 + .reg_rxhs_settle = 0x48, 77 + }, 78 + }; 79 + 80 + struct mixel_dphy_cfg { 81 + /* DPHY PLL parameters */ 82 + u32 cm; 83 + u32 cn; 84 + u32 co; 85 + /* DPHY register values */ 86 + u8 mc_prg_hs_prepare; 87 + u8 m_prg_hs_prepare; 88 + u8 mc_prg_hs_zero; 89 + u8 m_prg_hs_zero; 90 + u8 mc_prg_hs_trail; 91 + u8 m_prg_hs_trail; 92 + u8 rxhs_settle; 93 + }; 94 + 95 + struct mixel_dphy_priv { 96 + struct mixel_dphy_cfg cfg; 97 + struct regmap *regmap; 98 + struct clk *phy_ref_clk; 99 + const struct mixel_dphy_devdata *devdata; 100 + }; 101 + 102 + static const struct regmap_config mixel_dphy_regmap_config = { 103 + .reg_bits = 8, 104 + .val_bits = 32, 105 + .reg_stride = 4, 106 + .max_register = DPHY_REG_BYPASS_PLL, 107 + .name = "mipi-dphy", 108 + }; 109 + 110 + static int phy_write(struct phy *phy, u32 value, unsigned int reg) 111 + { 112 + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); 113 + int ret; 114 + 115 + ret = regmap_write(priv->regmap, reg, value); 116 + if (ret < 0) 117 + dev_err(&phy->dev, "Failed to write DPHY reg %d: %d\n", reg, 118 + ret); 119 + return ret; 120 + } 121 + 122 + /* 123 + * Find a ratio close to the desired one using continued fraction 124 + * approximation ending either at exact match or maximum allowed 125 + * nominator, denominator. 126 + */ 127 + static void get_best_ratio(u32 *pnum, u32 *pdenom, u32 max_n, u32 max_d) 128 + { 129 + u32 a = *pnum; 130 + u32 b = *pdenom; 131 + u32 c; 132 + u32 n[] = {0, 1}; 133 + u32 d[] = {1, 0}; 134 + u32 whole; 135 + unsigned int i = 1; 136 + 137 + while (b) { 138 + i ^= 1; 139 + whole = a / b; 140 + n[i] += (n[i ^ 1] * whole); 141 + d[i] += (d[i ^ 1] * whole); 142 + if ((n[i] > max_n) || (d[i] > max_d)) { 143 + i ^= 1; 144 + break; 145 + } 146 + c = a - (b * whole); 147 + a = b; 148 + b = c; 149 + } 150 + *pnum = n[i]; 151 + *pdenom = d[i]; 152 + } 153 + 154 + static int mixel_dphy_config_from_opts(struct phy *phy, 155 + struct phy_configure_opts_mipi_dphy *dphy_opts, 156 + struct mixel_dphy_cfg *cfg) 157 + { 158 + struct mixel_dphy_priv *priv = dev_get_drvdata(phy->dev.parent); 159 + unsigned long ref_clk = clk_get_rate(priv->phy_ref_clk); 160 + u32 lp_t, numerator, denominator; 161 + unsigned long long tmp; 162 + u32 n; 163 + int i; 164 + 165 + if (dphy_opts->hs_clk_rate > DATA_RATE_MAX_SPEED || 166 + dphy_opts->hs_clk_rate < DATA_RATE_MIN_SPEED) 167 + return -EINVAL; 168 + 169 + numerator = dphy_opts->hs_clk_rate; 170 + denominator = ref_clk; 171 + get_best_ratio(&numerator, &denominator, 255, 256); 172 + if (!numerator || !denominator) { 173 + dev_err(&phy->dev, "Invalid %d/%d for %ld/%ld\n", 174 + numerator, denominator, 175 + dphy_opts->hs_clk_rate, ref_clk); 176 + return -EINVAL; 177 + } 178 + 179 + while ((numerator < 16) && (denominator <= 128)) { 180 + numerator <<= 1; 181 + denominator <<= 1; 182 + } 183 + /* 184 + * CM ranges between 16 and 255 185 + * CN ranges between 1 and 32 186 + * CO is power of 2: 1, 2, 4, 8 187 + */ 188 + i = __ffs(denominator); 189 + if (i > 3) 190 + i = 3; 191 + cfg->cn = denominator >> i; 192 + cfg->co = 1 << i; 193 + cfg->cm = numerator; 194 + 195 + if (cfg->cm < 16 || cfg->cm > 255 || 196 + cfg->cn < 1 || cfg->cn > 32 || 197 + cfg->co < 1 || cfg->co > 8) { 198 + dev_err(&phy->dev, "Invalid CM/CN/CO values: %u/%u/%u\n", 199 + cfg->cm, cfg->cn, cfg->co); 200 + dev_err(&phy->dev, "for hs_clk/ref_clk=%ld/%ld ~ %d/%d\n", 201 + dphy_opts->hs_clk_rate, ref_clk, 202 + numerator, denominator); 203 + return -EINVAL; 204 + } 205 + 206 + dev_dbg(&phy->dev, "hs_clk/ref_clk=%ld/%ld ~ %d/%d\n", 207 + dphy_opts->hs_clk_rate, ref_clk, numerator, denominator); 208 + 209 + /* LP clock period */ 210 + tmp = 1000000000000LL; 211 + do_div(tmp, dphy_opts->lp_clk_rate); /* ps */ 212 + if (tmp > ULONG_MAX) 213 + return -EINVAL; 214 + 215 + lp_t = tmp; 216 + dev_dbg(&phy->dev, "LP clock %lu, period: %u ps\n", 217 + dphy_opts->lp_clk_rate, lp_t); 218 + 219 + /* hs_prepare: in lp clock periods */ 220 + if (2 * dphy_opts->hs_prepare > 5 * lp_t) { 221 + dev_err(&phy->dev, 222 + "hs_prepare (%u) > 2.5 * lp clock period (%u)\n", 223 + dphy_opts->hs_prepare, lp_t); 224 + return -EINVAL; 225 + } 226 + /* 00: lp_t, 01: 1.5 * lp_t, 10: 2 * lp_t, 11: 2.5 * lp_t */ 227 + if (dphy_opts->hs_prepare < lp_t) { 228 + n = 0; 229 + } else { 230 + tmp = 2 * (dphy_opts->hs_prepare - lp_t); 231 + do_div(tmp, lp_t); 232 + n = tmp; 233 + } 234 + cfg->m_prg_hs_prepare = n; 235 + 236 + /* clk_prepare: in lp clock periods */ 237 + if (2 * dphy_opts->clk_prepare > 3 * lp_t) { 238 + dev_err(&phy->dev, 239 + "clk_prepare (%u) > 1.5 * lp clock period (%u)\n", 240 + dphy_opts->clk_prepare, lp_t); 241 + return -EINVAL; 242 + } 243 + /* 00: lp_t, 01: 1.5 * lp_t */ 244 + cfg->mc_prg_hs_prepare = dphy_opts->clk_prepare > lp_t ? 1 : 0; 245 + 246 + /* hs_zero: formula from NXP BSP */ 247 + n = (144 * (dphy_opts->hs_clk_rate / 1000000) - 47500) / 10000; 248 + cfg->m_prg_hs_zero = n < 1 ? 1 : n; 249 + 250 + /* clk_zero: formula from NXP BSP */ 251 + n = (34 * (dphy_opts->hs_clk_rate / 1000000) - 2500) / 1000; 252 + cfg->mc_prg_hs_zero = n < 1 ? 1 : n; 253 + 254 + /* clk_trail, hs_trail: formula from NXP BSP */ 255 + n = (103 * (dphy_opts->hs_clk_rate / 1000000) + 10000) / 10000; 256 + if (n > 15) 257 + n = 15; 258 + if (n < 1) 259 + n = 1; 260 + cfg->m_prg_hs_trail = n; 261 + cfg->mc_prg_hs_trail = n; 262 + 263 + /* rxhs_settle: formula from NXP BSP */ 264 + if (dphy_opts->hs_clk_rate < MBPS(80)) 265 + cfg->rxhs_settle = 0x0d; 266 + else if (dphy_opts->hs_clk_rate < MBPS(90)) 267 + cfg->rxhs_settle = 0x0c; 268 + else if (dphy_opts->hs_clk_rate < MBPS(125)) 269 + cfg->rxhs_settle = 0x0b; 270 + else if (dphy_opts->hs_clk_rate < MBPS(150)) 271 + cfg->rxhs_settle = 0x0a; 272 + else if (dphy_opts->hs_clk_rate < MBPS(225)) 273 + cfg->rxhs_settle = 0x09; 274 + else if (dphy_opts->hs_clk_rate < MBPS(500)) 275 + cfg->rxhs_settle = 0x08; 276 + else 277 + cfg->rxhs_settle = 0x07; 278 + 279 + dev_dbg(&phy->dev, "phy_config: %u %u %u %u %u %u %u\n", 280 + cfg->m_prg_hs_prepare, cfg->mc_prg_hs_prepare, 281 + cfg->m_prg_hs_zero, cfg->mc_prg_hs_zero, 282 + cfg->m_prg_hs_trail, cfg->mc_prg_hs_trail, 283 + cfg->rxhs_settle); 284 + 285 + return 0; 286 + } 287 + 288 + static void mixel_phy_set_hs_timings(struct phy *phy) 289 + { 290 + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); 291 + 292 + phy_write(phy, priv->cfg.m_prg_hs_prepare, DPHY_M_PRG_HS_PREPARE); 293 + phy_write(phy, priv->cfg.mc_prg_hs_prepare, DPHY_MC_PRG_HS_PREPARE); 294 + phy_write(phy, priv->cfg.m_prg_hs_zero, DPHY_M_PRG_HS_ZERO); 295 + phy_write(phy, priv->cfg.mc_prg_hs_zero, DPHY_MC_PRG_HS_ZERO); 296 + phy_write(phy, priv->cfg.m_prg_hs_trail, DPHY_M_PRG_HS_TRAIL); 297 + phy_write(phy, priv->cfg.mc_prg_hs_trail, DPHY_MC_PRG_HS_TRAIL); 298 + phy_write(phy, priv->cfg.rxhs_settle, priv->devdata->reg_rxhs_settle); 299 + } 300 + 301 + static int mixel_dphy_set_pll_params(struct phy *phy) 302 + { 303 + struct mixel_dphy_priv *priv = dev_get_drvdata(phy->dev.parent); 304 + 305 + if (priv->cfg.cm < 16 || priv->cfg.cm > 255 || 306 + priv->cfg.cn < 1 || priv->cfg.cn > 32 || 307 + priv->cfg.co < 1 || priv->cfg.co > 8) { 308 + dev_err(&phy->dev, "Invalid CM/CN/CO values! (%u/%u/%u)\n", 309 + priv->cfg.cm, priv->cfg.cn, priv->cfg.co); 310 + return -EINVAL; 311 + } 312 + dev_dbg(&phy->dev, "Using CM:%u CN:%u CO:%u\n", 313 + priv->cfg.cm, priv->cfg.cn, priv->cfg.co); 314 + phy_write(phy, CM(priv->cfg.cm), DPHY_CM); 315 + phy_write(phy, CN(priv->cfg.cn), DPHY_CN); 316 + phy_write(phy, CO(priv->cfg.co), DPHY_CO); 317 + return 0; 318 + } 319 + 320 + static int mixel_dphy_configure(struct phy *phy, union phy_configure_opts *opts) 321 + { 322 + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); 323 + struct mixel_dphy_cfg cfg = { 0 }; 324 + int ret; 325 + 326 + ret = mixel_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); 327 + if (ret) 328 + return ret; 329 + 330 + /* Update the configuration */ 331 + memcpy(&priv->cfg, &cfg, sizeof(struct mixel_dphy_cfg)); 332 + 333 + phy_write(phy, 0x00, DPHY_LOCK_BYP); 334 + phy_write(phy, 0x01, priv->devdata->reg_tx_rcal); 335 + phy_write(phy, 0x00, priv->devdata->reg_auto_pd_en); 336 + phy_write(phy, 0x02, priv->devdata->reg_rxlprp); 337 + phy_write(phy, 0x02, priv->devdata->reg_rxcdrp); 338 + phy_write(phy, 0x25, DPHY_TST); 339 + 340 + mixel_phy_set_hs_timings(phy); 341 + ret = mixel_dphy_set_pll_params(phy); 342 + if (ret < 0) 343 + return ret; 344 + 345 + return 0; 346 + } 347 + 348 + static int mixel_dphy_validate(struct phy *phy, enum phy_mode mode, int submode, 349 + union phy_configure_opts *opts) 350 + { 351 + struct mixel_dphy_cfg cfg = { 0 }; 352 + 353 + if (mode != PHY_MODE_MIPI_DPHY) 354 + return -EINVAL; 355 + 356 + return mixel_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); 357 + } 358 + 359 + static int mixel_dphy_init(struct phy *phy) 360 + { 361 + phy_write(phy, PWR_OFF, DPHY_PD_PLL); 362 + phy_write(phy, PWR_OFF, DPHY_PD_DPHY); 363 + 364 + return 0; 365 + } 366 + 367 + static int mixel_dphy_exit(struct phy *phy) 368 + { 369 + phy_write(phy, 0, DPHY_CM); 370 + phy_write(phy, 0, DPHY_CN); 371 + phy_write(phy, 0, DPHY_CO); 372 + 373 + return 0; 374 + } 375 + 376 + static int mixel_dphy_power_on(struct phy *phy) 377 + { 378 + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); 379 + u32 locked; 380 + int ret; 381 + 382 + ret = clk_prepare_enable(priv->phy_ref_clk); 383 + if (ret < 0) 384 + return ret; 385 + 386 + phy_write(phy, PWR_ON, DPHY_PD_PLL); 387 + ret = regmap_read_poll_timeout(priv->regmap, DPHY_LOCK, locked, 388 + locked, PLL_LOCK_SLEEP, 389 + PLL_LOCK_TIMEOUT); 390 + if (ret < 0) { 391 + dev_err(&phy->dev, "Could not get DPHY lock (%d)!\n", ret); 392 + goto clock_disable; 393 + } 394 + phy_write(phy, PWR_ON, DPHY_PD_DPHY); 395 + 396 + return 0; 397 + clock_disable: 398 + clk_disable_unprepare(priv->phy_ref_clk); 399 + return ret; 400 + } 401 + 402 + static int mixel_dphy_power_off(struct phy *phy) 403 + { 404 + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); 405 + 406 + phy_write(phy, PWR_OFF, DPHY_PD_PLL); 407 + phy_write(phy, PWR_OFF, DPHY_PD_DPHY); 408 + 409 + clk_disable_unprepare(priv->phy_ref_clk); 410 + 411 + return 0; 412 + } 413 + 414 + static const struct phy_ops mixel_dphy_phy_ops = { 415 + .init = mixel_dphy_init, 416 + .exit = mixel_dphy_exit, 417 + .power_on = mixel_dphy_power_on, 418 + .power_off = mixel_dphy_power_off, 419 + .configure = mixel_dphy_configure, 420 + .validate = mixel_dphy_validate, 421 + .owner = THIS_MODULE, 422 + }; 423 + 424 + static const struct of_device_id mixel_dphy_of_match[] = { 425 + { .compatible = "fsl,imx8mq-mipi-dphy", 426 + .data = &mixel_dphy_devdata[MIXEL_IMX8MQ] }, 427 + { /* sentinel */ }, 428 + }; 429 + MODULE_DEVICE_TABLE(of, mixel_dphy_of_match); 430 + 431 + static int mixel_dphy_probe(struct platform_device *pdev) 432 + { 433 + struct device *dev = &pdev->dev; 434 + struct device_node *np = dev->of_node; 435 + struct phy_provider *phy_provider; 436 + struct mixel_dphy_priv *priv; 437 + struct resource *res; 438 + struct phy *phy; 439 + void __iomem *base; 440 + 441 + if (!np) 442 + return -ENODEV; 443 + 444 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 445 + if (!priv) 446 + return -ENOMEM; 447 + 448 + priv->devdata = of_device_get_match_data(&pdev->dev); 449 + if (!priv->devdata) 450 + return -EINVAL; 451 + 452 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 453 + base = devm_ioremap_resource(dev, res); 454 + if (IS_ERR(base)) 455 + return PTR_ERR(base); 456 + 457 + priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, 458 + &mixel_dphy_regmap_config); 459 + if (IS_ERR(priv->regmap)) { 460 + dev_err(dev, "Couldn't create the DPHY regmap\n"); 461 + return PTR_ERR(priv->regmap); 462 + } 463 + 464 + priv->phy_ref_clk = devm_clk_get(&pdev->dev, "phy_ref"); 465 + if (IS_ERR(priv->phy_ref_clk)) { 466 + dev_err(dev, "No phy_ref clock found\n"); 467 + return PTR_ERR(priv->phy_ref_clk); 468 + } 469 + dev_dbg(dev, "phy_ref clock rate: %lu\n", 470 + clk_get_rate(priv->phy_ref_clk)); 471 + 472 + dev_set_drvdata(dev, priv); 473 + 474 + phy = devm_phy_create(dev, np, &mixel_dphy_phy_ops); 475 + if (IS_ERR(phy)) { 476 + dev_err(dev, "Failed to create phy %ld\n", PTR_ERR(phy)); 477 + return PTR_ERR(phy); 478 + } 479 + phy_set_drvdata(phy, priv); 480 + 481 + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 482 + 483 + return PTR_ERR_OR_ZERO(phy_provider); 484 + } 485 + 486 + static struct platform_driver mixel_dphy_driver = { 487 + .probe = mixel_dphy_probe, 488 + .driver = { 489 + .name = "mixel-mipi-dphy", 490 + .of_match_table = mixel_dphy_of_match, 491 + } 492 + }; 493 + module_platform_driver(mixel_dphy_driver); 494 + 495 + MODULE_AUTHOR("NXP Semiconductor"); 496 + MODULE_DESCRIPTION("Mixel MIPI-DSI PHY driver"); 497 + MODULE_LICENSE("GPL");
+8
drivers/phy/qualcomm/Kconfig
··· 25 25 depends on OF 26 26 select GENERIC_PHY 27 27 28 + config PHY_QCOM_PCIE2 29 + tristate "Qualcomm PCIe Gen2 PHY Driver" 30 + depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) 31 + select GENERIC_PHY 32 + help 33 + Enable this to support the Qualcomm PCIe PHY, used with the Synopsys 34 + based PCIe controller. 35 + 28 36 config PHY_QCOM_QMP 29 37 tristate "Qualcomm QMP PHY Driver" 30 38 depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
+1
drivers/phy/qualcomm/Makefile
··· 2 2 obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o 3 3 obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o 4 4 obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o 5 + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o 5 6 obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o 6 7 obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o 7 8 obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
+331
drivers/phy/qualcomm/phy-qcom-pcie2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2019, Linaro Ltd. 5 + */ 6 + 7 + #include <linux/clk-provider.h> 8 + #include <linux/clk.h> 9 + #include <linux/iopoll.h> 10 + #include <linux/module.h> 11 + #include <linux/phy/phy.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/reset.h> 14 + #include <linux/slab.h> 15 + 16 + #include <dt-bindings/phy/phy.h> 17 + 18 + #define PCIE20_PARF_PHY_STTS 0x3c 19 + #define PCIE2_PHY_RESET_CTRL 0x44 20 + #define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0 21 + #define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4 22 + #define PCIE20_PARF_PCS_SWING_CTRL1 0x88 23 + #define PCIE20_PARF_PCS_SWING_CTRL2 0x8c 24 + #define PCIE20_PARF_PCS_DEEMPH1 0x74 25 + #define PCIE20_PARF_PCS_DEEMPH2 0x78 26 + #define PCIE20_PARF_PCS_DEEMPH3 0x7c 27 + #define PCIE20_PARF_CONFIGBITS 0x84 28 + #define PCIE20_PARF_PHY_CTRL3 0x94 29 + #define PCIE20_PARF_PCS_CTRL 0x80 30 + 31 + #define TX_AMP_VAL 120 32 + #define PHY_RX0_EQ_GEN1_VAL 0 33 + #define PHY_RX0_EQ_GEN2_VAL 4 34 + #define TX_DEEMPH_GEN1_VAL 24 35 + #define TX_DEEMPH_GEN2_3_5DB_VAL 26 36 + #define TX_DEEMPH_GEN2_6DB_VAL 36 37 + #define PHY_TX0_TERM_OFFST_VAL 0 38 + 39 + struct qcom_phy { 40 + struct device *dev; 41 + void __iomem *base; 42 + 43 + struct regulator_bulk_data vregs[2]; 44 + 45 + struct reset_control *phy_reset; 46 + struct reset_control *pipe_reset; 47 + struct clk *pipe_clk; 48 + }; 49 + 50 + static int qcom_pcie2_phy_init(struct phy *phy) 51 + { 52 + struct qcom_phy *qphy = phy_get_drvdata(phy); 53 + int ret; 54 + 55 + ret = reset_control_deassert(qphy->phy_reset); 56 + if (ret) { 57 + dev_err(qphy->dev, "cannot deassert pipe reset\n"); 58 + return ret; 59 + } 60 + 61 + ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs); 62 + if (ret) 63 + reset_control_assert(qphy->phy_reset); 64 + 65 + return ret; 66 + } 67 + 68 + static int qcom_pcie2_phy_power_on(struct phy *phy) 69 + { 70 + struct qcom_phy *qphy = phy_get_drvdata(phy); 71 + int ret; 72 + u32 val; 73 + 74 + /* Program REF_CLK source */ 75 + val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 76 + val &= ~BIT(1); 77 + writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 78 + 79 + usleep_range(1000, 2000); 80 + 81 + /* Don't use PAD for refclock */ 82 + val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 83 + val &= ~BIT(0); 84 + writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 85 + 86 + /* Program SSP ENABLE */ 87 + val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3); 88 + val |= BIT(0); 89 + writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3); 90 + 91 + usleep_range(1000, 2000); 92 + 93 + /* Assert Phy SW Reset */ 94 + val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); 95 + val |= BIT(0); 96 + writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); 97 + 98 + /* Program Tx Amplitude */ 99 + val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL1); 100 + val &= ~0x7f; 101 + val |= TX_AMP_VAL; 102 + writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL1); 103 + 104 + val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL2); 105 + val &= ~0x7f; 106 + val |= TX_AMP_VAL; 107 + writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL2); 108 + 109 + /* Program De-Emphasis */ 110 + val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH1); 111 + val &= ~0x3f; 112 + val |= TX_DEEMPH_GEN2_6DB_VAL; 113 + writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH1); 114 + 115 + val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH2); 116 + val &= ~0x3f; 117 + val |= TX_DEEMPH_GEN2_3_5DB_VAL; 118 + writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH2); 119 + 120 + val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH3); 121 + val &= ~0x3f; 122 + val |= TX_DEEMPH_GEN1_VAL; 123 + writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH3); 124 + 125 + /* Program Rx_Eq */ 126 + val = readl(qphy->base + PCIE20_PARF_CONFIGBITS); 127 + val &= ~0x7; 128 + val |= PHY_RX0_EQ_GEN2_VAL; 129 + writel(val, qphy->base + PCIE20_PARF_CONFIGBITS); 130 + 131 + /* Program Tx0_term_offset */ 132 + val = readl(qphy->base + PCIE20_PARF_PHY_CTRL3); 133 + val &= ~0x1f; 134 + val |= PHY_TX0_TERM_OFFST_VAL; 135 + writel(val, qphy->base + PCIE20_PARF_PHY_CTRL3); 136 + 137 + /* disable Tx2Rx Loopback */ 138 + val = readl(qphy->base + PCIE20_PARF_PCS_CTRL); 139 + val &= ~BIT(1); 140 + writel(val, qphy->base + PCIE20_PARF_PCS_CTRL); 141 + 142 + /* De-assert Phy SW Reset */ 143 + val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); 144 + val &= ~BIT(0); 145 + writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); 146 + 147 + usleep_range(1000, 2000); 148 + 149 + ret = reset_control_deassert(qphy->pipe_reset); 150 + if (ret) { 151 + dev_err(qphy->dev, "cannot deassert pipe reset\n"); 152 + goto out; 153 + } 154 + 155 + clk_set_rate(qphy->pipe_clk, 250000000); 156 + 157 + ret = clk_prepare_enable(qphy->pipe_clk); 158 + if (ret) { 159 + dev_err(qphy->dev, "failed to enable pipe clock\n"); 160 + goto out; 161 + } 162 + 163 + ret = readl_poll_timeout(qphy->base + PCIE20_PARF_PHY_STTS, val, 164 + !(val & BIT(0)), 1000, 10); 165 + if (ret) 166 + dev_err(qphy->dev, "phy initialization failed\n"); 167 + 168 + out: 169 + return ret; 170 + } 171 + 172 + static int qcom_pcie2_phy_power_off(struct phy *phy) 173 + { 174 + struct qcom_phy *qphy = phy_get_drvdata(phy); 175 + u32 val; 176 + 177 + val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); 178 + val |= BIT(0); 179 + writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); 180 + 181 + clk_disable_unprepare(qphy->pipe_clk); 182 + reset_control_assert(qphy->pipe_reset); 183 + 184 + return 0; 185 + } 186 + 187 + static int qcom_pcie2_phy_exit(struct phy *phy) 188 + { 189 + struct qcom_phy *qphy = phy_get_drvdata(phy); 190 + 191 + regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); 192 + reset_control_assert(qphy->phy_reset); 193 + 194 + return 0; 195 + } 196 + 197 + static const struct phy_ops qcom_pcie2_ops = { 198 + .init = qcom_pcie2_phy_init, 199 + .power_on = qcom_pcie2_phy_power_on, 200 + .power_off = qcom_pcie2_phy_power_off, 201 + .exit = qcom_pcie2_phy_exit, 202 + .owner = THIS_MODULE, 203 + }; 204 + 205 + /* 206 + * Register a fixed rate pipe clock. 207 + * 208 + * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate 209 + * controls it. The <s>_pipe_clk coming out of the GCC is requested 210 + * by the PHY driver for its operations. 211 + * We register the <s>_pipe_clksrc here. The gcc driver takes care 212 + * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. 213 + * Below picture shows this relationship. 214 + * 215 + * +---------------+ 216 + * | PHY block |<<---------------------------------------+ 217 + * | | | 218 + * | +-------+ | +-----+ | 219 + * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ 220 + * clk | +-------+ | +-----+ 221 + * +---------------+ 222 + */ 223 + static int phy_pipe_clksrc_register(struct qcom_phy *qphy) 224 + { 225 + struct device_node *np = qphy->dev->of_node; 226 + struct clk_fixed_rate *fixed; 227 + struct clk_init_data init = { }; 228 + int ret; 229 + 230 + ret = of_property_read_string(np, "clock-output-names", &init.name); 231 + if (ret) { 232 + dev_err(qphy->dev, "%s: No clock-output-names\n", np->name); 233 + return ret; 234 + } 235 + 236 + fixed = devm_kzalloc(qphy->dev, sizeof(*fixed), GFP_KERNEL); 237 + if (!fixed) 238 + return -ENOMEM; 239 + 240 + init.ops = &clk_fixed_rate_ops; 241 + 242 + /* controllers using QMP phys use 250MHz pipe clock interface */ 243 + fixed->fixed_rate = 250000000; 244 + fixed->hw.init = &init; 245 + 246 + return devm_clk_hw_register(qphy->dev, &fixed->hw); 247 + } 248 + 249 + static int qcom_pcie2_phy_probe(struct platform_device *pdev) 250 + { 251 + struct phy_provider *phy_provider; 252 + struct qcom_phy *qphy; 253 + struct resource *res; 254 + struct device *dev = &pdev->dev; 255 + struct phy *phy; 256 + int ret; 257 + 258 + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); 259 + if (!qphy) 260 + return -ENOMEM; 261 + 262 + qphy->dev = dev; 263 + 264 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 265 + qphy->base = devm_ioremap_resource(dev, res); 266 + if (IS_ERR(qphy->base)) 267 + return PTR_ERR(qphy->base); 268 + 269 + ret = phy_pipe_clksrc_register(qphy); 270 + if (ret) { 271 + dev_err(dev, "failed to register pipe_clk\n"); 272 + return ret; 273 + } 274 + 275 + qphy->vregs[0].supply = "vdda-vp"; 276 + qphy->vregs[1].supply = "vdda-vph"; 277 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(qphy->vregs), qphy->vregs); 278 + if (ret < 0) 279 + return ret; 280 + 281 + qphy->pipe_clk = devm_clk_get(dev, NULL); 282 + if (IS_ERR(qphy->pipe_clk)) { 283 + dev_err(dev, "failed to acquire pipe clock\n"); 284 + return PTR_ERR(qphy->pipe_clk); 285 + } 286 + 287 + qphy->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); 288 + if (IS_ERR(qphy->phy_reset)) { 289 + dev_err(dev, "failed to acquire phy reset\n"); 290 + return PTR_ERR(qphy->phy_reset); 291 + } 292 + 293 + qphy->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe"); 294 + if (IS_ERR(qphy->pipe_reset)) { 295 + dev_err(dev, "failed to acquire pipe reset\n"); 296 + return PTR_ERR(qphy->pipe_reset); 297 + } 298 + 299 + phy = devm_phy_create(dev, dev->of_node, &qcom_pcie2_ops); 300 + if (IS_ERR(phy)) { 301 + dev_err(dev, "failed to create phy\n"); 302 + return PTR_ERR(phy); 303 + } 304 + 305 + phy_set_drvdata(phy, qphy); 306 + 307 + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 308 + if (IS_ERR(phy_provider)) 309 + dev_err(dev, "failed to register phy provider\n"); 310 + 311 + return PTR_ERR_OR_ZERO(phy_provider); 312 + } 313 + 314 + static const struct of_device_id qcom_pcie2_phy_match_table[] = { 315 + { .compatible = "qcom,pcie2-phy" }, 316 + {} 317 + }; 318 + MODULE_DEVICE_TABLE(of, qcom_pcie2_phy_match_table); 319 + 320 + static struct platform_driver qcom_pcie2_phy_driver = { 321 + .probe = qcom_pcie2_phy_probe, 322 + .driver = { 323 + .name = "phy-qcom-pcie2", 324 + .of_match_table = qcom_pcie2_phy_match_table, 325 + }, 326 + }; 327 + 328 + module_platform_driver(qcom_pcie2_phy_driver); 329 + 330 + MODULE_DESCRIPTION("Qualcomm PCIe PHY driver"); 331 + MODULE_LICENSE("GPL v2");
+3 -2
drivers/phy/qualcomm/phy-qcom-qmp.c
··· 1074 1074 1075 1075 .start_ctrl = PCS_START | PLL_READY_GATE_EN, 1076 1076 .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 1077 + .mask_pcs_ready = PHYSTATUS, 1077 1078 .mask_com_pcs_ready = PCS_READY, 1078 1079 1079 1080 .has_phy_com_ctrl = true, ··· 1254 1253 1255 1254 .start_ctrl = SERDES_START | PCS_START, 1256 1255 .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 1257 - .mask_com_pcs_ready = PCS_READY, 1256 + .mask_pcs_ready = PHYSTATUS, 1258 1257 }; 1259 1258 1260 1259 static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ··· 1548 1547 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; 1549 1548 mask = cfg->mask_pcs_ready; 1550 1549 1551 - ret = readl_poll_timeout(status, val, !(val & mask), 1, 1550 + ret = readl_poll_timeout(status, val, val & mask, 10, 1552 1551 PHY_INIT_COMPLETE_TIMEOUT); 1553 1552 if (ret) { 1554 1553 dev_err(qmp->dev, "phy initialization timed-out\n");
+15 -4
drivers/phy/renesas/phy-rcar-gen3-usb2.c
··· 13 13 #include <linux/interrupt.h> 14 14 #include <linux/io.h> 15 15 #include <linux/module.h> 16 + #include <linux/mutex.h> 16 17 #include <linux/of.h> 17 18 #include <linux/of_address.h> 18 19 #include <linux/of_device.h> ··· 107 106 struct rcar_gen3_phy rphys[NUM_OF_PHYS]; 108 107 struct regulator *vbus; 109 108 struct work_struct work; 109 + struct mutex lock; /* protects rphys[...].powered */ 110 110 enum usb_dr_mode dr_mode; 111 111 bool extcon_host; 112 112 bool is_otg_channel; ··· 439 437 struct rcar_gen3_chan *channel = rphy->ch; 440 438 void __iomem *usb2_base = channel->base; 441 439 u32 val; 442 - int ret; 440 + int ret = 0; 443 441 442 + mutex_lock(&channel->lock); 444 443 if (!rcar_gen3_are_all_rphys_power_off(channel)) 445 - return 0; 444 + goto out; 446 445 447 446 if (channel->vbus) { 448 447 ret = regulator_enable(channel->vbus); 449 448 if (ret) 450 - return ret; 449 + goto out; 451 450 } 452 451 453 452 val = readl(usb2_base + USB2_USBCTR); ··· 457 454 val &= ~USB2_USBCTR_PLL_RST; 458 455 writel(val, usb2_base + USB2_USBCTR); 459 456 457 + out: 458 + /* The powered flag should be set for any other phys anyway */ 460 459 rphy->powered = true; 460 + mutex_unlock(&channel->lock); 461 461 462 462 return 0; 463 463 } ··· 471 465 struct rcar_gen3_chan *channel = rphy->ch; 472 466 int ret = 0; 473 467 468 + mutex_lock(&channel->lock); 474 469 rphy->powered = false; 475 470 476 471 if (!rcar_gen3_are_all_rphys_power_off(channel)) 477 - return 0; 472 + goto out; 478 473 479 474 if (channel->vbus) 480 475 ret = regulator_disable(channel->vbus); 476 + 477 + out: 478 + mutex_unlock(&channel->lock); 481 479 482 480 return ret; 483 481 } ··· 649 639 if (!phy_usb2_ops) 650 640 return -EINVAL; 651 641 642 + mutex_init(&channel->lock); 652 643 for (i = 0; i < NUM_OF_PHYS; i++) { 653 644 channel->rphys[i].phy = devm_phy_create(dev, NULL, 654 645 phy_usb2_ops);
+2 -3
drivers/phy/samsung/phy-samsung-usb2.c
··· 156 156 if (!cfg) 157 157 return -EINVAL; 158 158 159 - drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) + 160 - cfg->num_phys * sizeof(struct samsung_usb2_phy_instance), 161 - GFP_KERNEL); 159 + drv = devm_kzalloc(dev, struct_size(drv, instances, cfg->num_phys), 160 + GFP_KERNEL); 162 161 if (!drv) 163 162 return -ENOMEM; 164 163
+2 -2
drivers/phy/ti/phy-am654-serdes.c
··· 247 247 mux_control_deselect(phy->control); 248 248 } 249 249 250 - struct phy *serdes_am654_xlate(struct device *dev, struct of_phandle_args 251 - *args) 250 + static struct phy *serdes_am654_xlate(struct device *dev, 251 + struct of_phandle_args *args) 252 252 { 253 253 struct serdes_am654 *am654_phy; 254 254 struct phy *phy;