diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2013-11-28 06:24:00 +0100 |
---|---|---|
committer | Peter Griffin <peter.griffin@linaro.org> | 2014-06-25 17:00:22 +0100 |
commit | 8892e8d863dec0e3cf885fb323fd81487ba11de3 (patch) | |
tree | 0d79f84365c51443461ff0dcee8e463315adcae3 | |
parent | 68246da9fde29bfec78e4ddf270b30b594a9b296 (diff) |
usb: phy: add STiH407 picoPHY for USB2
This patch adds the support for the picoPHY to manage USB2 devices.
This is available on STiH407 and used by the DWC3 HC port#2.
v2: use devm_reset_control_get
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Conflicts:
drivers/usb/phy/Kconfig
drivers/usb/phy/Makefile
-rw-r--r-- | drivers/usb/phy/Kconfig | 9 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-stih407-usb2.c | 168 |
3 files changed, 179 insertions, 0 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e253fa05be68..a7f4a5a70438 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -229,4 +229,13 @@ config USB_ULPI_VIEWPORT Provides read/write operations to the ULPI phy register set for controllers with a viewport register (e.g. Chipidea/ARC controllers). +config PHY_STIH407_USB + tristate "STMicroelectronics picoPHY/MiPHY driver for STiH407 series" + depends on ARCH_STI + help + Enable this to support the USB transceiver that is part of + STMicroelectronics STiH407 SoC series. This will provide the picoPHY + that is used to manage USB2 ports and MiPHY HW associated to USB3 + ports (refer to DWC3 layer). + endmenu diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 24a91332d4ad..b84eff4ee94b 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -29,3 +29,5 @@ obj-$(CONFIG_USB_RCAR_GEN2_PHY) += phy-rcar-gen2-usb.o obj-$(CONFIG_USB_ULPI) += phy-ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o +obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb2.o + diff --git a/drivers/usb/phy/phy-stih407-usb2.c b/drivers/usb/phy/phy-stih407-usb2.c new file mode 100644 index 000000000000..2cb7751ec93e --- /dev/null +++ b/drivers/usb/phy/phy-stih407-usb2.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2013 STMicroelectronics + * + * STMicroelectronics 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> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/clk.h> +#include <linux/regmap.h> +#include <linux/reset.h> +#include <linux/mfd/syscon.h> +#include <linux/usb/phy.h> + +#define phy_to_priv(x) container_of((x), struct stih407_usb2_picophy, phy) + +/* To program USB2 pico PHY control */ +#define STIH407_USB3_PORT2_PICOPHY 0xf4 /* 5061 */ +/* port #2 parameters overriding */ +#define STIH407_USB3_PORT2_PICOPHY_PARAM 0x100 /* 5064 */ +#define STIH407_USB3_PORT2_PICOPHY_PARAM_DEF 0x39a4dc + +/** + * struct stih407_usb_cfg - SoC specific PHY register mapping + * @syscfg: Offset in syscfg registers bank + * @syscfg_param: Offset in syscfg parameter registers bank + * @cfg_mask: Bits mask for PHY configuration + * @cfg: Static configuration value for PHY + * @param_mask: Bits mask for picoPHY parameter register + * @param: Static configuration value for picoPHY parameter register + */ +struct stih407_usb_cfg { + u32 syscfg; + u32 syscfg_param; + u32 cfg_mask; + u32 cfg; + u32 param_mask; + u32 param; +}; + +struct stih407_usb2_picophy { + struct usb_phy phy; + struct regmap *regmap; + const struct stih407_usb_cfg *cfg; + struct reset_control *rstc; +}; + +static struct stih407_usb_cfg stih407_usb2_picophy_cfg = { + .syscfg = STIH407_USB3_PORT2_PICOPHY, + .syscfg_param = STIH407_USB3_PORT2_PICOPHY_PARAM, + .cfg_mask = 0xff, + .cfg = 0x6, + .param_mask = 0xffffffff, + .param = STIH407_USB3_PORT2_PICOPHY_PARAM_DEF, +}; + +static int stih407_usb2_picophy_init(struct usb_phy *phy) +{ + struct stih407_usb2_picophy *phy_dev = phy_to_priv(phy); + int ret; + + dev_info(phy->dev, "picoPHY init...\n"); + + /* USB2 pico PHY control */ + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg); + if (ret) + return ret; + + /* USB2 pico PHY port2 parameters override */ + return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg_param, + phy_dev->cfg->param_mask, + phy_dev->cfg->param); +} + +static const struct of_device_id stih407_usb2_picophy_of_match[]; + +static int stih407_usb2_picophy_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct stih407_usb2_picophy *phy_dev; + struct device *dev = &pdev->dev; + struct usb_phy *phy; + + phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; + + match = of_match_device(stih407_usb2_picophy_of_match, &pdev->dev); + if (!match) + return -ENODEV; + + phy_dev->cfg = match->data; + + phy_dev->rstc = devm_reset_control_get(dev, NULL); + if (IS_ERR(phy_dev->rstc)) { + dev_err(dev, "failed to ctrl picoPHY reset\n"); + return PTR_ERR(phy_dev->rstc); + } + + dev_info(dev, "reset picoPHY\n"); + reset_control_deassert(phy_dev->rstc); + + 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 = &phy_dev->phy; + phy->dev = dev; + phy->label = "STiH407 USB2 picoPHY"; + phy->init = stih407_usb2_picophy_init; + phy->type = USB_PHY_TYPE_USB2; + + usb_add_phy_dev(phy); + + platform_set_drvdata(pdev, phy_dev); + + dev_info(dev, "USB2 picoPHY probed\n"); + + return 0; +} + +static int stih407_usb2_picophy_remove(struct platform_device *pdev) +{ + struct stih407_usb2_picophy *phy_dev = platform_get_drvdata(pdev); + + reset_control_assert(phy_dev->rstc); + + usb_remove_phy(&phy_dev->phy); + + return 0; +} + +static const struct of_device_id stih407_usb2_picophy_of_match[] = { + {.compatible = "st,stih407-usb2phy", .data = &stih407_usb2_picophy_cfg}, + {}, +}; + +MODULE_DEVICE_TABLE(of, stih407_usb2_picophy_of_match); + +static struct platform_driver stih407_usb2_picophy_driver = { + .probe = stih407_usb2_picophy_probe, + .remove = stih407_usb2_picophy_remove, + .driver = { + .name = "stih407-usb2-phy", + .owner = THIS_MODULE, + .of_match_table = stih407_usb2_picophy_of_match, + } +}; + +module_platform_driver(stih407_usb2_picophy_driver); + +MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics USB2 picoPHY driver for STiH407 SoC"); +MODULE_LICENSE("GPL v2"); |