New Features

============
 *) Add driver for USB PHYs on sun9i
 *) Add driver for USB PHY on dm816x
 *) Modified exynos5-usbdrd driver to add support for Exynos5433 SoC
 
 Fixes
 =====
 *) Fix power_on/power_off failure paths in some drivers
 *) Make miphy365x use generic PHY type constants
 *) Fix build errors due to missing export symbols in qcom-ufs driver
 *) Make all the functions return proper error values
 
 Cleanups
 ========
 *) use PTR_ERR_OR_ZERO to simplify code
 *) use devm_kcalloc instead of devm_kzalloc with multiply
 *) remove un-necessary ifdef CONFIG_OF
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJVHrrMAAoJEA5ceFyATYLZV8kP/074teM4HZMAqmUVRG+nRr8b
 Eb8QYOzpnazUKtUovMYePzLjIZ3kvlMepSVVZiZqP6Uc2s6bnhTUN758HZBTdMVO
 Cer63lcp5eM6yBSIL4kNo3+18ikql3LJK9kQZoLGszZmVJzwwqhL/cWxl8+WfZ+P
 U71ciL07xmQD1c1GbRsuDBykaDKnf4M9HVUzP9w/pFANKYWWHdR3bj53kz9W7bGm
 gF/6wVFfxkknPfQjlqo9VUoSPN3P+WIcoM2rPG1b1u2adAAKFSYvXX2eJKWZF6Cz
 L9IZn1bTB0tMkrbswpMRqPtKjfmGyi1Acx8jt8WVA5pjNZ4K2P+9T7vsWifEnYa/
 BDYdJJRzZSL89m9zwEFvLF490pTJrk33eFbqzHDGmDcdtj8KY8XZ9Fp5R2Lmj26s
 mtST0Pi+j9SGg95KZBcXd2l1EJmdDutEYy7LgVvkLk4IFPfOyaAFEhSNW+Qi+Lh9
 SkDqbZUrk9ZxzsWqYJW5LVbQlscJ2NzQuf5AgkrXsufXO0B8RAV5bt0f88ENmQsJ
 rbbbWIb/ljT6YbZqT8z2X8T0PNZBknSfepb5LO5QAZMMJJm2202TondsISytvC9U
 fS5sBIDzuiiMtOA9FwA5Yl1bPWq6QY4OwqIMX3LAs10ylJhbuqJ7nK5qH3O4bpk+
 DzOCd1oLJhXjnOXIujz2
 =0gB+
 -----END PGP SIGNATURE-----

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

Kishon writes:

New Features
============
*) Add driver for USB PHYs on sun9i
*) Add driver for USB PHY on dm816x
*) Modified exynos5-usbdrd driver to add support for Exynos5433 SoC

Fixes
=====
*) Fix power_on/power_off failure paths in some drivers
*) Make miphy365x use generic PHY type constants
*) Fix build errors due to missing export symbols in qcom-ufs driver
*) Make all the functions return proper error values

Cleanups
========
*) use PTR_ERR_OR_ZERO to simplify code
*) use devm_kcalloc instead of devm_kzalloc with multiply
*) remove un-necessary ifdef CONFIG_OF
This commit is contained in:
Greg Kroah-Hartman 2015-04-10 13:47:50 +02:00
commit 2aebe3f3b2
26 changed files with 655 additions and 110 deletions

View file

@ -0,0 +1,24 @@
Device tree binding documentation for am816x USB PHY
=========================
Required properties:
- compatible : should be "ti,dm816x-usb-phy"
- reg : offset and length of the PHY register set.
- reg-names : name for the phy registers
- clocks : phandle to the clock
- clock-names : name of the clock
- syscon: phandle for the syscon node to access misc registers
- #phy-cells : from the generic PHY bindings, must be 1
- syscon: phandle for the syscon node to access misc registers
Example:
usb_phy0: usb-phy@20 {
compatible = "ti,dm8168-usb-phy";
reg = <0x20 0x8>;
reg-names = "phy";
clocks = <&main_fapll 6>;
clock-names = "refclk";
#phy-cells = <0>;
syscon = <&scm_conf>;
};

View file

@ -20,8 +20,8 @@ Required nodes : A sub-node is required for each channel the controller
Required properties (port (child) node):
- #phy-cells : Should be 1 (See second example)
Cell after port phandle is device type from:
- MIPHY_TYPE_SATA
- MIPHY_TYPE_PCI
- PHY_TYPE_SATA
- PHY_TYPE_PCI
- reg : Address and length of register sets for each device in
"reg-names"
- reg-names : The names of the register addresses corresponding to the
@ -68,10 +68,10 @@ property, containing a phandle to the phy port node and a device type.
Example:
#include <dt-bindings/phy/phy-miphy365x.h>
#include <dt-bindings/phy/phy.h>
sata0: sata@fe380000 {
...
phys = <&phy_port0 MIPHY_TYPE_SATA>;
phys = <&phy_port0 PHY_TYPE_SATA>;
...
};

