summaryrefslogtreecommitdiffstats
path: root/drivers/phy/amlogic/phy-meson-gxl-usb2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy/amlogic/phy-meson-gxl-usb2.c')
-rw-r--r--drivers/phy/amlogic/phy-meson-gxl-usb2.c78
1 files changed, 57 insertions, 21 deletions
diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb2.c b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
index e90c4ee25dfe..9f9b5414b97a 100644
--- a/drivers/phy/amlogic/phy-meson-gxl-usb2.c
+++ b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
@@ -11,14 +11,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
-#include <linux/usb/of.h>
/* bits [31:27] are read-only */
#define U2P_R0 0x0
@@ -70,12 +71,11 @@
/* bits [31:14] are read-only */
#define U2P_R2 0x8
- #define U2P_R2_DATA_IN_MASK GENMASK(3, 0)
- #define U2P_R2_DATA_IN_EN_MASK GENMASK(7, 4)
- #define U2P_R2_ADDR_MASK GENMASK(11, 8)
- #define U2P_R2_DATA_OUT_SEL BIT(12)
- #define U2P_R2_CLK BIT(13)
- #define U2P_R2_DATA_OUT_MASK GENMASK(17, 14)
+ #define U2P_R2_TESTDATA_IN_MASK GENMASK(7, 0)
+ #define U2P_R2_TESTADDR_MASK GENMASK(11, 8)
+ #define U2P_R2_TESTDATA_OUT_SEL BIT(12)
+ #define U2P_R2_TESTCLK BIT(13)
+ #define U2P_R2_TESTDATA_OUT_MASK GENMASK(17, 14)
#define U2P_R2_ACA_PIN_RANGE_C BIT(18)
#define U2P_R2_ACA_PIN_RANGE_B BIT(19)
#define U2P_R2_ACA_PIN_RANGE_A BIT(20)
@@ -99,6 +99,8 @@ struct phy_meson_gxl_usb2_priv {
struct regmap *regmap;
enum phy_mode mode;
int is_enabled;
+ struct clk *clk;
+ struct reset_control *reset;
};
static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
@@ -108,6 +110,31 @@ static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
.max_register = U2P_R3,
};
+static int phy_meson_gxl_usb2_init(struct phy *phy)
+{
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = reset_control_reset(priv->reset);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int phy_meson_gxl_usb2_exit(struct phy *phy)
+{
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
static int phy_meson_gxl_usb2_reset(struct phy *phy)
{
struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
@@ -195,6 +222,8 @@ static int phy_meson_gxl_usb2_power_on(struct phy *phy)
}
static const struct phy_ops phy_meson_gxl_usb2_ops = {
+ .init = phy_meson_gxl_usb2_init,
+ .exit = phy_meson_gxl_usb2_exit,
.power_on = phy_meson_gxl_usb2_power_on,
.power_off = phy_meson_gxl_usb2_power_off,
.set_mode = phy_meson_gxl_usb2_set_mode,
@@ -210,6 +239,7 @@ static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
struct phy_meson_gxl_usb2_priv *priv;
struct phy *phy;
void __iomem *base;
+ int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -222,28 +252,34 @@ static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- switch (of_usb_get_dr_mode_by_phy(dev->of_node, -1)) {
- case USB_DR_MODE_PERIPHERAL:
- priv->mode = PHY_MODE_USB_DEVICE;
- break;
- case USB_DR_MODE_OTG:
- priv->mode = PHY_MODE_USB_OTG;
- break;
- case USB_DR_MODE_HOST:
- default:
- priv->mode = PHY_MODE_USB_HOST;
- break;
- }
+ /* start in host mode */
+ priv->mode = PHY_MODE_USB_HOST;
priv->regmap = devm_regmap_init_mmio(dev, base,
&phy_meson_gxl_usb2_regmap_conf);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
+ priv->clk = devm_clk_get(dev, "phy");
+ if (IS_ERR(priv->clk)) {
+ ret = PTR_ERR(priv->clk);
+ if (ret == -ENOENT)
+ priv->clk = NULL;
+ else
+ return ret;
+ }
+
+ priv->reset = devm_reset_control_get_optional_shared(dev, "phy");
+ if (IS_ERR(priv->reset))
+ return PTR_ERR(priv->reset);
+
phy = devm_phy_create(dev, NULL, &phy_meson_gxl_usb2_ops);
if (IS_ERR(phy)) {
- dev_err(dev, "failed to create PHY\n");
- return PTR_ERR(phy);
+ ret = PTR_ERR(phy);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to create PHY\n");
+
+ return ret;
}
phy_set_drvdata(phy, priv);