xref: /linux/drivers/phy/socionext/phy-uniphier-usb3hs.c (revision 40d763460614e6b264cf4ef8771d8b70367ecd20)
15ab43d0fSKunihiko Hayashi // SPDX-License-Identifier: GPL-2.0
25ab43d0fSKunihiko Hayashi /*
35ab43d0fSKunihiko Hayashi  * phy-uniphier-usb3hs.c - HS-PHY driver for Socionext UniPhier USB3 controller
45ab43d0fSKunihiko Hayashi  * Copyright 2015-2018 Socionext Inc.
55ab43d0fSKunihiko Hayashi  * Author:
65ab43d0fSKunihiko Hayashi  *      Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
75ab43d0fSKunihiko Hayashi  * Contributors:
85ab43d0fSKunihiko Hayashi  *      Motoya Tanigawa <tanigawa.motoya@socionext.com>
95ab43d0fSKunihiko Hayashi  *      Masami Hiramatsu <masami.hiramatsu@linaro.org>
105ab43d0fSKunihiko Hayashi  */
115ab43d0fSKunihiko Hayashi 
125ab43d0fSKunihiko Hayashi #include <linux/bitfield.h>
135ab43d0fSKunihiko Hayashi #include <linux/bitops.h>
145ab43d0fSKunihiko Hayashi #include <linux/clk.h>
155ab43d0fSKunihiko Hayashi #include <linux/io.h>
165ab43d0fSKunihiko Hayashi #include <linux/module.h>
175ab43d0fSKunihiko Hayashi #include <linux/nvmem-consumer.h>
185ab43d0fSKunihiko Hayashi #include <linux/of.h>
195ab43d0fSKunihiko Hayashi #include <linux/of_platform.h>
205ab43d0fSKunihiko Hayashi #include <linux/phy/phy.h>
215ab43d0fSKunihiko Hayashi #include <linux/platform_device.h>
225ab43d0fSKunihiko Hayashi #include <linux/regulator/consumer.h>
235ab43d0fSKunihiko Hayashi #include <linux/reset.h>
245ab43d0fSKunihiko Hayashi #include <linux/slab.h>
255ab43d0fSKunihiko Hayashi 
265ab43d0fSKunihiko Hayashi #define HSPHY_CFG0		0x0
275ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_HS_I_MASK	GENMASK(31, 28)
285ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_HSDISC_MASK	GENMASK(27, 26)
295ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_SWING_MASK	GENMASK(17, 16)
305ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_SEL_T_MASK	GENMASK(15, 12)
315ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_RTERM_MASK	GENMASK(7, 6)
325ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_TRIMMASK	(HSPHY_CFG0_HS_I_MASK \
335ab43d0fSKunihiko Hayashi 				 | HSPHY_CFG0_SEL_T_MASK \
345ab43d0fSKunihiko Hayashi 				 | HSPHY_CFG0_RTERM_MASK)
355ab43d0fSKunihiko Hayashi 
365ab43d0fSKunihiko Hayashi #define HSPHY_CFG1		0x4
375ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_DAT_EN	BIT(29)
385ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_ADR_EN	BIT(28)
395ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_ADR_MASK	GENMASK(27, 16)
405ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_DAT_MASK	GENMASK(23, 16)
415ab43d0fSKunihiko Hayashi 
425ab43d0fSKunihiko Hayashi #define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) }
435ab43d0fSKunihiko Hayashi 
445ab43d0fSKunihiko Hayashi #define LS_SLEW		PHY_F(10, 6, 6)	/* LS mode slew rate */
455ab43d0fSKunihiko Hayashi #define FS_LS_DRV	PHY_F(10, 5, 5)	/* FS/LS slew rate */
465ab43d0fSKunihiko Hayashi 
475ab43d0fSKunihiko Hayashi #define MAX_PHY_PARAMS	2
485ab43d0fSKunihiko Hayashi 
495ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_param {
505ab43d0fSKunihiko Hayashi 	struct {
515ab43d0fSKunihiko Hayashi 		int reg_no;
525ab43d0fSKunihiko Hayashi 		int msb;
535ab43d0fSKunihiko Hayashi 		int lsb;
545ab43d0fSKunihiko Hayashi 	} field;
555ab43d0fSKunihiko Hayashi 	u8 value;
565ab43d0fSKunihiko Hayashi };
575ab43d0fSKunihiko Hayashi 
585ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param {
595ab43d0fSKunihiko Hayashi 	unsigned int rterm;
605ab43d0fSKunihiko Hayashi 	unsigned int sel_t;
615ab43d0fSKunihiko Hayashi 	unsigned int hs_i;
625ab43d0fSKunihiko Hayashi };
635ab43d0fSKunihiko Hayashi 
645ab43d0fSKunihiko Hayashi #define trim_param_is_valid(p)	((p)->rterm || (p)->sel_t || (p)->hs_i)
655ab43d0fSKunihiko Hayashi 
665ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv {
675ab43d0fSKunihiko Hayashi 	struct device *dev;
685ab43d0fSKunihiko Hayashi 	void __iomem *base;
695ab43d0fSKunihiko Hayashi 	struct clk *clk, *clk_parent, *clk_ext;
705ab43d0fSKunihiko Hayashi 	struct reset_control *rst, *rst_parent;
715ab43d0fSKunihiko Hayashi 	struct regulator *vbus;
725ab43d0fSKunihiko Hayashi 	const struct uniphier_u3hsphy_soc_data *data;
735ab43d0fSKunihiko Hayashi };
745ab43d0fSKunihiko Hayashi 
755ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_soc_data {
765ab43d0fSKunihiko Hayashi 	int nparams;
775ab43d0fSKunihiko Hayashi 	const struct uniphier_u3hsphy_param param[MAX_PHY_PARAMS];
785ab43d0fSKunihiko Hayashi 	u32 config0;
795ab43d0fSKunihiko Hayashi 	u32 config1;
805ab43d0fSKunihiko Hayashi 	void (*trim_func)(struct uniphier_u3hsphy_priv *priv, u32 *pconfig,
815ab43d0fSKunihiko Hayashi 			  struct uniphier_u3hsphy_trim_param *pt);
825ab43d0fSKunihiko Hayashi };
835ab43d0fSKunihiko Hayashi 
845ab43d0fSKunihiko Hayashi static void uniphier_u3hsphy_trim_ld20(struct uniphier_u3hsphy_priv *priv,
855ab43d0fSKunihiko Hayashi 				       u32 *pconfig,
865ab43d0fSKunihiko Hayashi 				       struct uniphier_u3hsphy_trim_param *pt)
875ab43d0fSKunihiko Hayashi {
885ab43d0fSKunihiko Hayashi 	*pconfig &= ~HSPHY_CFG0_RTERM_MASK;
895ab43d0fSKunihiko Hayashi 	*pconfig |= FIELD_PREP(HSPHY_CFG0_RTERM_MASK, pt->rterm);
905ab43d0fSKunihiko Hayashi 
915ab43d0fSKunihiko Hayashi 	*pconfig &= ~HSPHY_CFG0_SEL_T_MASK;
925ab43d0fSKunihiko Hayashi 	*pconfig |= FIELD_PREP(HSPHY_CFG0_SEL_T_MASK, pt->sel_t);
935ab43d0fSKunihiko Hayashi 
945ab43d0fSKunihiko Hayashi 	*pconfig &= ~HSPHY_CFG0_HS_I_MASK;
955ab43d0fSKunihiko Hayashi 	*pconfig |= FIELD_PREP(HSPHY_CFG0_HS_I_MASK,  pt->hs_i);
965ab43d0fSKunihiko Hayashi }
975ab43d0fSKunihiko Hayashi 
985ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_get_nvparam(struct uniphier_u3hsphy_priv *priv,
995ab43d0fSKunihiko Hayashi 					const char *name, unsigned int *val)
1005ab43d0fSKunihiko Hayashi {
1015ab43d0fSKunihiko Hayashi 	struct nvmem_cell *cell;
1025ab43d0fSKunihiko Hayashi 	u8 *buf;
1035ab43d0fSKunihiko Hayashi 
1045ab43d0fSKunihiko Hayashi 	cell = devm_nvmem_cell_get(priv->dev, name);
1055ab43d0fSKunihiko Hayashi 	if (IS_ERR(cell))
1065ab43d0fSKunihiko Hayashi 		return PTR_ERR(cell);
1075ab43d0fSKunihiko Hayashi 
1085ab43d0fSKunihiko Hayashi 	buf = nvmem_cell_read(cell, NULL);
1095ab43d0fSKunihiko Hayashi 	if (IS_ERR(buf))
1105ab43d0fSKunihiko Hayashi 		return PTR_ERR(buf);
1115ab43d0fSKunihiko Hayashi 
1125ab43d0fSKunihiko Hayashi 	*val = *buf;
1135ab43d0fSKunihiko Hayashi 
1145ab43d0fSKunihiko Hayashi 	kfree(buf);
1155ab43d0fSKunihiko Hayashi 
1165ab43d0fSKunihiko Hayashi 	return 0;
1175ab43d0fSKunihiko Hayashi }
1185ab43d0fSKunihiko Hayashi 
1195ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_get_nvparams(struct uniphier_u3hsphy_priv *priv,
1205ab43d0fSKunihiko Hayashi 					 struct uniphier_u3hsphy_trim_param *pt)
1215ab43d0fSKunihiko Hayashi {
1225ab43d0fSKunihiko Hayashi 	int ret;
1235ab43d0fSKunihiko Hayashi 
1245ab43d0fSKunihiko Hayashi 	ret = uniphier_u3hsphy_get_nvparam(priv, "rterm", &pt->rterm);
1255ab43d0fSKunihiko Hayashi 	if (ret)
1265ab43d0fSKunihiko Hayashi 		return ret;
1275ab43d0fSKunihiko Hayashi 
1285ab43d0fSKunihiko Hayashi 	ret = uniphier_u3hsphy_get_nvparam(priv, "sel_t", &pt->sel_t);
1295ab43d0fSKunihiko Hayashi 	if (ret)
1305ab43d0fSKunihiko Hayashi 		return ret;
1315ab43d0fSKunihiko Hayashi 
1325ab43d0fSKunihiko Hayashi 	ret = uniphier_u3hsphy_get_nvparam(priv, "hs_i", &pt->hs_i);
1335ab43d0fSKunihiko Hayashi 	if (ret)
1345ab43d0fSKunihiko Hayashi 		return ret;
1355ab43d0fSKunihiko Hayashi 
1365ab43d0fSKunihiko Hayashi 	return 0;
1375ab43d0fSKunihiko Hayashi }
1385ab43d0fSKunihiko Hayashi 
1395ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_update_config(struct uniphier_u3hsphy_priv *priv,
1405ab43d0fSKunihiko Hayashi 					  u32 *pconfig)
1415ab43d0fSKunihiko Hayashi {
1425ab43d0fSKunihiko Hayashi 	struct uniphier_u3hsphy_trim_param trim;
1435ab43d0fSKunihiko Hayashi 	int ret, trimmed = 0;
1445ab43d0fSKunihiko Hayashi 
1455ab43d0fSKunihiko Hayashi 	if (priv->data->trim_func) {
1465ab43d0fSKunihiko Hayashi 		ret = uniphier_u3hsphy_get_nvparams(priv, &trim);
1475ab43d0fSKunihiko Hayashi 		if (ret == -EPROBE_DEFER)
1485ab43d0fSKunihiko Hayashi 			return ret;
1495ab43d0fSKunihiko Hayashi 
1505ab43d0fSKunihiko Hayashi 		/*
1515ab43d0fSKunihiko Hayashi 		 * call trim_func only when trimming parameters that aren't
1525ab43d0fSKunihiko Hayashi 		 * all-zero can be acquired. All-zero parameters mean nothing
1535ab43d0fSKunihiko Hayashi 		 * has been written to nvmem.
1545ab43d0fSKunihiko Hayashi 		 */
1555ab43d0fSKunihiko Hayashi 		if (!ret && trim_param_is_valid(&trim)) {
1565ab43d0fSKunihiko Hayashi 			priv->data->trim_func(priv, pconfig, &trim);
1575ab43d0fSKunihiko Hayashi 			trimmed = 1;
1585ab43d0fSKunihiko Hayashi 		} else {
1595ab43d0fSKunihiko Hayashi 			dev_dbg(priv->dev, "can't get parameter from nvmem\n");
1605ab43d0fSKunihiko Hayashi 		}
1615ab43d0fSKunihiko Hayashi 	}
1625ab43d0fSKunihiko Hayashi 
1635ab43d0fSKunihiko Hayashi 	/* use default parameters without trimming values */
1645ab43d0fSKunihiko Hayashi 	if (!trimmed) {
1655ab43d0fSKunihiko Hayashi 		*pconfig &= ~HSPHY_CFG0_HSDISC_MASK;
1665ab43d0fSKunihiko Hayashi 		*pconfig |= FIELD_PREP(HSPHY_CFG0_HSDISC_MASK, 3);
1675ab43d0fSKunihiko Hayashi 	}
1685ab43d0fSKunihiko Hayashi 
1695ab43d0fSKunihiko Hayashi 	return 0;
1705ab43d0fSKunihiko Hayashi }
1715ab43d0fSKunihiko Hayashi 
1725ab43d0fSKunihiko Hayashi static void uniphier_u3hsphy_set_param(struct uniphier_u3hsphy_priv *priv,
1735ab43d0fSKunihiko Hayashi 				       const struct uniphier_u3hsphy_param *p)
1745ab43d0fSKunihiko Hayashi {
1755ab43d0fSKunihiko Hayashi 	u32 val;
1765ab43d0fSKunihiko Hayashi 	u32 field_mask = GENMASK(p->field.msb, p->field.lsb);
1775ab43d0fSKunihiko Hayashi 	u8 data;
1785ab43d0fSKunihiko Hayashi 
1795ab43d0fSKunihiko Hayashi 	val = readl(priv->base + HSPHY_CFG1);
1805ab43d0fSKunihiko Hayashi 	val &= ~HSPHY_CFG1_ADR_MASK;
1815ab43d0fSKunihiko Hayashi 	val |= FIELD_PREP(HSPHY_CFG1_ADR_MASK, p->field.reg_no)
1825ab43d0fSKunihiko Hayashi 		| HSPHY_CFG1_ADR_EN;
1835ab43d0fSKunihiko Hayashi 	writel(val, priv->base + HSPHY_CFG1);
1845ab43d0fSKunihiko Hayashi 
1855ab43d0fSKunihiko Hayashi 	val = readl(priv->base + HSPHY_CFG1);
1865ab43d0fSKunihiko Hayashi 	val &= ~HSPHY_CFG1_ADR_EN;
1875ab43d0fSKunihiko Hayashi 	writel(val, priv->base + HSPHY_CFG1);
1885ab43d0fSKunihiko Hayashi 
1895ab43d0fSKunihiko Hayashi 	val = readl(priv->base + HSPHY_CFG1);
1905ab43d0fSKunihiko Hayashi 	val &= ~FIELD_PREP(HSPHY_CFG1_DAT_MASK, field_mask);
1915ab43d0fSKunihiko Hayashi 	data = field_mask & (p->value << p->field.lsb);
1925ab43d0fSKunihiko Hayashi 	val |=  FIELD_PREP(HSPHY_CFG1_DAT_MASK, data) | HSPHY_CFG1_DAT_EN;
1935ab43d0fSKunihiko Hayashi 	writel(val, priv->base + HSPHY_CFG1);
1945ab43d0fSKunihiko Hayashi 
1955ab43d0fSKunihiko Hayashi 	val = readl(priv->base + HSPHY_CFG1);
1965ab43d0fSKunihiko Hayashi 	val &= ~HSPHY_CFG1_DAT_EN;
1975ab43d0fSKunihiko Hayashi 	writel(val, priv->base + HSPHY_CFG1);
1985ab43d0fSKunihiko Hayashi }
1995ab43d0fSKunihiko Hayashi 
2005ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_power_on(struct phy *phy)
2015ab43d0fSKunihiko Hayashi {
2025ab43d0fSKunihiko Hayashi 	struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
2035ab43d0fSKunihiko Hayashi 	int ret;
2045ab43d0fSKunihiko Hayashi 
2055ab43d0fSKunihiko Hayashi 	ret = clk_prepare_enable(priv->clk_ext);
2065ab43d0fSKunihiko Hayashi 	if (ret)
2075ab43d0fSKunihiko Hayashi 		return ret;
2085ab43d0fSKunihiko Hayashi 
2095ab43d0fSKunihiko Hayashi 	ret = clk_prepare_enable(priv->clk);
2105ab43d0fSKunihiko Hayashi 	if (ret)
2115ab43d0fSKunihiko Hayashi 		goto out_clk_ext_disable;
2125ab43d0fSKunihiko Hayashi 
2135ab43d0fSKunihiko Hayashi 	ret = reset_control_deassert(priv->rst);
2145ab43d0fSKunihiko Hayashi 	if (ret)
2155ab43d0fSKunihiko Hayashi 		goto out_clk_disable;
2165ab43d0fSKunihiko Hayashi 
2175ab43d0fSKunihiko Hayashi 	if (priv->vbus) {
2185ab43d0fSKunihiko Hayashi 		ret = regulator_enable(priv->vbus);
2195ab43d0fSKunihiko Hayashi 		if (ret)
2205ab43d0fSKunihiko Hayashi 			goto out_rst_assert;
2215ab43d0fSKunihiko Hayashi 	}
2225ab43d0fSKunihiko Hayashi 
2235ab43d0fSKunihiko Hayashi 	return 0;
2245ab43d0fSKunihiko Hayashi 
2255ab43d0fSKunihiko Hayashi out_rst_assert:
2265ab43d0fSKunihiko Hayashi 	reset_control_assert(priv->rst);
2275ab43d0fSKunihiko Hayashi out_clk_disable:
2285ab43d0fSKunihiko Hayashi 	clk_disable_unprepare(priv->clk);
2295ab43d0fSKunihiko Hayashi out_clk_ext_disable:
2305ab43d0fSKunihiko Hayashi 	clk_disable_unprepare(priv->clk_ext);
2315ab43d0fSKunihiko Hayashi 
2325ab43d0fSKunihiko Hayashi 	return ret;
2335ab43d0fSKunihiko Hayashi }
2345ab43d0fSKunihiko Hayashi 
2355ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_power_off(struct phy *phy)
2365ab43d0fSKunihiko Hayashi {
2375ab43d0fSKunihiko Hayashi 	struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
2385ab43d0fSKunihiko Hayashi 
2395ab43d0fSKunihiko Hayashi 	if (priv->vbus)
2405ab43d0fSKunihiko Hayashi 		regulator_disable(priv->vbus);
2415ab43d0fSKunihiko Hayashi 
2425ab43d0fSKunihiko Hayashi 	reset_control_assert(priv->rst);
2435ab43d0fSKunihiko Hayashi 	clk_disable_unprepare(priv->clk);
2445ab43d0fSKunihiko Hayashi 	clk_disable_unprepare(priv->clk_ext);
2455ab43d0fSKunihiko Hayashi 
2465ab43d0fSKunihiko Hayashi 	return 0;
2475ab43d0fSKunihiko Hayashi }
2485ab43d0fSKunihiko Hayashi 
2495ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_init(struct phy *phy)
2505ab43d0fSKunihiko Hayashi {
2515ab43d0fSKunihiko Hayashi 	struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
2525ab43d0fSKunihiko Hayashi 	u32 config0, config1;
2535ab43d0fSKunihiko Hayashi 	int i, ret;
2545ab43d0fSKunihiko Hayashi 
2555ab43d0fSKunihiko Hayashi 	ret = clk_prepare_enable(priv->clk_parent);
2565ab43d0fSKunihiko Hayashi 	if (ret)
2575ab43d0fSKunihiko Hayashi 		return ret;
2585ab43d0fSKunihiko Hayashi 
2595ab43d0fSKunihiko Hayashi 	ret = reset_control_deassert(priv->rst_parent);
2605ab43d0fSKunihiko Hayashi 	if (ret)
2615ab43d0fSKunihiko Hayashi 		goto out_clk_disable;
2625ab43d0fSKunihiko Hayashi 
2635ab43d0fSKunihiko Hayashi 	if (!priv->data->config0 && !priv->data->config1)
2645ab43d0fSKunihiko Hayashi 		return 0;
2655ab43d0fSKunihiko Hayashi 
2665ab43d0fSKunihiko Hayashi 	config0 = priv->data->config0;
2675ab43d0fSKunihiko Hayashi 	config1 = priv->data->config1;
2685ab43d0fSKunihiko Hayashi 
2695ab43d0fSKunihiko Hayashi 	ret = uniphier_u3hsphy_update_config(priv, &config0);
2705ab43d0fSKunihiko Hayashi 	if (ret)
2715ab43d0fSKunihiko Hayashi 		goto out_rst_assert;
2725ab43d0fSKunihiko Hayashi 
2735ab43d0fSKunihiko Hayashi 	writel(config0, priv->base + HSPHY_CFG0);
2745ab43d0fSKunihiko Hayashi 	writel(config1, priv->base + HSPHY_CFG1);
2755ab43d0fSKunihiko Hayashi 
2765ab43d0fSKunihiko Hayashi 	for (i = 0; i < priv->data->nparams; i++)
2775ab43d0fSKunihiko Hayashi 		uniphier_u3hsphy_set_param(priv, &priv->data->param[i]);
2785ab43d0fSKunihiko Hayashi 
2795ab43d0fSKunihiko Hayashi 	return 0;
2805ab43d0fSKunihiko Hayashi 
2815ab43d0fSKunihiko Hayashi out_rst_assert:
2825ab43d0fSKunihiko Hayashi 	reset_control_assert(priv->rst_parent);
2835ab43d0fSKunihiko Hayashi out_clk_disable:
2845ab43d0fSKunihiko Hayashi 	clk_disable_unprepare(priv->clk_parent);
2855ab43d0fSKunihiko Hayashi 
2865ab43d0fSKunihiko Hayashi 	return ret;
2875ab43d0fSKunihiko Hayashi }
2885ab43d0fSKunihiko Hayashi 
2895ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_exit(struct phy *phy)
2905ab43d0fSKunihiko Hayashi {
2915ab43d0fSKunihiko Hayashi 	struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
2925ab43d0fSKunihiko Hayashi 
2935ab43d0fSKunihiko Hayashi 	reset_control_assert(priv->rst_parent);
2945ab43d0fSKunihiko Hayashi 	clk_disable_unprepare(priv->clk_parent);
2955ab43d0fSKunihiko Hayashi 
2965ab43d0fSKunihiko Hayashi 	return 0;
2975ab43d0fSKunihiko Hayashi }
2985ab43d0fSKunihiko Hayashi 
2995ab43d0fSKunihiko Hayashi static const struct phy_ops uniphier_u3hsphy_ops = {
3005ab43d0fSKunihiko Hayashi 	.init           = uniphier_u3hsphy_init,
3015ab43d0fSKunihiko Hayashi 	.exit           = uniphier_u3hsphy_exit,
3025ab43d0fSKunihiko Hayashi 	.power_on       = uniphier_u3hsphy_power_on,
3035ab43d0fSKunihiko Hayashi 	.power_off      = uniphier_u3hsphy_power_off,
3045ab43d0fSKunihiko Hayashi 	.owner          = THIS_MODULE,
3055ab43d0fSKunihiko Hayashi };
3065ab43d0fSKunihiko Hayashi 
3075ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_probe(struct platform_device *pdev)
3085ab43d0fSKunihiko Hayashi {
3095ab43d0fSKunihiko Hayashi 	struct device *dev = &pdev->dev;
3105ab43d0fSKunihiko Hayashi 	struct uniphier_u3hsphy_priv *priv;
3115ab43d0fSKunihiko Hayashi 	struct phy_provider *phy_provider;
3125ab43d0fSKunihiko Hayashi 	struct phy *phy;
3135ab43d0fSKunihiko Hayashi 
3145ab43d0fSKunihiko Hayashi 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
3155ab43d0fSKunihiko Hayashi 	if (!priv)
3165ab43d0fSKunihiko Hayashi 		return -ENOMEM;
3175ab43d0fSKunihiko Hayashi 
3185ab43d0fSKunihiko Hayashi 	priv->dev = dev;
3195ab43d0fSKunihiko Hayashi 	priv->data = of_device_get_match_data(dev);
3205ab43d0fSKunihiko Hayashi 	if (WARN_ON(!priv->data ||
3215ab43d0fSKunihiko Hayashi 		    priv->data->nparams > MAX_PHY_PARAMS))
3225ab43d0fSKunihiko Hayashi 		return -EINVAL;
3235ab43d0fSKunihiko Hayashi 
324*40d76346SKunihiko Hayashi 	priv->base = devm_platform_ioremap_resource(pdev, 0);
3255ab43d0fSKunihiko Hayashi 	if (IS_ERR(priv->base))
3265ab43d0fSKunihiko Hayashi 		return PTR_ERR(priv->base);
3275ab43d0fSKunihiko Hayashi 
3285ab43d0fSKunihiko Hayashi 	priv->clk = devm_clk_get(dev, "phy");
3295ab43d0fSKunihiko Hayashi 	if (IS_ERR(priv->clk))
3305ab43d0fSKunihiko Hayashi 		return PTR_ERR(priv->clk);
3315ab43d0fSKunihiko Hayashi 
3325ab43d0fSKunihiko Hayashi 	priv->clk_parent = devm_clk_get(dev, "link");
3335ab43d0fSKunihiko Hayashi 	if (IS_ERR(priv->clk_parent))
3345ab43d0fSKunihiko Hayashi 		return PTR_ERR(priv->clk_parent);
3355ab43d0fSKunihiko Hayashi 
336752d31a3SChunfeng Yun 	priv->clk_ext = devm_clk_get_optional(dev, "phy-ext");
337752d31a3SChunfeng Yun 	if (IS_ERR(priv->clk_ext))
3385ab43d0fSKunihiko Hayashi 		return PTR_ERR(priv->clk_ext);
3395ab43d0fSKunihiko Hayashi 
3405ab43d0fSKunihiko Hayashi 	priv->rst = devm_reset_control_get_shared(dev, "phy");
3415ab43d0fSKunihiko Hayashi 	if (IS_ERR(priv->rst))
3425ab43d0fSKunihiko Hayashi 		return PTR_ERR(priv->rst);
3435ab43d0fSKunihiko Hayashi 
3445ab43d0fSKunihiko Hayashi 	priv->rst_parent = devm_reset_control_get_shared(dev, "link");
3455ab43d0fSKunihiko Hayashi 	if (IS_ERR(priv->rst_parent))
3465ab43d0fSKunihiko Hayashi 		return PTR_ERR(priv->rst_parent);
3475ab43d0fSKunihiko Hayashi 
3485ab43d0fSKunihiko Hayashi 	priv->vbus = devm_regulator_get_optional(dev, "vbus");
3495ab43d0fSKunihiko Hayashi 	if (IS_ERR(priv->vbus)) {
3505ab43d0fSKunihiko Hayashi 		if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
3515ab43d0fSKunihiko Hayashi 			return PTR_ERR(priv->vbus);
3525ab43d0fSKunihiko Hayashi 		priv->vbus = NULL;
3535ab43d0fSKunihiko Hayashi 	}
3545ab43d0fSKunihiko Hayashi 
3555ab43d0fSKunihiko Hayashi 	phy = devm_phy_create(dev, dev->of_node, &uniphier_u3hsphy_ops);
3565ab43d0fSKunihiko Hayashi 	if (IS_ERR(phy))
3575ab43d0fSKunihiko Hayashi 		return PTR_ERR(phy);
3585ab43d0fSKunihiko Hayashi 
3595ab43d0fSKunihiko Hayashi 	phy_set_drvdata(phy, priv);
3605ab43d0fSKunihiko Hayashi 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
3615ab43d0fSKunihiko Hayashi 
3625ab43d0fSKunihiko Hayashi 	return PTR_ERR_OR_ZERO(phy_provider);
3635ab43d0fSKunihiko Hayashi }
3645ab43d0fSKunihiko Hayashi 
3655ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = {
3665ab43d0fSKunihiko Hayashi 	.nparams = 0,
3675ab43d0fSKunihiko Hayashi };
3685ab43d0fSKunihiko Hayashi 
3695ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = {
3705ab43d0fSKunihiko Hayashi 	.nparams = 2,
3715ab43d0fSKunihiko Hayashi 	.param = {
3725ab43d0fSKunihiko Hayashi 		{ LS_SLEW, 1 },
3735ab43d0fSKunihiko Hayashi 		{ FS_LS_DRV, 1 },
3745ab43d0fSKunihiko Hayashi 	},
3755ab43d0fSKunihiko Hayashi 	.trim_func = uniphier_u3hsphy_trim_ld20,
3765ab43d0fSKunihiko Hayashi 	.config0 = 0x92316680,
3775ab43d0fSKunihiko Hayashi 	.config1 = 0x00000106,
3785ab43d0fSKunihiko Hayashi };
3795ab43d0fSKunihiko Hayashi 
3805ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pxs3_data = {
3815ab43d0fSKunihiko Hayashi 	.nparams = 0,
3825ab43d0fSKunihiko Hayashi 	.trim_func = uniphier_u3hsphy_trim_ld20,
3835ab43d0fSKunihiko Hayashi 	.config0 = 0x92316680,
3845ab43d0fSKunihiko Hayashi 	.config1 = 0x00000106,
3855ab43d0fSKunihiko Hayashi };
3865ab43d0fSKunihiko Hayashi 
3875ab43d0fSKunihiko Hayashi static const struct of_device_id uniphier_u3hsphy_match[] = {
3885ab43d0fSKunihiko Hayashi 	{
3895ab43d0fSKunihiko Hayashi 		.compatible = "socionext,uniphier-pxs2-usb3-hsphy",
3905ab43d0fSKunihiko Hayashi 		.data = &uniphier_pxs2_data,
3915ab43d0fSKunihiko Hayashi 	},
3925ab43d0fSKunihiko Hayashi 	{
3935ab43d0fSKunihiko Hayashi 		.compatible = "socionext,uniphier-ld20-usb3-hsphy",
3945ab43d0fSKunihiko Hayashi 		.data = &uniphier_ld20_data,
3955ab43d0fSKunihiko Hayashi 	},
3965ab43d0fSKunihiko Hayashi 	{
3975ab43d0fSKunihiko Hayashi 		.compatible = "socionext,uniphier-pxs3-usb3-hsphy",
3985ab43d0fSKunihiko Hayashi 		.data = &uniphier_pxs3_data,
3995ab43d0fSKunihiko Hayashi 	},
4005ab43d0fSKunihiko Hayashi 	{ /* sentinel */ }
4015ab43d0fSKunihiko Hayashi };
4025ab43d0fSKunihiko Hayashi MODULE_DEVICE_TABLE(of, uniphier_u3hsphy_match);
4035ab43d0fSKunihiko Hayashi 
4045ab43d0fSKunihiko Hayashi static struct platform_driver uniphier_u3hsphy_driver = {
4055ab43d0fSKunihiko Hayashi 	.probe = uniphier_u3hsphy_probe,
4065ab43d0fSKunihiko Hayashi 	.driver	= {
4075ab43d0fSKunihiko Hayashi 		.name = "uniphier-usb3-hsphy",
4085ab43d0fSKunihiko Hayashi 		.of_match_table	= uniphier_u3hsphy_match,
4095ab43d0fSKunihiko Hayashi 	},
4105ab43d0fSKunihiko Hayashi };
4115ab43d0fSKunihiko Hayashi 
4125ab43d0fSKunihiko Hayashi module_platform_driver(uniphier_u3hsphy_driver);
4135ab43d0fSKunihiko Hayashi 
4145ab43d0fSKunihiko Hayashi MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
4155ab43d0fSKunihiko Hayashi MODULE_DESCRIPTION("UniPhier HS-PHY driver for USB3 controller");
4165ab43d0fSKunihiko Hayashi MODULE_LICENSE("GPL v2");
417