View file

@ -128,6 +128,7 @@ Required properties:
- compatible : Should be set to one of the following supported values:
- "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC,
- "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC.
- "samsung,exynos5433-usbdrd-phy" - for exynos5433 SoC.
- "samsung,exynos7-usbdrd-phy" - for exynos7 SoC.
- reg : Register offset and length of USB DRD PHY register set;
- clocks: Clock IDs array as required by the controller
@ -139,7 +140,7 @@ Required properties:
PHY operations, associated by phy name. It is used to
determine bit values for clock settings register.
For Exynos5420 this is given as 'sclk_usbphy30' in CMU.
- optional clocks: Exynos7 SoC has now following additional
- optional clocks: Exynos5433 & Exynos7 SoC has now following additional
gate clocks available:
- phy_pipe: for PIPE3 phy
- phy_utmi: for UTMI+ phy

View file

@ -0,0 +1,38 @@
Allwinner sun9i USB PHY
-----------------------
Required properties:
- compatible : should be one of
* allwinner,sun9i-a80-usb-phy
- reg : a list of offset + length pairs
- #phy-cells : from the generic phy bindings, must be 0
- phy_type : "hsic" for HSIC usage;
other values or absence of this property indicates normal USB
- clocks : phandle + clock specifier for the phy clocks
- clock-names : depending on the "phy_type" property,
* "phy" for normal USB
* "hsic_480M", "hsic_12M" for HSIC
- resets : a list of phandle + reset specifier pairs
- reset-names : depending on the "phy_type" property,
* "phy" for normal USB
* "hsic" for HSIC
Optional Properties:
- phy-supply : from the generic phy bindings, a phandle to a regulator that
provides power to VBUS.
It is recommended to list all clocks and resets available.
The driver will only use those matching the phy_type.
Example:
usbphy1: phy@00a01800 {
compatible = "allwinner,sun9i-a80-usb-phy";
reg = <0x00a01800 0x4>;
clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>,
<&usb_phy_clk 3>;
clock-names = "hsic_480M", "hsic_12M", "phy";
resets = <&usb_phy_clk 18>, <&usb_phy_clk 19>;
reset-names = "hsic", "phy";
status = "disabled";
#phy-cells = <0>;
};

View file

@ -1468,6 +1468,8 @@ F: drivers/clocksource/arm_global_timer.c
F: drivers/i2c/busses/i2c-st.c
F: drivers/media/rc/st_rc.c
F: drivers/mmc/host/sdhci-st.c
F: drivers/phy/phy-miphy28lp.c
F: drivers/phy/phy-miphy365x.c
F: drivers/phy/phy-stih407-usb.c
F: drivers/phy/phy-stih41x-usb.c
F: drivers/pinctrl/pinctrl-st.c

View file

@ -10,7 +10,7 @@
#include "stih416-clock.dtsi"
#include "stih416-pinctrl.dtsi"
#include <dt-bindings/phy/phy-miphy365x.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset-controller/stih416-resets.h>
/ {
@ -306,7 +306,7 @@
reg = <0xfe380000 0x1000>;
interrupts = <GIC_SPI 157 IRQ_TYPE_NONE>;
interrupt-names = "hostc";
phys = <&phy_port0 MIPHY_TYPE_SATA>;
phys = <&phy_port0 PHY_TYPE_SATA>;
phy-names = "sata-phy";
resets = <&powerdown STIH416_SATA0_POWERDOWN>,
<&softreset STIH416_SATA0_SOFTRESET>;

View file

@ -35,6 +35,13 @@ config ARMADA375_USBCLUSTER_PHY
depends on OF
select GENERIC_PHY
config PHY_DM816X_USB
tristate "TI dm816x USB PHY driver"
depends on ARCH_OMAP2PLUS
select GENERIC_PHY
help
Enable this for dm816x USB to work.
config PHY_EXYNOS_MIPI_VIDEO
tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
depends on HAS_IOMEM
@ -174,6 +181,17 @@ config PHY_SUN4I_USB
This driver controls the entire USB PHY block, both the USB OTG
parts, as well as the 2 regular USB 2 host PHYs.
config PHY_SUN9I_USB
tristate "Allwinner sun9i SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
depends on RESET_CONTROLLER
select GENERIC_PHY
help
Enable this to support the transceiver that is part of Allwinner
sun9i SoCs.
This driver controls each individual USB 2 host PHY.
config PHY_SAMSUNG_USB2
tristate "Samsung USB 2.0 PHY driver"
depends on HAS_IOMEM

View file

@ -5,6 +5,7 @@
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
@ -20,6 +21,7 @@ obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o

View file

@ -218,7 +218,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
if (priv->nphys == 0)
return -ENODEV;
priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
GFP_KERNEL);
if (!priv->phys)
return -ENOMEM;

