diff options
author | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 12:17:53 -0700 |
---|---|---|
committer | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 15:44:42 -0700 |
commit | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch) | |
tree | 1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/drivers/phy/phy-stih41x-usb.c | |
parent | 98260f3884f4a202f9ca5eabed40b1354c489b29 (diff) |
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base.
It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and
the base is:
commit 0917f823c59692d751951bf5ea699a2d1e2f26a2
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat Jul 25 12:13:34 2015 +0200
Prepare v4.1.3-rt3
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
We lose all the git history this way and it's not good. We
should apply another opnfv project repo in future.
Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/drivers/phy/phy-stih41x-usb.c')
-rw-r--r-- | kernel/drivers/phy/phy-stih41x-usb.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/kernel/drivers/phy/phy-stih41x-usb.c b/kernel/drivers/phy/phy-stih41x-usb.c new file mode 100644 index 000000000..c093b472b --- /dev/null +++ b/kernel/drivers/phy/phy-stih41x-usb.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2014 STMicroelectronics + * + * STMicroelectronics PHY driver for STiH41x USB. + * + * Author: Maxime Coquelin <maxime.coquelin@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> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> + +#define SYSCFG332 0x80 +#define SYSCFG2520 0x820 + +/** + * struct stih41x_usb_cfg - SoC specific PHY register mapping + * @syscfg: Offset in syscfg registers bank + * @cfg_mask: Bits mask for PHY configuration + * @cfg: Static configuration value for PHY + * @oscok: Notify the PHY oscillator clock is ready + * Setting this bit enable the PHY + */ +struct stih41x_usb_cfg { + u32 syscfg; + u32 cfg_mask; + u32 cfg; + u32 oscok; +}; + +/** + * struct stih41x_usb_phy - Private data for the PHY + * @dev: device for this controller + * @regmap: Syscfg registers bank in which PHY is configured + * @cfg: SoC specific PHY register mapping + * @clk: Oscillator used by the PHY + */ +struct stih41x_usb_phy { + struct device *dev; + struct regmap *regmap; + const struct stih41x_usb_cfg *cfg; + struct clk *clk; +}; + +static struct stih41x_usb_cfg stih415_usb_phy_cfg = { + .syscfg = SYSCFG332, + .cfg_mask = 0x3f, + .cfg = 0x38, + .oscok = BIT(6), +}; + +static struct stih41x_usb_cfg stih416_usb_phy_cfg = { + .syscfg = SYSCFG2520, + .cfg_mask = 0x33f, + .cfg = 0x238, + .oscok = BIT(6), +}; + +static int stih41x_usb_phy_init(struct phy *phy) +{ + struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); + + return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg); +} + +static int stih41x_usb_phy_power_on(struct phy *phy) +{ + struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); + int ret; + + ret = clk_prepare_enable(phy_dev->clk); + if (ret) { + dev_err(phy_dev->dev, "Failed to enable osc_phy clock\n"); + return ret; + } + + 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) +{ + struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); + int ret; + + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->oscok, 0); + if (ret) { + dev_err(phy_dev->dev, "Failed to clear oscok bit\n"); + return ret; + } + + clk_disable_unprepare(phy_dev->clk); + + return 0; +} + +static struct phy_ops stih41x_usb_phy_ops = { + .init = stih41x_usb_phy_init, + .power_on = stih41x_usb_phy_power_on, + .power_off = stih41x_usb_phy_power_off, + .owner = THIS_MODULE, +}; + +static const struct of_device_id stih41x_usb_phy_of_match[]; + +static int stih41x_usb_phy_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct stih41x_usb_phy *phy_dev; + struct device *dev = &pdev->dev; + struct phy_provider *phy_provider; + struct phy *phy; + + phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; + + match = of_match_device(stih41x_usb_phy_of_match, &pdev->dev); + if (!match) + return -ENODEV; + + phy_dev->cfg = match->data; + + phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(phy_dev->regmap)) { + dev_err(dev, "No syscfg phandle specified\n"); + return PTR_ERR(phy_dev->regmap); + } + + phy_dev->clk = devm_clk_get(dev, "osc_phy"); + if (IS_ERR(phy_dev->clk)) { + dev_err(dev, "osc_phy clk not found\n"); + return PTR_ERR(phy_dev->clk); + } + + phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops); + + if (IS_ERR(phy)) { + dev_err(dev, "failed to create phy\n"); + return PTR_ERR(phy); + } + + phy_dev->dev = dev; + + phy_set_drvdata(phy, phy_dev); + + 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 stih41x_usb_phy_of_match[] = { + { .compatible = "st,stih415-usb-phy", .data = &stih415_usb_phy_cfg }, + { .compatible = "st,stih416-usb-phy", .data = &stih416_usb_phy_cfg }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, stih41x_usb_phy_of_match); + +static struct platform_driver stih41x_usb_phy_driver = { + .probe = stih41x_usb_phy_probe, + .driver = { + .name = "stih41x-usb-phy", + .of_match_table = stih41x_usb_phy_of_match, + } +}; +module_platform_driver(stih41x_usb_phy_driver); + +MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics USB PHY driver for STiH41x series"); +MODULE_LICENSE("GPL v2"); |