diff options
Diffstat (limited to 'drivers/phy')
41 files changed, 926 insertions, 139 deletions
diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c index 6233a7979a93..ac322d643c7a 100644 --- a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c +++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c @@ -188,7 +188,7 @@ static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = { .reg_read = phy_g12a_usb3_pcie_cr_bus_read, .reg_write = phy_g12a_usb3_pcie_cr_bus_write, .max_register = 0xffff, - .fast_io = true, + .disable_locking = true, }; static int phy_g12a_usb3_init(struct phy *phy) diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c index 58dff80e9386..9f2f84d65dcd 100644 --- a/drivers/phy/broadcom/phy-bcm-ns-usb2.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Broadcom Northstar USB 2.0 PHY Driver * * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/bcma/bcma.h> diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c index a53ae128eadf..14f45bc35cc5 100644 --- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Broadcom Northstar USB 3.0 PHY Driver * @@ -7,10 +8,6 @@ * All magic values used for initialization (and related comments) were obtained * from Broadcom's SDK: * Copyright (c) Broadcom Corp, 2012 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/bcma/bcma.h> diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c index 7a6a6dd3fced..f5c1f2983a1d 100644 --- a/drivers/phy/broadcom/phy-brcm-usb.c +++ b/drivers/phy/broadcom/phy-brcm-usb.c @@ -368,6 +368,13 @@ static int brcm_usb_phy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } +static int brcm_usb_phy_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &brcm_usb_phy_group); + + return 0; +} + #ifdef CONFIG_PM_SLEEP static int brcm_usb_phy_suspend(struct device *dev) { @@ -433,9 +440,9 @@ MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids); static struct platform_driver brcm_usb_driver = { .probe = brcm_usb_phy_probe, + .remove = brcm_usb_phy_remove, .driver = { .name = "brcmstb-usb-phy", - .owner = THIS_MODULE, .pm = &brcm_usb_phy_pm_ops, .of_match_table = brcm_usb_dt_ids, }, diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig index f435d6406943..320630ffe3cd 100644 --- a/drivers/phy/freescale/Kconfig +++ b/drivers/phy/freescale/Kconfig @@ -4,3 +4,13 @@ config PHY_FSL_IMX8MQ_USB depends on OF && HAS_IOMEM select GENERIC_PHY default ARCH_MXC && ARM64 + +config PHY_MIXEL_MIPI_DPHY + tristate "Mixel MIPI DSI PHY support" + depends on OF && HAS_IOMEM + select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + select REGMAP_MMIO + help + Enable this to add support for the Mixel DSI PHY as found + on NXP's i.MX8 family of SOCs. diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile index a459a44f6ecd..1d02e3869b45 100644 --- a/drivers/phy/freescale/Makefile +++ b/drivers/phy/freescale/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o +obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o diff --git a/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c b/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c new file mode 100644 index 000000000000..9f2c1da14f5a --- /dev/null +++ b/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017,2018 NXP + * Copyright 2019 Purism SPC + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +/* DPHY registers */ +#define DPHY_PD_DPHY 0x00 +#define DPHY_M_PRG_HS_PREPARE 0x04 +#define DPHY_MC_PRG_HS_PREPARE 0x08 +#define DPHY_M_PRG_HS_ZERO 0x0c +#define DPHY_MC_PRG_HS_ZERO 0x10 +#define DPHY_M_PRG_HS_TRAIL 0x14 +#define DPHY_MC_PRG_HS_TRAIL 0x18 +#define DPHY_PD_PLL 0x1c +#define DPHY_TST 0x20 +#define DPHY_CN 0x24 +#define DPHY_CM 0x28 +#define DPHY_CO 0x2c +#define DPHY_LOCK 0x30 +#define DPHY_LOCK_BYP 0x34 +#define DPHY_REG_BYPASS_PLL 0x4C + +#define MBPS(x) ((x) * 1000000) + +#define DATA_RATE_MAX_SPEED MBPS(1500) +#define DATA_RATE_MIN_SPEED MBPS(80) + +#define PLL_LOCK_SLEEP 10 +#define PLL_LOCK_TIMEOUT 1000 + +#define CN_BUF 0xcb7a89c0 +#define CO_BUF 0x63 +#define CM(x) ( \ + ((x) < 32) ? 0xe0 | ((x) - 16) : \ + ((x) < 64) ? 0xc0 | ((x) - 32) : \ + ((x) < 128) ? 0x80 | ((x) - 64) : \ + ((x) - 128)) +#define CN(x) (((x) == 1) ? 0x1f : (((CN_BUF) >> ((x) - 1)) & 0x1f)) +#define CO(x) ((CO_BUF) >> (8 - (x)) & 0x03) + +/* PHY power on is active low */ +#define PWR_ON 0 +#define PWR_OFF 1 + +enum mixel_dphy_devtype { + MIXEL_IMX8MQ, +}; + +struct mixel_dphy_devdata { + u8 reg_tx_rcal; + u8 reg_auto_pd_en; + u8 reg_rxlprp; + u8 reg_rxcdrp; + u8 reg_rxhs_settle; +}; + +static const struct mixel_dphy_devdata mixel_dphy_devdata[] = { + [MIXEL_IMX8MQ] = { + .reg_tx_rcal = 0x38, + .reg_auto_pd_en = 0x3c, + .reg_rxlprp = 0x40, + .reg_rxcdrp = 0x44, + .reg_rxhs_settle = 0x48, + }, +}; + +struct mixel_dphy_cfg { + /* DPHY PLL parameters */ + u32 cm; + u32 cn; + u32 co; + /* DPHY register values */ + u8 mc_prg_hs_prepare; + u8 m_prg_hs_prepare; + u8 mc_prg_hs_zero; + u8 m_prg_hs_zero; + u8 mc_prg_hs_trail; + u8 m_prg_hs_trail; + u8 rxhs_settle; +}; + +struct mixel_dphy_priv { + struct mixel_dphy_cfg cfg; + struct regmap *regmap; + struct clk *phy_ref_clk; + const struct mixel_dphy_devdata *devdata; +}; + +static const struct regmap_config mixel_dphy_regmap_config = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = DPHY_REG_BYPASS_PLL, + .name = "mipi-dphy", +}; + +static int phy_write(struct phy *phy, u32 value, unsigned int reg) +{ + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = regmap_write(priv->regmap, reg, value); + if (ret < 0) + dev_err(&phy->dev, "Failed to write DPHY reg %d: %d\n", reg, + ret); + return ret; +} + +/* + * Find a ratio close to the desired one using continued fraction + * approximation ending either at exact match or maximum allowed + * nominator, denominator. + */ +static void get_best_ratio(u32 *pnum, u32 *pdenom, u32 max_n, u32 max_d) +{ + u32 a = *pnum; + u32 b = *pdenom; + u32 c; + u32 n[] = {0, 1}; + u32 d[] = {1, 0}; + u32 whole; + unsigned int i = 1; + + while (b) { + i ^= 1; + whole = a / b; + n[i] += (n[i ^ 1] * whole); + d[i] += (d[i ^ 1] * whole); + if ((n[i] > max_n) || (d[i] > max_d)) { + i ^= 1; + break; + } + c = a - (b * whole); + a = b; + b = c; + } + *pnum = n[i]; + *pdenom = d[i]; +} + +static int mixel_dphy_config_from_opts(struct phy *phy, + struct phy_configure_opts_mipi_dphy *dphy_opts, + struct mixel_dphy_cfg *cfg) +{ + struct mixel_dphy_priv *priv = dev_get_drvdata(phy->dev.parent); + unsigned long ref_clk = clk_get_rate(priv->phy_ref_clk); + u32 lp_t, numerator, denominator; + unsigned long long tmp; + u32 n; + int i; + + if (dphy_opts->hs_clk_rate > DATA_RATE_MAX_SPEED || + dphy_opts->hs_clk_rate < DATA_RATE_MIN_SPEED) + return -EINVAL; + + numerator = dphy_opts->hs_clk_rate; + denominator = ref_clk; + get_best_ratio(&numerator, &denominator, 255, 256); + if (!numerator || !denominator) { + dev_err(&phy->dev, "Invalid %d/%d for %ld/%ld\n", + numerator, denominator, + dphy_opts->hs_clk_rate, ref_clk); + return -EINVAL; + } + + while ((numerator < 16) && (denominator <= 128)) { + numerator <<= 1; + denominator <<= 1; + } + /* + * CM ranges between 16 and 255 + * CN ranges between 1 and 32 + * CO is power of 2: 1, 2, 4, 8 + */ + i = __ffs(denominator); + if (i > 3) + i = 3; + cfg->cn = denominator >> i; + cfg->co = 1 << i; + cfg->cm = numerator; + + if (cfg->cm < 16 || cfg->cm > 255 || + cfg->cn < 1 || cfg->cn > 32 || + cfg->co < 1 || cfg->co > 8) { + dev_err(&phy->dev, "Invalid CM/CN/CO values: %u/%u/%u\n", + cfg->cm, cfg->cn, cfg->co); + dev_err(&phy->dev, "for hs_clk/ref_clk=%ld/%ld ~ %d/%d\n", + dphy_opts->hs_clk_rate, ref_clk, + numerator, denominator); + return -EINVAL; + } + + dev_dbg(&phy->dev, "hs_clk/ref_clk=%ld/%ld ~ %d/%d\n", + dphy_opts->hs_clk_rate, ref_clk, numerator, denominator); + + /* LP clock period */ + tmp = 1000000000000LL; + do_div(tmp, dphy_opts->lp_clk_rate); /* ps */ + if (tmp > ULONG_MAX) + return -EINVAL; + + lp_t = tmp; + dev_dbg(&phy->dev, "LP clock %lu, period: %u ps\n", + dphy_opts->lp_clk_rate, lp_t); + + /* hs_prepare: in lp clock periods */ + if (2 * dphy_opts->hs_prepare > 5 * lp_t) { + dev_err(&phy->dev, + "hs_prepare (%u) > 2.5 * lp clock period (%u)\n", + dphy_opts->hs_prepare, lp_t); + return -EINVAL; + } + /* 00: lp_t, 01: 1.5 * lp_t, 10: 2 * lp_t, 11: 2.5 * lp_t */ + if (dphy_opts->hs_prepare < lp_t) { + n = 0; + } else { + tmp = 2 * (dphy_opts->hs_prepare - lp_t); + do_div(tmp, lp_t); + n = tmp; + } + cfg->m_prg_hs_prepare = n; + + /* clk_prepare: in lp clock periods */ + if (2 * dphy_opts->clk_prepare > 3 * lp_t) { + dev_err(&phy->dev, + "clk_prepare (%u) > 1.5 * lp clock period (%u)\n", + dphy_opts->clk_prepare, lp_t); + return -EINVAL; + } + /* 00: lp_t, 01: 1.5 * lp_t */ + cfg->mc_prg_hs_prepare = dphy_opts->clk_prepare > lp_t ? 1 : 0; + + /* hs_zero: formula from NXP BSP */ + n = (144 * (dphy_opts->hs_clk_rate / 1000000) - 47500) / 10000; + cfg->m_prg_hs_zero = n < 1 ? 1 : n; + + /* clk_zero: formula from NXP BSP */ + n = (34 * (dphy_opts->hs_clk_rate / 1000000) - 2500) / 1000; + cfg->mc_prg_hs_zero = n < 1 ? 1 : n; + + /* clk_trail, hs_trail: formula from NXP BSP */ + n = (103 * (dphy_opts->hs_clk_rate / 1000000) + 10000) / 10000; + if (n > 15) + n = 15; + if (n < 1) + n = 1; + cfg->m_prg_hs_trail = n; + cfg->mc_prg_hs_trail = n; + + /* rxhs_settle: formula from NXP BSP */ + if (dphy_opts->hs_clk_rate < MBPS(80)) + cfg->rxhs_settle = 0x0d; + else if (dphy_opts->hs_clk_rate < MBPS(90)) + cfg->rxhs_settle = 0x0c; + else if (dphy_opts->hs_clk_rate < MBPS(125)) + cfg->rxhs_settle = 0x0b; + else if (dphy_opts->hs_clk_rate < MBPS(150)) + cfg->rxhs_settle = 0x0a; + else if (dphy_opts->hs_clk_rate < MBPS(225)) + cfg->rxhs_settle = 0x09; + else if (dphy_opts->hs_clk_rate < MBPS(500)) + cfg->rxhs_settle = 0x08; + else + cfg->rxhs_settle = 0x07; + + dev_dbg(&phy->dev, "phy_config: %u %u %u %u %u %u %u\n", + cfg->m_prg_hs_prepare, cfg->mc_prg_hs_prepare, + cfg->m_prg_hs_zero, cfg->mc_prg_hs_zero, + cfg->m_prg_hs_trail, cfg->mc_prg_hs_trail, + cfg->rxhs_settle); + + return 0; +} + +static void mixel_phy_set_hs_timings(struct phy *phy) +{ + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); + + phy_write(phy, priv->cfg.m_prg_hs_prepare, DPHY_M_PRG_HS_PREPARE); + phy_write(phy, priv->cfg.mc_prg_hs_prepare, DPHY_MC_PRG_HS_PREPARE); + phy_write(phy, priv->cfg.m_prg_hs_zero, DPHY_M_PRG_HS_ZERO); + phy_write(phy, priv->cfg.mc_prg_hs_zero, DPHY_MC_PRG_HS_ZERO); + phy_write(phy, priv->cfg.m_prg_hs_trail, DPHY_M_PRG_HS_TRAIL); + phy_write(phy, priv->cfg.mc_prg_hs_trail, DPHY_MC_PRG_HS_TRAIL); + phy_write(phy, priv->cfg.rxhs_settle, priv->devdata->reg_rxhs_settle); +} + +static int mixel_dphy_set_pll_params(struct phy *phy) +{ + struct mixel_dphy_priv *priv = dev_get_drvdata(phy->dev.parent); + + if (priv->cfg.cm < 16 || priv->cfg.cm > 255 || + priv->cfg.cn < 1 || priv->cfg.cn > 32 || + priv->cfg.co < 1 || priv->cfg.co > 8) { + dev_err(&phy->dev, "Invalid CM/CN/CO values! (%u/%u/%u)\n", + priv->cfg.cm, priv->cfg.cn, priv->cfg.co); + return -EINVAL; + } + dev_dbg(&phy->dev, "Using CM:%u CN:%u CO:%u\n", + priv->cfg.cm, priv->cfg.cn, priv->cfg.co); + phy_write(phy, CM(priv->cfg.cm), DPHY_CM); + phy_write(phy, CN(priv->cfg.cn), DPHY_CN); + phy_write(phy, CO(priv->cfg.co), DPHY_CO); + return 0; +} + +static int mixel_dphy_configure(struct phy *phy, union phy_configure_opts *opts) +{ + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); + struct mixel_dphy_cfg cfg = { 0 }; + int ret; + + ret = mixel_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); + if (ret) + return ret; + + /* Update the configuration */ + memcpy(&priv->cfg, &cfg, sizeof(struct mixel_dphy_cfg)); + + phy_write(phy, 0x00, DPHY_LOCK_BYP); + phy_write(phy, 0x01, priv->devdata->reg_tx_rcal); + phy_write(phy, 0x00, priv->devdata->reg_auto_pd_en); + phy_write(phy, 0x02, priv->devdata->reg_rxlprp); + phy_write(phy, 0x02, priv->devdata->reg_rxcdrp); + phy_write(phy, 0x25, DPHY_TST); + + mixel_phy_set_hs_timings(phy); + ret = mixel_dphy_set_pll_params(phy); + if (ret < 0) + return ret; + + return 0; +} + +static int mixel_dphy_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts) +{ + struct mixel_dphy_cfg cfg = { 0 }; + + if (mode != PHY_MODE_MIPI_DPHY) + return -EINVAL; + + return mixel_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); +} + +static int mixel_dphy_init(struct phy *phy) +{ + phy_write(phy, PWR_OFF, DPHY_PD_PLL); + phy_write(phy, PWR_OFF, DPHY_PD_DPHY); + + return 0; +} + +static int mixel_dphy_exit(struct phy *phy) +{ + phy_write(phy, 0, DPHY_CM); + phy_write(phy, 0, DPHY_CN); + phy_write(phy, 0, DPHY_CO); + + return 0; +} + +static int mixel_dphy_power_on(struct phy *phy) +{ + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); + u32 locked; + int ret; + + ret = clk_prepare_enable(priv->phy_ref_clk); + if (ret < 0) + return ret; + + phy_write(phy, PWR_ON, DPHY_PD_PLL); + ret = regmap_read_poll_timeout(priv->regmap, DPHY_LOCK, locked, + locked, PLL_LOCK_SLEEP, + PLL_LOCK_TIMEOUT); + if (ret < 0) { + dev_err(&phy->dev, "Could not get DPHY lock (%d)!\n", ret); + goto clock_disable; + } + phy_write(phy, PWR_ON, DPHY_PD_DPHY); + + return 0; +clock_disable: + clk_disable_unprepare(priv->phy_ref_clk); + return ret; +} + +static int mixel_dphy_power_off(struct phy *phy) +{ + struct mixel_dphy_priv *priv = phy_get_drvdata(phy); + + phy_write(phy, PWR_OFF, DPHY_PD_PLL); + phy_write(phy, PWR_OFF, DPHY_PD_DPHY); + + clk_disable_unprepare(priv->phy_ref_clk); + + return 0; +} + +static const struct phy_ops mixel_dphy_phy_ops = { + .init = mixel_dphy_init, + .exit = mixel_dphy_exit, + .power_on = mixel_dphy_power_on, + .power_off = mixel_dphy_power_off, + .configure = mixel_dphy_configure, + .validate = mixel_dphy_validate, + .owner = THIS_MODULE, +}; + +static const struct of_device_id mixel_dphy_of_match[] = { + { .compatible = "fsl,imx8mq-mipi-dphy", + .data = &mixel_dphy_devdata[MIXEL_IMX8MQ] }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mixel_dphy_of_match); + +static int mixel_dphy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct phy_provider *phy_provider; + struct mixel_dphy_priv *priv; + struct resource *res; + struct phy *phy; + void __iomem *base; + + if (!np) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->devdata = of_device_get_match_data(&pdev->dev); + if (!priv->devdata) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &mixel_dphy_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(dev, "Couldn't create the DPHY regmap\n"); + return PTR_ERR(priv->regmap); + } + + priv->phy_ref_clk = devm_clk_get(&pdev->dev, "phy_ref"); + if (IS_ERR(priv->phy_ref_clk)) { + dev_err(dev, "No phy_ref clock found\n"); + return PTR_ERR(priv->phy_ref_clk); + } + dev_dbg(dev, "phy_ref clock rate: %lu\n", + clk_get_rate(priv->phy_ref_clk)); + + dev_set_drvdata(dev, priv); + + phy = devm_phy_create(dev, np, &mixel_dphy_phy_ops); + if (IS_ERR(phy)) { + dev_err(dev, "Failed to create phy %ld\n", PTR_ERR(phy)); + return PTR_ERR(phy); + } + phy_set_drvdata(phy, priv); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static struct platform_driver mixel_dphy_driver = { + .probe = mixel_dphy_probe, + .driver = { + .name = "mixel-mipi-dphy", + .of_match_table = mixel_dphy_of_match, + } +}; +module_platform_driver(mixel_dphy_driver); + +MODULE_AUTHOR("NXP Semiconductor"); +MODULE_DESCRIPTION("Mixel MIPI-DSI PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/hisilicon/phy-histb-combphy.c b/drivers/phy/hisilicon/phy-histb-combphy.c index 5777b3120017..62d10ef20296 100644 --- a/drivers/phy/hisilicon/phy-histb-combphy.c +++ b/drivers/phy/hisilicon/phy-histb-combphy.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * COMBPHY driver for HiSilicon STB SoCs * * Copyright (C) 2016-2017 HiSilicon Co., Ltd. http://www.hisilicon.com * * Authors: Jianguo Sun <sunjianguo1@huawei.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/clk.h> diff --git a/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c b/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c index f9e0dd19ff26..be09b1530ae6 100644 --- a/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c +++ b/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Lantiq XWAY SoC RCU module based USB 1.1/2.0 PHY driver * * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com> * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/clk.h> diff --git a/drivers/phy/phy-lpc18xx-usb-otg.c b/drivers/phy/phy-lpc18xx-usb-otg.c index 7de280a45421..f905d3c64584 100644 --- a/drivers/phy/phy-lpc18xx-usb-otg.c +++ b/drivers/phy/phy-lpc18xx-usb-otg.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * PHY driver for NXP LPC18xx/43xx internal USB OTG PHY * * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/clk.h> diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index eb49864a6bad..e46824da29f6 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -25,6 +25,14 @@ config PHY_QCOM_IPQ806X_SATA depends on OF select GENERIC_PHY +config PHY_QCOM_PCIE2 + tristate "Qualcomm PCIe Gen2 PHY Driver" + depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) + select GENERIC_PHY + help + Enable this to support the Qualcomm PCIe PHY, used with the Synopsys + based PCIe controller. + config PHY_QCOM_QMP tristate "Qualcomm QMP PHY Driver" depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index c56efd3af205..283251d6a5d9 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o +obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o diff --git a/drivers/phy/qualcomm/phy-qcom-pcie2.c b/drivers/phy/qualcomm/phy-qcom-pcie2.c new file mode 100644 index 000000000000..9dba3594e6d9 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-pcie2.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Linaro Ltd. + */ + +#include <linux/clk-provider.h> +#include <linux/clk.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/reset.h> +#include <linux/slab.h> + +#include <dt-bindings/phy/phy.h> + +#define PCIE20_PARF_PHY_STTS 0x3c +#define PCIE2_PHY_RESET_CTRL 0x44 +#define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0 +#define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4 +#define PCIE20_PARF_PCS_SWING_CTRL1 0x88 +#define PCIE20_PARF_PCS_SWING_CTRL2 0x8c +#define PCIE20_PARF_PCS_DEEMPH1 0x74 +#define PCIE20_PARF_PCS_DEEMPH2 0x78 +#define PCIE20_PARF_PCS_DEEMPH3 0x7c +#define PCIE20_PARF_CONFIGBITS 0x84 +#define PCIE20_PARF_PHY_CTRL3 0x94 +#define PCIE20_PARF_PCS_CTRL 0x80 + +#define TX_AMP_VAL 120 +#define PHY_RX0_EQ_GEN1_VAL 0 +#define PHY_RX0_EQ_GEN2_VAL 4 +#define TX_DEEMPH_GEN1_VAL 24 +#define TX_DEEMPH_GEN2_3_5DB_VAL 26 +#define TX_DEEMPH_GEN2_6DB_VAL 36 +#define PHY_TX0_TERM_OFFST_VAL 0 + +struct qcom_phy { + struct device *dev; + void __iomem *base; + + struct regulator_bulk_data vregs[2]; + + struct reset_control *phy_reset; + struct reset_control *pipe_reset; + struct clk *pipe_clk; +}; + +static int qcom_pcie2_phy_init(struct phy *phy) +{ + struct qcom_phy *qphy = phy_get_drvdata(phy); + int ret; + + ret = reset_control_deassert(qphy->phy_reset); + if (ret) { + dev_err(qphy->dev, "cannot deassert pipe reset\n"); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs); + if (ret) + reset_control_assert(qphy->phy_reset); + + return ret; +} + +static int qcom_pcie2_phy_power_on(struct phy *phy) +{ + struct qcom_phy *qphy = phy_get_drvdata(phy); + int ret; + u32 val; + + /* Program REF_CLK source */ + val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); + val &= ~BIT(1); + writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); + + usleep_range(1000, 2000); + + /* Don't use PAD for refclock */ + val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); + val &= ~BIT(0); + writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); + + /* Program SSP ENABLE */ + val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3); + val |= BIT(0); + writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3); + + usleep_range(1000, 2000); + + /* Assert Phy SW Reset */ + val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); + val |= BIT(0); + writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); + + /* Program Tx Amplitude */ + val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL1); + val &= ~0x7f; + val |= TX_AMP_VAL; + writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL1); + + val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL2); + val &= ~0x7f; + val |= TX_AMP_VAL; + writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL2); + + /* Program De-Emphasis */ + val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH1); + val &= ~0x3f; + val |= TX_DEEMPH_GEN2_6DB_VAL; + writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH1); + + val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH2); + val &= ~0x3f; + val |= TX_DEEMPH_GEN2_3_5DB_VAL; + writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH2); + + val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH3); + val &= ~0x3f; + val |= TX_DEEMPH_GEN1_VAL; + writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH3); + + /* Program Rx_Eq */ + val = readl(qphy->base + PCIE20_PARF_CONFIGBITS); + val &= ~0x7; + val |= PHY_RX0_EQ_GEN2_VAL; + writel(val, qphy->base + PCIE20_PARF_CONFIGBITS); + + /* Program Tx0_term_offset */ + val = readl(qphy->base + PCIE20_PARF_PHY_CTRL3); + val &= ~0x1f; + val |= PHY_TX0_TERM_OFFST_VAL; + writel(val, qphy->base + PCIE20_PARF_PHY_CTRL3); + + /* disable Tx2Rx Loopback */ + val = readl(qphy->base + PCIE20_PARF_PCS_CTRL); + val &= ~BIT(1); + writel(val, qphy->base + PCIE20_PARF_PCS_CTRL); + + /* De-assert Phy SW Reset */ + val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); + val &= ~BIT(0); + writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); + + usleep_range(1000, 2000); + + ret = reset_control_deassert(qphy->pipe_reset); + if (ret) { + dev_err(qphy->dev, "cannot deassert pipe reset\n"); + goto out; + } + + clk_set_rate(qphy->pipe_clk, 250000000); + + ret = clk_prepare_enable(qphy->pipe_clk); + if (ret) { + dev_err(qphy->dev, "failed to enable pipe clock\n"); + goto out; + } + + ret = readl_poll_timeout(qphy->base + PCIE20_PARF_PHY_STTS, val, + !(val & BIT(0)), 1000, 10); + if (ret) + dev_err(qphy->dev, "phy initialization failed\n"); + +out: + return ret; +} + +static int qcom_pcie2_phy_power_off(struct phy *phy) +{ + struct qcom_phy *qphy = phy_get_drvdata(phy); + u32 val; + + val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); + val |= BIT(0); + writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); + + clk_disable_unprepare(qphy->pipe_clk); + reset_control_assert(qphy->pipe_reset); + + return 0; +} + +static int qcom_pcie2_phy_exit(struct phy *phy) +{ + struct qcom_phy *qphy = phy_get_drvdata(phy); + + regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); + reset_control_assert(qphy->phy_reset); + + return 0; +} + +static const struct phy_ops qcom_pcie2_ops = { + .init = qcom_pcie2_phy_init, + .power_on = qcom_pcie2_phy_power_on, + .power_off = qcom_pcie2_phy_power_off, + .exit = qcom_pcie2_phy_exit, + .owner = THIS_MODULE, +}; + +/* + * Register a fixed rate pipe clock. + * + * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate + * controls it. The <s>_pipe_clk coming out of the GCC is requested + * by the PHY driver for its operations. + * We register the <s>_pipe_clksrc here. The gcc driver takes care + * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. + * Below picture shows this relationship. + * + * +---------------+ + * | PHY block |<<---------------------------------------+ + * | | | + * | +-------+ | +-----+ | + * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ + * clk | +-------+ | +-----+ + * +---------------+ + */ +static int phy_pipe_clksrc_register(struct qcom_phy *qphy) +{ + struct device_node *np = qphy->dev->of_node; + struct clk_fixed_rate *fixed; + struct clk_init_data init = { }; + int ret; + + ret = of_property_read_string(np, "clock-output-names", &init.name); + if (ret) { + dev_err(qphy->dev, "%s: No clock-output-names\n", np->name); + return ret; + } + + fixed = devm_kzalloc(qphy->dev, sizeof(*fixed), GFP_KERNEL); + if (!fixed) + return -ENOMEM; + + init.ops = &clk_fixed_rate_ops; + + /* controllers using QMP phys use 250MHz pipe clock interface */ + fixed->fixed_rate = 250000000; + fixed->hw.init = &init; + + return devm_clk_hw_register(qphy->dev, &fixed->hw); +} + +static int qcom_pcie2_phy_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct qcom_phy *qphy; + struct resource *res; + struct device *dev = &pdev->dev; + struct phy *phy; + int ret; + + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); + if (!qphy) + return -ENOMEM; + + qphy->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + qphy->base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->base)) + return PTR_ERR(qphy->base); + + ret = phy_pipe_clksrc_register(qphy); + if (ret) { + dev_err(dev, "failed to register pipe_clk\n"); + return ret; + } + + qphy->vregs[0].supply = "vdda-vp"; + qphy->vregs[1].supply = "vdda-vph"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(qphy->vregs), qphy->vregs); + if (ret < 0) + return ret; + + qphy->pipe_clk = devm_clk_get(dev, NULL); + if (IS_ERR(qphy->pipe_clk)) { + dev_err(dev, "failed to acquire pipe clock\n"); + return PTR_ERR(qphy->pipe_clk); + } + + qphy->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); + if (IS_ERR(qphy->phy_reset)) { + dev_err(dev, "failed to acquire phy reset\n"); + return PTR_ERR(qphy->phy_reset); + } + + qphy->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe"); + if (IS_ERR(qphy->pipe_reset)) { + dev_err(dev, "failed to acquire pipe reset\n"); + return PTR_ERR(qphy->pipe_reset); + } + + phy = devm_phy_create(dev, dev->of_node, &qcom_pcie2_ops); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create phy\n"); + return PTR_ERR(phy); + } + + phy_set_drvdata(phy, qphy); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + dev_err(dev, "failed to register phy provider\n"); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id qcom_pcie2_phy_match_table[] = { + { .compatible = "qcom,pcie2-phy" }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_pcie2_phy_match_table); + +static struct platform_driver qcom_pcie2_phy_driver = { + .probe = qcom_pcie2_phy_probe, + .driver = { + .name = "phy-qcom-pcie2", + .of_match_table = qcom_pcie2_phy_match_table, + }, +}; + +module_platform_driver(qcom_pcie2_phy_driver); + +MODULE_DESCRIPTION("Qualcomm PCIe PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index cd91b4179b10..34ff6434da8f 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -1074,6 +1074,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = { .start_ctrl = PCS_START | PLL_READY_GATE_EN, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .mask_pcs_ready = PHYSTATUS, .mask_com_pcs_ready = PCS_READY, .has_phy_com_ctrl = true, @@ -1253,7 +1254,7 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, - .mask_com_pcs_ready = PCS_READY, + .mask_pcs_ready = PHYSTATUS, }; static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { @@ -1547,7 +1548,7 @@ static int qcom_qmp_phy_enable(struct phy *phy) status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; mask = cfg->mask_pcs_ready; - ret = readl_poll_timeout(status, val, !(val & mask), 1, + ret = readl_poll_timeout(status, val, val & mask, 10, PHY_INIT_COMPLETE_TIMEOUT); if (ret) { dev_err(qmp->dev, "phy initialization timed-out\n"); diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 1cbf1d6f28ce..bf94a52d3087 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -564,7 +564,7 @@ static int __maybe_unused qusb2_phy_runtime_resume(struct device *dev) } if (!qphy->has_se_clk_scheme) { - clk_prepare_enable(qphy->ref_clk); + ret = clk_prepare_enable(qphy->ref_clk); if (ret) { dev_err(dev, "failed to enable ref clk, %d\n", ret); goto disable_ahb_clk; diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index 04934f8dac91..b163b3a1558d 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -1,9 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /** * Copyright (C) 2016 Linaro Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/ulpi/driver.h> diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c index c110563a73cb..04d18d52f700 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c @@ -1,9 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /** * Copyright (C) 2016 Linaro Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/ulpi/driver.h> diff --git a/drivers/phy/renesas/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c index 8dc5710d9c98..2926e4937301 100644 --- a/drivers/phy/renesas/phy-rcar-gen2.c +++ b/drivers/phy/renesas/phy-rcar-gen2.c @@ -391,6 +391,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) error = of_property_read_u32(np, "reg", &channel_num); if (error || channel_num > 2) { dev_err(dev, "Invalid \"reg\" property\n"); + of_node_put(np); return error; } channel->select_mask = select_mask[channel_num]; @@ -406,6 +407,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) data->gen2_phy_ops); if (IS_ERR(phy->phy)) { dev_err(dev, "Failed to create PHY\n"); + of_node_put(np); return PTR_ERR(phy->phy); } phy_set_drvdata(phy->phy, phy); diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 1322185a00a2..8ffba67568ec 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -13,6 +13,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> @@ -106,6 +107,7 @@ struct rcar_gen3_chan { struct rcar_gen3_phy rphys[NUM_OF_PHYS]; struct regulator *vbus; struct work_struct work; + struct mutex lock; /* protects rphys[...].powered */ enum usb_dr_mode dr_mode; bool extcon_host; bool is_otg_channel; @@ -437,15 +439,16 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) struct rcar_gen3_chan *channel = rphy->ch; void __iomem *usb2_base = channel->base; u32 val; - int ret; + int ret = 0; + mutex_lock(&channel->lock); if (!rcar_gen3_are_all_rphys_power_off(channel)) - return 0; + goto out; if (channel->vbus) { ret = regulator_enable(channel->vbus); if (ret) - return ret; + goto out; } val = readl(usb2_base + USB2_USBCTR); @@ -454,7 +457,10 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) val &= ~USB2_USBCTR_PLL_RST; writel(val, usb2_base + USB2_USBCTR); +out: + /* The powered flag should be set for any other phys anyway */ rphy->powered = true; + mutex_unlock(&channel->lock); return 0; } @@ -465,14 +471,18 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) struct rcar_gen3_chan *channel = rphy->ch; int ret = 0; + mutex_lock(&channel->lock); rphy->powered = false; if (!rcar_gen3_are_all_rphys_power_off(channel)) - return 0; + goto out; if (channel->vbus) ret = regulator_disable(channel->vbus); +out: + mutex_unlock(&channel->lock); + return ret; } @@ -639,6 +649,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) if (!phy_usb2_ops) return -EINVAL; + mutex_init(&channel->lock); for (i = 0; i < NUM_OF_PHYS; i++) { channel->rphys[i].phy = devm_phy_create(dev, NULL, phy_usb2_ops); diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c index b804c6bf4b55..2dc19ddd120f 100644 --- a/drivers/phy/rockchip/phy-rockchip-emmc.c +++ b/drivers/phy/rockchip/phy-rockchip-emmc.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Rockchip emmc PHY driver * * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com> * Copyright (C) 2016 ROCKCHIP, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/clk.h> diff --git a/drivers/phy/rockchip/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c index 7cbdde029c0a..75216091d901 100644 --- a/drivers/phy/rockchip/phy-rockchip-pcie.c +++ b/drivers/phy/rockchip/phy-rockchip-pcie.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Rockchip PCIe PHY driver * * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com> * Copyright (C) 2016 ROCKCHIP, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/clk.h> diff --git a/drivers/phy/rockchip/phy-rockchip-usb.c b/drivers/phy/rockchip/phy-rockchip-usb.c index b2899c744ad9..8454285977eb 100644 --- a/drivers/phy/rockchip/phy-rockchip-usb.c +++ b/drivers/phy/rockchip/phy-rockchip-usb.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Rockchip usb PHY driver * * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com> * Copyright (C) 2014 ROCKCHIP, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/clk.h> diff --git a/drivers/phy/samsung/phy-exynos-dp-video.c b/drivers/phy/samsung/phy-exynos-dp-video.c index 2dd6dd1f37a8..aebd216dcf2f 100644 --- a/drivers/phy/samsung/phy-exynos-dp-video.c +++ b/drivers/phy/samsung/phy-exynos-dp-video.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung EXYNOS SoC series Display Port PHY driver * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Author: Jingoo Han <jg1.han@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/err.h> diff --git a/drivers/phy/samsung/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c index 00d89599c67d..3784bf100b95 100644 --- a/drivers/phy/samsung/phy-exynos-mipi-video.c +++ b/drivers/phy/samsung/phy-exynos-mipi-video.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver * * Copyright (C) 2013,2016 Samsung Electronics Co., Ltd. * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/err.h> diff --git a/drivers/phy/samsung/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c index a89c12faff39..1b4ba8bdb43c 100644 --- a/drivers/phy/samsung/phy-exynos-pcie.c +++ b/drivers/phy/samsung/phy-exynos-pcie.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung EXYNOS SoC series PCIe PHY driver * @@ -5,10 +6,6 @@ * * Copyright (C) 2017 Samsung Electronics Co., Ltd. * Jaehoon Chung <jh80.chung@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/delay.h> diff --git a/drivers/phy/samsung/phy-exynos4210-usb2.c b/drivers/phy/samsung/phy-exynos4210-usb2.c index 1f50e1004828..3898a7f58217 100644 --- a/drivers/phy/samsung/phy-exynos4210-usb2.c +++ b/drivers/phy/samsung/phy-exynos4210-usb2.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4210 support * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Author: Kamil Debski <k.debski@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/delay.h> diff --git a/drivers/phy/samsung/phy-exynos4x12-usb2.c b/drivers/phy/samsung/phy-exynos4x12-usb2.c index 7f27a91acf87..b528a5d037fe 100644 --- a/drivers/phy/samsung/phy-exynos4x12-usb2.c +++ b/drivers/phy/samsung/phy-exynos4x12-usb2.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Author: Kamil Debski <k.debski@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/delay.h> diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index b8b226a20014..646259bee909 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung EXYNOS5 SoC series USB DRD PHY driver * @@ -5,10 +6,6 @@ * * Copyright (C) 2014 Samsung Electronics Co., Ltd. * Author: Vivek Gautam <gautam.vivek@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/clk.h> diff --git a/drivers/phy/samsung/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c index 60e13afcd9b8..9e5fc126032c 100644 --- a/drivers/phy/samsung/phy-exynos5250-sata.c +++ b/drivers/phy/samsung/phy-exynos5250-sata.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung SATA SerDes(PHY) driver * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Authors: Girish K S <ks.giri@samsung.com> * Yuvaraj Kumar C D <yuvaraj.cd@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/clk.h> diff --git a/drivers/phy/samsung/phy-exynos5250-usb2.c b/drivers/phy/samsung/phy-exynos5250-usb2.c index aad806272305..4f53b711fd6f 100644 --- a/drivers/phy/samsung/phy-exynos5250-usb2.c +++ b/drivers/phy/samsung/phy-exynos5250-usb2.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Author: Kamil Debski <k.debski@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/delay.h> diff --git a/drivers/phy/samsung/phy-s5pv210-usb2.c b/drivers/phy/samsung/phy-s5pv210-usb2.c index f6f72339bbc3..56a5083fe6f9 100644 --- a/drivers/phy/samsung/phy-s5pv210-usb2.c +++ b/drivers/phy/samsung/phy-s5pv210-usb2.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Authors: Kamil Debski <k.debski@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/delay.h> diff --git a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c index ea818866985a..6c82f4fbe8a2 100644 --- a/drivers/phy/samsung/phy-samsung-usb2.c +++ b/drivers/phy/samsung/phy-samsung-usb2.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Samsung SoC USB 1.1/2.0 PHY driver * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Author: Kamil Debski <k.debski@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/clk.h> @@ -159,9 +156,8 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) if (!cfg) return -EINVAL; - drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) + - cfg->num_phys * sizeof(struct samsung_usb2_phy_instance), - GFP_KERNEL); + drv = devm_kzalloc(dev, struct_size(drv, instances, cfg->num_phys), + GFP_KERNEL); if (!drv) return -ENOMEM; diff --git a/drivers/phy/samsung/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h index 6563e7ca0ac4..2c1a7d71142b 100644 --- a/drivers/phy/samsung/phy-samsung-usb2.h +++ b/drivers/phy/samsung/phy-samsung-usb2.h @@ -1,12 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Samsung SoC USB 1.1/2.0 PHY driver * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * Author: Kamil Debski <k.debski@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _PHY_EXYNOS_USB2_H diff --git a/drivers/phy/st/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c index 213e2e15339c..068160a34f5c 100644 --- a/drivers/phy/st/phy-miphy28lp.c +++ b/drivers/phy/st/phy-miphy28lp.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2014 STMicroelectronics * * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407). * * Author: Alexandre Torgue <alexandre.torgue@st.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * */ #include <linux/platform_device.h> diff --git a/drivers/phy/st/phy-spear1310-miphy.c b/drivers/phy/st/phy-spear1310-miphy.c index ed67e98e54ca..8871cd186304 100644 --- a/drivers/phy/st/phy-spear1310-miphy.c +++ b/drivers/phy/st/phy-spear1310-miphy.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ST SPEAr1310-miphy driver * * Copyright (C) 2014 ST Microelectronics * Pratyush Anand <pratyush.anand@gmail.com> * Mohit Kumar <mohit.kumar.dhaka@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/bitops.h> diff --git a/drivers/phy/st/phy-spear1340-miphy.c b/drivers/phy/st/phy-spear1340-miphy.c index 97280c0cf612..ed4d0e2df053 100644 --- a/drivers/phy/st/phy-spear1340-miphy.c +++ b/drivers/phy/st/phy-spear1340-miphy.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ST spear1340-miphy driver * * Copyright (C) 2014 ST Microelectronics * Pratyush Anand <pratyush.anand@gmail.com> * Mohit Kumar <mohit.kumar.dhaka@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/bitops.h> diff --git a/drivers/phy/st/phy-stih407-usb.c b/drivers/phy/st/phy-stih407-usb.c index b1f44ab669fb..a4ae2cca7f63 100644 --- a/drivers/phy/st/phy-stih407-usb.c +++ b/drivers/phy/st/phy-stih407-usb.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2014 STMicroelectronics * * STMicroelectronics Generic PHY driver for STiH407 USB2. * * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * */ #include <linux/platform_device.h> #include <linux/io.h> diff --git a/drivers/phy/tegra/xusb-tegra124.c b/drivers/phy/tegra/xusb-tegra124.c index e8a2ba6eabd5..98d84920c676 100644 --- a/drivers/phy/tegra/xusb-tegra124.c +++ b/drivers/phy/tegra/xusb-tegra124.c @@ -1713,6 +1713,13 @@ static const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = { .hsic_set_idle = tegra124_hsic_set_idle, }; +static const char * const tegra124_xusb_padctl_supply_names[] = { + "avdd-pll-utmip", + "avdd-pll-erefe", + "avdd-pex-pll", + "hvdd-pex-pll-e", +}; + const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = { .num_pads = ARRAY_SIZE(tegra124_pads), .pads = tegra124_pads, @@ -1735,6 +1742,8 @@ const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = { }, }, .ops = &tegra124_xusb_padctl_ops, + .supply_names = tegra124_xusb_padctl_supply_names, + .num_supplies = ARRAY_SIZE(tegra124_xusb_padctl_supply_names), }; EXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc); diff --git a/drivers/phy/tegra/xusb-tegra210.c b/drivers/phy/tegra/xusb-tegra210.c index 18cea8311d22..0c0df6897a3b 100644 --- a/drivers/phy/tegra/xusb-tegra210.c +++ b/drivers/phy/tegra/xusb-tegra210.c @@ -2009,6 +2009,13 @@ static const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = { .hsic_set_idle = tegra210_hsic_set_idle, }; +static const char * const tegra210_xusb_padctl_supply_names[] = { + "avdd-pll-utmip", + "avdd-pll-uerefe", + "dvdd-pex-pll", + "hvdd-pex-pll-e", +}; + const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = { .num_pads = ARRAY_SIZE(tegra210_pads), .pads = tegra210_pads, @@ -2027,6 +2034,8 @@ const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = { }, }, .ops = &tegra210_xusb_padctl_ops, + .supply_names = tegra210_xusb_padctl_supply_names, + .num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names), }; EXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc); diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c index d3769200cb9b..f8edd0840fa2 100644 --- a/drivers/phy/ti/phy-am654-serdes.c +++ b/drivers/phy/ti/phy-am654-serdes.c @@ -247,8 +247,8 @@ static void serdes_am654_release(struct phy *x) mux_control_deselect(phy->control); } -struct phy *serdes_am654_xlate(struct device *dev, struct of_phandle_args - *args) +static struct phy *serdes_am654_xlate(struct device *dev, + struct of_phandle_args *args) { struct serdes_am654 *am654_phy; struct phy *phy; diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c index 329fb938099a..d8d0cc11d187 100644 --- a/drivers/phy/ti/phy-tusb1210.c +++ b/drivers/phy/ti/phy-tusb1210.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /** * tusb1210.c - TUSB1210 USB ULPI PHY driver * * Copyright (C) 2015 Intel Corporation * * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/ulpi/driver.h> |