View file

@ -103,9 +103,6 @@
#define MODE_TEST_EN BIT(11)
#define ANA_TEST_DC_CTRL(x) ((x) << 12)
#define to_phy_berlin_usb_priv(p) \
container_of((p), struct phy_berlin_usb_priv, phy)
static const u32 phy_berlin_pll_dividers[] = {
/* Berlin 2 */
CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
@ -115,14 +112,13 @@ static const u32 phy_berlin_pll_dividers[] = {
struct phy_berlin_usb_priv {
void __iomem *base;
struct phy *phy;
struct reset_control *rst_ctrl;
u32 pll_divider;
};
static int phy_berlin_usb_power_on(struct phy *phy)
{
struct phy_berlin_usb_priv *priv = dev_get_drvdata(phy->dev.parent);
struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);
reset_control_reset(priv->rst_ctrl);
@ -175,6 +171,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
of_match_device(phy_berlin_sata_of_match, &pdev->dev);
struct phy_berlin_usb_priv *priv;
struct resource *res;
struct phy *phy;
struct phy_provider *phy_provider;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@ -192,20 +189,18 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
priv->pll_divider = *((u32 *)match->data);
priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
if (IS_ERR(priv->phy)) {
phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
if (IS_ERR(phy)) {
dev_err(&pdev->dev, "failed to create PHY\n");
return PTR_ERR(priv->phy);
return PTR_ERR(phy);
}
platform_set_drvdata(pdev, priv);
phy_set_drvdata(phy, priv);
phy_provider =
devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
return 0;
return PTR_ERR_OR_ZERO(phy_provider);
}
static struct platform_driver phy_berlin_usb_driver = {

View file

@ -0,0 +1,290 @@
/*
* 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/usb/phy_companion.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>
#include <linux/phy/phy.h>
#include <linux/of_platform.h>
#include <linux/mfd/syscon.h>
/*
* TRM has two sets of USB_CTRL registers.. The correct register bits
* are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the
* phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at
* least dm816x rev c ignores writes to USB_CTRL register, but the TI
* kernel is writing to those so it's possible that later revisions
* have worknig USB_CTRL register.
*
* Also note that At least USB_CTRL register seems to be dm816x specific
* according to the TRM. It's possible that USBPHY_CTRL is more generic,
* but that would have to be checked against the SR70LX documentation
* which does not seem to be publicly available.
*
* Finally, the phy on dm814x and am335x is different from dm816x.
*/
#define DM816X_USB_CTRL_PHYCLKSRC BIT(8) /* 1 = PLL ref clock */
#define DM816X_USB_CTRL_PHYSLEEP1 BIT(1) /* Enable the first phy */
#define DM816X_USB_CTRL_PHYSLEEP0 BIT(0) /* Enable the second phy */
#define DM816X_USBPHY_CTRL_TXRISETUNE 1
#define DM816X_USBPHY_CTRL_TXVREFTUNE 0xc
#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2
struct dm816x_usb_phy {
struct regmap *syscon;
struct device *dev;
unsigned int instance;
struct clk *refclk;
struct usb_phy phy;
unsigned int usb_ctrl; /* Shared between phy0 and phy1 */
unsigned int usbphy_ctrl;
};
static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
{
otg->host = host;
if (!host)
otg->state = OTG_STATE_UNDEFINED;
return 0;
}
static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg,
struct usb_gadget *gadget)
{
otg->gadget = gadget;
if (!gadget)
otg->state = OTG_STATE_UNDEFINED;
return 0;
}
static int dm816x_usb_phy_init(struct phy *x)
{
struct dm816x_usb_phy *phy = phy_get_drvdata(x);
unsigned int val;
int error;
if (clk_get_rate(phy->refclk) != 24000000)
dev_warn(phy->dev, "nonstandard phy refclk\n");
/* Set PLL ref clock and put phys to sleep */
error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
DM816X_USB_CTRL_PHYCLKSRC |
DM816X_USB_CTRL_PHYSLEEP1 |
DM816X_USB_CTRL_PHYSLEEP0,
0);
regmap_read(phy->syscon, phy->usb_ctrl, &val);
if ((val & 3) != 0)
dev_info(phy->dev,
"Working dm816x USB_CTRL! (0x%08x)\n",
val);
/*
* TI kernel sets these values for "symmetrical eye diagram and
* better signal quality" so let's assume somebody checked the
* values with a scope and set them here too.
*/
regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
val |= DM816X_USBPHY_CTRL_TXRISETUNE |
DM816X_USBPHY_CTRL_TXVREFTUNE |
DM816X_USBPHY_CTRL_TXPREEMTUNE;
regmap_write(phy->syscon, phy->usbphy_ctrl, val);
return 0;
}
static struct phy_ops ops = {
.init = dm816x_usb_phy_init,
.owner = THIS_MODULE,
};
static int dm816x_usb_phy_runtime_suspend(struct device *dev)
{
struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
unsigned int mask, val;
int error = 0;
mask = BIT(phy->instance);
val = ~BIT(phy->instance);
error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
mask, val);
if (error)
dev_err(phy->dev, "phy%i failed to power off\n",
phy->instance);
clk_disable(phy->refclk);
return 0;
}
static int dm816x_usb_phy_runtime_resume(struct device *dev)
{
struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
unsigned int mask, val;
int error;
error = clk_enable(phy->refclk);
if (error)
return error;
/*
* Note that at least dm816x rev c does not seem to do
* anything with the USB_CTRL register. But let's follow
* what the TI tree is doing in case later revisions use
* USB_CTRL.
*/
mask = BIT(phy->instance);
val = BIT(phy->instance);
error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
mask, val);
if (error) {
dev_err(phy->dev, "phy%i failed to power on\n",
phy->instance);
clk_disable(phy->refclk);
return error;
}
return 0;
}
static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops,
dm816x_usb_phy_runtime_suspend,
dm816x_usb_phy_runtime_resume,
NULL);
#ifdef CONFIG_OF
static const struct of_device_id dm816x_usb_phy_id_table[] = {
{
.compatible = "ti,dm8168-usb-phy",
},
{},
};
MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table);
#endif
static int dm816x_usb_phy_probe(struct platform_device *pdev)
{
struct dm816x_usb_phy *phy;
struct resource *res;
struct phy *generic_phy;
struct phy_provider *phy_provider;
struct usb_otg *otg;
const struct of_device_id *of_id;
const struct usb_phy_data *phy_data;
int error;
of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table),
&pdev->dev);
if (!of_id)
return -EINVAL;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"syscon");
if (IS_ERR(phy->syscon))
return PTR_ERR(phy->syscon);
/*
* According to sprs614e.pdf, the first usb_ctrl is shared and
* the second instance for usb_ctrl is reserved.. Also the
* register bits are different from earlier TRMs.
*/
phy->usb_ctrl = 0x20;
phy->usbphy_ctrl = (res->start & 0xff) + 4;
if (phy->usbphy_ctrl == 0x2c)
phy->instance = 1;
phy_data = of_id->data;
otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
if (!otg)
return -ENOMEM;
phy->dev = &pdev->dev;
phy->phy.dev = phy->dev;
phy->phy.label = "dm8168_usb_phy";
phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2;
otg->set_host = dm816x_usb_phy_set_host;
otg->set_peripheral = dm816x_usb_phy_set_peripheral;
otg->usb_phy = &phy->phy;
platform_set_drvdata(pdev, phy);
phy->refclk = devm_clk_get(phy->dev, "refclk");
if (IS_ERR(phy->refclk))
return PTR_ERR(phy->refclk);
error = clk_prepare(phy->refclk);
if (error)
return error;
pm_runtime_enable(phy->dev);
generic_phy = devm_phy_create(phy->dev, NULL, &ops);
if (IS_ERR(generic_phy))
return PTR_ERR(generic_phy);
phy_set_drvdata(generic_phy, phy);
phy_provider = devm_of_phy_provider_register(phy->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
usb_add_phy_dev(&phy->phy);
return 0;
}
static int dm816x_usb_phy_remove(struct platform_device *pdev)
{
struct dm816x_usb_phy *phy = platform_get_drvdata(pdev);
usb_remove_phy(&phy->phy);
pm_runtime_disable(phy->dev);
clk_unprepare(phy->refclk);
return 0;
}
static struct platform_driver dm816x_usb_phy_driver = {
.probe = dm816x_usb_phy_probe,
.remove = dm816x_usb_phy_remove,
.driver = {
.name = "dm816x-usb-phy",
.pm = &dm816x_usb_phy_pm_ops,
.of_match_table = of_match_ptr(dm816x_usb_phy_id_table),
},
};
module_platform_driver(dm816x_usb_phy_driver);
MODULE_ALIAS("platform:dm816x_usb");
MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
MODULE_DESCRIPTION("dm816x usb phy driver");
MODULE_LICENSE("GPL v2");

View file

@ -624,6 +624,13 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
.has_common_clk_gate = true,
};
static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
.pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
.has_common_clk_gate = false,
};
static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
@ -637,6 +644,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
}, {
.compatible = "samsung,exynos5420-usbdrd-phy",
.data = &exynos5420_usbdrd_phy
}, {
.compatible = "samsung,exynos5433-usbdrd-phy",
.data = &exynos5433_usbdrd_phy
}, {
.compatible = "samsung,exynos7-usbdrd-phy",
.data = &exynos7_usbdrd_phy

View file

@ -1259,10 +1259,7 @@ static int miphy28lp_probe(struct platform_device *pdev)
}
provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
if (IS_ERR(provider))
return PTR_ERR(provider);
return 0;
return PTR_ERR_OR_ZERO(provider);
}
static const struct of_device_id miphy28lp_of_match[] = {

View file

@ -25,7 +25,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <dt-bindings/phy/phy-miphy365x.h>
#include <dt-bindings/phy/phy.h>
#define HFC_TIMEOUT 100
@ -177,7 +177,7 @@ static u8 rx_tx_spd[] = {
static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
struct miphy365x_dev *miphy_dev)
{
bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
bool sata = (miphy_phy->type == PHY_TYPE_SATA);
return regmap_update_bits(miphy_dev->regmap,
miphy_phy->ctrlreg,
@ -431,7 +431,7 @@ static int miphy365x_init(struct phy *phy)
}
/* Initialise Miphy for PCIe or SATA */
if (miphy_phy->type == MIPHY_TYPE_PCIE)
if (miphy_phy->type == PHY_TYPE_PCIE)
ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
else
ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
@ -455,8 +455,8 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
return ret;
}
if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
(!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) ||
(!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE)))
return 0;
miphy_phy->base = of_iomap(phynode, index);
@ -499,8 +499,8 @@ static struct phy *miphy365x_xlate(struct device *dev,
miphy_phy->type = args->args[0];
if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
miphy_phy->type == MIPHY_TYPE_PCIE)) {
if (!(miphy_phy->type == PHY_TYPE_SATA ||
miphy_phy->type == PHY_TYPE_PCIE)) {
dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
return ERR_PTR(-EINVAL);
}

View file

@ -216,7 +216,6 @@ void omap_control_usb_set_mode(struct device *dev,
return;
ctrl_phy = dev_get_drvdata(dev);
if (!ctrl_phy) {
dev_err(dev, "Invalid control phy device\n");
return;
@ -241,8 +240,6 @@ void omap_control_usb_set_mode(struct device *dev,
}
EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
#ifdef CONFIG_OF
static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
@ -278,8 +275,6 @@ static const struct of_device_id omap_control_phy_id_table[] = {
{},
};
MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
#endif
static int omap_control_phy_probe(struct platform_device *pdev)
{
@ -287,8 +282,7 @@ static int omap_control_phy_probe(struct platform_device *pdev)
const struct of_device_id *of_id;
struct omap_control_phy *control_phy;
of_id = of_match_device(of_match_ptr(omap_control_phy_id_table),
&pdev->dev);
of_id = of_match_device(omap_control_phy_id_table, &pdev->dev);
if (!of_id)
return -EINVAL;
@ -344,7 +338,7 @@ static struct platform_driver omap_control_phy_driver = {
.probe = omap_control_phy_probe,
.driver = {
.name = "omap-control-phy",
.of_match_table = of_match_ptr(omap_control_phy_id_table),
.of_match_table = omap_control_phy_id_table,
},
};

View file

@ -144,7 +144,6 @@ static struct phy_ops ops = {
.owner = THIS_MODULE,
};
#ifdef CONFIG_OF
static const struct usb_phy_data omap_usb2_data = {
.label = "omap_usb2",
.flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
@ -185,7 +184,6 @@ static const struct of_device_id omap_usb2_id_table[] = {
{},
};
MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
#endif
static int omap_usb2_probe(struct platform_device *pdev)
{
@ -200,7 +198,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
const struct of_device_id *of_id;
struct usb_phy_data *phy_data;
of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev);
of_id = of_match_device(omap_usb2_id_table, &pdev->dev);
if (!of_id)
return -EINVAL;
@ -378,7 +376,7 @@ static struct platform_driver omap_usb2_driver = {
.driver = {
.name = "omap-usb2",
.pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(omap_usb2_id_table),
.of_match_table = omap_usb2_id_table,
},
};

View file

@ -73,6 +73,7 @@ int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
out:
return ret;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
struct ufs_qcom_phy *common_cfg,
@ -101,6 +102,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
if (IS_ERR(generic_phy)) {
err = PTR_ERR(generic_phy);
dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
generic_phy = NULL;
goto out;
}
@ -110,6 +112,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
out:
return generic_phy;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
/*
* This assumes the embedded phy structure inside generic_phy is of type
@ -121,6 +124,7 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy)
{
return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy);
}
EXPORT_SYMBOL_GPL(get_ufs_qcom_phy);
static
int ufs_qcom_phy_base_init(struct platform_device *pdev,
@ -131,40 +135,23 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev,
int err = 0;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
if (!res) {
dev_err(dev, "%s: phy_mem resource not found\n", __func__);
err = -ENOMEM;
goto out;
}
phy_common->mmio = devm_ioremap_resource(dev, res);
if (IS_ERR((void const *)phy_common->mmio)) {
err = PTR_ERR((void const *)phy_common->mmio);
phy_common->mmio = NULL;
dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n",
__func__, err);
goto out;
return err;
}
/* "dev_ref_clk_ctrl_mem" is optional resource */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"dev_ref_clk_ctrl_mem");
if (!res) {
dev_dbg(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n",
__func__);
goto out;
}
phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res);
if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio)) {
err = PTR_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio);
if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio))
phy_common->dev_ref_clk_ctrl_mmio = NULL;
dev_err(dev, "%s: ioremap for dev_ref_clk_ctrl_mem resource failed %d\n",
__func__, err);
}
out:
return err;
return 0;
}
static int __ufs_qcom_phy_clk_get(struct phy *phy,
@ -228,6 +215,7 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy,
out:
return err;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
int
ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
@ -252,6 +240,7 @@ ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
out:
return err;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
static int __ufs_qcom_phy_init_vreg(struct phy *phy,
struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional)
@ -647,6 +636,7 @@ int ufs_qcom_phy_remove(struct phy *generic_phy,
return 0;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove);
int ufs_qcom_phy_exit(struct phy *generic_phy)
{
@ -657,6 +647,7 @@ int ufs_qcom_phy_exit(struct phy *generic_phy)
return 0;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit);
int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
{
@ -725,6 +716,7 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
out:
return err;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on);
int ufs_qcom_phy_power_off(struct phy *generic_phy)
{
@ -743,3 +735,4 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
return 0;
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off);

View file

@ -37,10 +37,14 @@ static int samsung_usb2_phy_power_on(struct phy *phy)
spin_lock(&drv->lock);
ret = inst->cfg->power_on(inst);
spin_unlock(&drv->lock);
if (ret)
goto err_power_on;
}
return 0;
err_power_on:
clk_disable_unprepare(drv->ref_clk);
err_instance_clk:
clk_disable_unprepare(drv->clk);
err_main_clk:
@ -51,7 +55,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
{
struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
struct samsung_usb2_phy_driver *drv = inst->drv;
int ret = 0;
int ret;
dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
inst->cfg->label);
@ -59,10 +63,12 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
spin_lock(&drv->lock);
ret = inst->cfg->power_off(inst);
spin_unlock(&drv->lock);
if (ret)
return ret;
}
clk_disable_unprepare(drv->ref_clk);
clk_disable_unprepare(drv->clk);
return ret;
return 0;
}
static struct phy_ops samsung_usb2_phy_ops = {

View file

@ -192,14 +192,14 @@ static struct phy *spear1310_miphy_xlate(struct device *dev,
if (args->args_count < 1) {
dev_err(dev, "DT did not pass correct no of args\n");
return NULL;
return ERR_PTR(-ENODEV);
}
priv->mode = args->args[0];
if (priv->mode != SATA && priv->mode != PCIE) {
dev_err(dev, "DT did not pass correct phy mode\n");
return NULL;
return ERR_PTR(-ENODEV);
}
return priv->phy;

View file

@ -229,14 +229,14 @@ static struct phy *spear1340_miphy_xlate(struct device *dev,
if (args->args_count < 1) {
dev_err(dev, "DT did not pass correct no of args\n");
return NULL;
return ERR_PTR(-ENODEV);
}
priv->mode = args->args[0];
if (priv->mode != SATA && priv->mode != PCIE) {
dev_err(dev, "DT did not pass correct phy mode\n");
return NULL;
return ERR_PTR(-ENODEV);
}
return priv->phy;

View file

@ -87,8 +87,12 @@ static int stih41x_usb_phy_power_on(struct phy *phy)
return ret;
}
return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
phy_dev->cfg->oscok, phy_dev->cfg->oscok);
ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
phy_dev->cfg->oscok, phy_dev->cfg->oscok);
if (ret)
clk_disable_unprepare(phy_dev->clk);
return ret;
}
static int stih41x_usb_phy_power_off(struct phy *phy)

202
drivers/phy/phy-sun9i-usb.c Normal file
View file

@ -0,0 +1,202 @@
/*
* Allwinner sun9i USB phy driver
*
* Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
*
* Based on phy-sun4i-usb.c from
* Hans de Goede <hdegoede@redhat.com>
*
* and code from
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
*
* 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, or
* (at your option) any later version.
*
* 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>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/usb/of.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#define SUNXI_AHB_INCR16_BURST_EN BIT(11)
#define SUNXI_AHB_INCR8_BURST_EN BIT(10)
#define SUNXI_AHB_INCR4_BURST_EN BIT(9)
#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
#define SUNXI_ULPI_BYPASS_EN BIT(0)
/* usb1 HSIC specific bits */
#define SUNXI_EHCI_HS_FORCE BIT(20)
#define SUNXI_HSIC_CONNECT_DET BIT(17)
#define SUNXI_HSIC_CONNECT_INT BIT(16)
#define SUNXI_HSIC BIT(1)
struct sun9i_usb_phy {
struct phy *phy;
void __iomem *pmu;
struct reset_control *reset;
struct clk *clk;
struct clk *hsic_clk;
enum usb_phy_interface type;
};
static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable)
{
u32 bits, reg_value;
bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN |
SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN |
SUNXI_ULPI_BYPASS_EN;
if (phy->type == USBPHY_INTERFACE_MODE_HSIC)
bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE |
SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT;
reg_value = readl(phy->pmu);
if (enable)
reg_value |= bits;
else
reg_value &= ~bits;
writel(reg_value, phy->pmu);
}
static int sun9i_usb_phy_init(struct phy *_phy)
{
struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
int ret;
ret = clk_prepare_enable(phy->clk);
if (ret)
goto err_clk;
ret = clk_prepare_enable(phy->hsic_clk);
if (ret)
goto err_hsic_clk;
ret = reset_control_deassert(phy->reset);
if (ret)
goto err_reset;
sun9i_usb_phy_passby(phy, 1);
return 0;
err_reset:
clk_disable_unprepare(phy->hsic_clk);
err_hsic_clk:
clk_disable_unprepare(phy->clk);
err_clk:
return ret;
}
static int sun9i_usb_phy_exit(struct phy *_phy)
{
struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
sun9i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->hsic_clk);
clk_disable_unprepare(phy->clk);
return 0;
}
static struct phy_ops sun9i_usb_phy_ops = {
.init = sun9i_usb_phy_init,
.exit = sun9i_usb_phy_exit,
.owner = THIS_MODULE,
};
static int sun9i_usb_phy_probe(struct platform_device *pdev)
{
struct sun9i_usb_phy *phy;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct phy_provider *phy_provider;
struct resource *res;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
phy->type = of_usb_get_phy_mode(np);
if (phy->type == USBPHY_INTERFACE_MODE_HSIC) {
phy->clk = devm_clk_get(dev, "hsic_480M");
if (IS_ERR(phy->clk)) {
dev_err(dev, "failed to get hsic_480M clock\n");
return PTR_ERR(phy->clk);
}
phy->hsic_clk = devm_clk_get(dev, "hsic_12M");
if (IS_ERR(phy->clk)) {
dev_err(dev, "failed to get hsic_12M clock\n");
return PTR_ERR(phy->clk);
}
phy->reset = devm_reset_control_get(dev, "hsic");
if (IS_ERR(phy->reset)) {
dev_err(dev, "failed to get reset control\n");
return PTR_ERR(phy->reset);
}
} else {
phy->clk = devm_clk_get(dev, "phy");
if (IS_ERR(phy->clk)) {
dev_err(dev, "failed to get phy clock\n");
return PTR_ERR(phy->clk);
}
phy->reset = devm_reset_control_get(dev, "phy");
if (IS_ERR(phy->reset)) {
dev_err(dev, "failed to get reset control\n");
return PTR_ERR(phy->reset);
}
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
phy->pmu = devm_ioremap_resource(dev, res);
if (IS_ERR(phy->pmu))
return PTR_ERR(phy->pmu);
phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops);
if (IS_ERR(phy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(phy->phy);
}
phy_set_drvdata(phy->phy, phy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id sun9i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun9i-a80-usb-phy" },
{ },
};
MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match);
static struct platform_driver sun9i_usb_phy_driver = {
.probe = sun9i_usb_phy_probe,
.driver = {
.of_match_table = sun9i_usb_phy_of_match,
.name = "sun9i-usb-phy",
}
};
module_platform_driver(sun9i_usb_phy_driver);
MODULE_DESCRIPTION("Allwinner sun9i USB phy driver");
MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
MODULE_LICENSE("GPL");

View file

@ -287,9 +287,7 @@ static struct phy_ops ops = {
.owner = THIS_MODULE,
};
#ifdef CONFIG_OF
static const struct of_device_id ti_pipe3_id_table[];
#endif
static int ti_pipe3_probe(struct platform_device *pdev)
{
@ -311,8 +309,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
spin_lock_init(&phy->lock);
if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
match = of_match_device(of_match_ptr(ti_pipe3_id_table),
&pdev->dev);
match = of_match_device(ti_pipe3_id_table, &pdev->dev);
if (!match)
return -EINVAL;
@ -570,7 +567,6 @@ static const struct dev_pm_ops ti_pipe3_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
};
#ifdef CONFIG_OF
static const struct of_device_id ti_pipe3_id_table[] = {
{
.compatible = "ti,phy-usb3",
@ -590,7 +586,6 @@ static const struct of_device_id ti_pipe3_id_table[] = {
{}
};
MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
#endif
static struct platform_driver ti_pipe3_driver = {
.probe = ti_pipe3_probe,
@ -598,7 +593,7 @@ static struct platform_driver ti_pipe3_driver = {
.driver = {
.name = "ti-pipe3",
.pm = &ti_pipe3_pm_ops,
.of_match_table = of_match_ptr(ti_pipe3_id_table),
.of_match_table = ti_pipe3_id_table,
},
};

View file

@ -1657,7 +1657,6 @@ static int xgene_phy_probe(struct platform_device *pdev)
struct phy_provider *phy_provider;
struct xgene_phy_ctx *ctx;
struct resource *res;
int rc = 0;
u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
@ -1676,10 +1675,8 @@ static int xgene_phy_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ctx->sds_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ctx->sds_base)) {
rc = PTR_ERR(ctx->sds_base);
goto error;
}
if (IS_ERR(ctx->sds_base))
return PTR_ERR(ctx->sds_base);
/* Retrieve optional clock */
ctx->clk = clk_get(&pdev->dev, NULL);
@ -1709,22 +1706,12 @@ static int xgene_phy_probe(struct platform_device *pdev)
ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
if (IS_ERR(ctx->phy)) {
dev_dbg(&pdev->dev, "Failed to create PHY\n");
rc = PTR_ERR(ctx->phy);
goto error;
return PTR_ERR(ctx->phy);
}
phy_set_drvdata(ctx->phy, ctx);
phy_provider = devm_of_phy_provider_register(ctx->dev,
xgene_phy_xlate);
if (IS_ERR(phy_provider)) {
rc = PTR_ERR(phy_provider);
goto error;
}
return 0;
error:
return rc;
phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id xgene_phy_of_match[] = {

View file

@ -1,14 +0,0 @@
/*
* This header provides constants for the phy framework
* based on the STMicroelectronics MiPHY365x.
*
* Author: Lee Jones <lee.jones@linaro.org>
*/
#ifndef _DT_BINDINGS_PHY_MIPHY
#define _DT_BINDINGS_PHY_MIPHY
#define MIPHY_TYPE_SATA 1
#define MIPHY_TYPE_PCIE 2
#define MIPHY_TYPE_USB 3
#endif /* _DT_BINDINGS_PHY_MIPHY */

View file

@ -36,6 +36,9 @@
#define EXYNOS5420_MTCADC_PHY_CONTROL (0x724)
#define EXYNOS5420_DPTX_PHY_CONTROL (0x728)
/* Exynos5433 specific register definitions */
#define EXYNOS5433_USBHOST30_PHY_CONTROL (0x728)
#define EXYNOS5_PHY_ENABLE BIT(0)
#define EXYNOS5_MIPI_PHY_S_RESETN BIT(1)