xref: /rk3399_rockchip-uboot/drivers/phy/ti-pipe3-phy.c (revision 90aa625c9a9e1fb7a2f001fd8e50099bacaf92b8)
1982082d9SJean-Jacques Hiblot /*
2982082d9SJean-Jacques Hiblot  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
3982082d9SJean-Jacques Hiblot  * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
4982082d9SJean-Jacques Hiblot  *
5982082d9SJean-Jacques Hiblot  * SPDX-License-Identifier:	GPL-2.0+
6982082d9SJean-Jacques Hiblot  */
7982082d9SJean-Jacques Hiblot 
8982082d9SJean-Jacques Hiblot #include <common.h>
9982082d9SJean-Jacques Hiblot #include <dm.h>
10982082d9SJean-Jacques Hiblot #include <dm/device.h>
11982082d9SJean-Jacques Hiblot #include <generic-phy.h>
12982082d9SJean-Jacques Hiblot #include <asm/io.h>
13982082d9SJean-Jacques Hiblot #include <asm/arch/sys_proto.h>
14982082d9SJean-Jacques Hiblot #include <syscon.h>
15982082d9SJean-Jacques Hiblot #include <regmap.h>
16982082d9SJean-Jacques Hiblot 
17982082d9SJean-Jacques Hiblot /* PLLCTRL Registers */
18982082d9SJean-Jacques Hiblot #define PLL_STATUS              0x00000004
19982082d9SJean-Jacques Hiblot #define PLL_GO                  0x00000008
20982082d9SJean-Jacques Hiblot #define PLL_CONFIGURATION1      0x0000000C
21982082d9SJean-Jacques Hiblot #define PLL_CONFIGURATION2      0x00000010
22982082d9SJean-Jacques Hiblot #define PLL_CONFIGURATION3      0x00000014
23982082d9SJean-Jacques Hiblot #define PLL_CONFIGURATION4      0x00000020
24982082d9SJean-Jacques Hiblot 
25982082d9SJean-Jacques Hiblot #define PLL_REGM_MASK           0x001FFE00
26982082d9SJean-Jacques Hiblot #define PLL_REGM_SHIFT          9
27982082d9SJean-Jacques Hiblot #define PLL_REGM_F_MASK         0x0003FFFF
28982082d9SJean-Jacques Hiblot #define PLL_REGM_F_SHIFT        0
29982082d9SJean-Jacques Hiblot #define PLL_REGN_MASK           0x000001FE
30982082d9SJean-Jacques Hiblot #define PLL_REGN_SHIFT          1
31982082d9SJean-Jacques Hiblot #define PLL_SELFREQDCO_MASK     0x0000000E
32982082d9SJean-Jacques Hiblot #define PLL_SELFREQDCO_SHIFT    1
33982082d9SJean-Jacques Hiblot #define PLL_SD_MASK             0x0003FC00
34982082d9SJean-Jacques Hiblot #define PLL_SD_SHIFT            10
35982082d9SJean-Jacques Hiblot #define SET_PLL_GO              0x1
36982082d9SJean-Jacques Hiblot #define PLL_TICOPWDN            BIT(16)
37982082d9SJean-Jacques Hiblot #define PLL_LDOPWDN             BIT(15)
38982082d9SJean-Jacques Hiblot #define PLL_LOCK                0x2
39982082d9SJean-Jacques Hiblot #define PLL_IDLE                0x1
40982082d9SJean-Jacques Hiblot 
41982082d9SJean-Jacques Hiblot /* Software rest for the SATA PLL (in CTRL_CORE_SMA_SW_0 register)*/
42982082d9SJean-Jacques Hiblot #define SATA_PLL_SOFT_RESET (1<<18)
43982082d9SJean-Jacques Hiblot 
44982082d9SJean-Jacques Hiblot /* PHY POWER CONTROL Register */
45982082d9SJean-Jacques Hiblot #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK         0x003FC000
46982082d9SJean-Jacques Hiblot #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT        0xE
47982082d9SJean-Jacques Hiblot 
48982082d9SJean-Jacques Hiblot #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK        0xFFC00000
49982082d9SJean-Jacques Hiblot #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT       0x16
50982082d9SJean-Jacques Hiblot 
51982082d9SJean-Jacques Hiblot #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON       0x3
52982082d9SJean-Jacques Hiblot #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF      0x0
53982082d9SJean-Jacques Hiblot 
54982082d9SJean-Jacques Hiblot 
55982082d9SJean-Jacques Hiblot #define PLL_IDLE_TIME   100     /* in milliseconds */
56982082d9SJean-Jacques Hiblot #define PLL_LOCK_TIME   100     /* in milliseconds */
57982082d9SJean-Jacques Hiblot 
58982082d9SJean-Jacques Hiblot struct omap_pipe3 {
59982082d9SJean-Jacques Hiblot 	void __iomem		*pll_ctrl_base;
60982082d9SJean-Jacques Hiblot 	void __iomem		*power_reg;
61982082d9SJean-Jacques Hiblot 	void __iomem		*pll_reset_reg;
62982082d9SJean-Jacques Hiblot 	struct pipe3_dpll_map	*dpll_map;
63982082d9SJean-Jacques Hiblot };
64982082d9SJean-Jacques Hiblot 
65982082d9SJean-Jacques Hiblot 
66982082d9SJean-Jacques Hiblot struct pipe3_dpll_params {
67982082d9SJean-Jacques Hiblot 	u16     m;
68982082d9SJean-Jacques Hiblot 	u8      n;
69982082d9SJean-Jacques Hiblot 	u8      freq:3;
70982082d9SJean-Jacques Hiblot 	u8      sd;
71982082d9SJean-Jacques Hiblot 	u32     mf;
72982082d9SJean-Jacques Hiblot };
73982082d9SJean-Jacques Hiblot 
74982082d9SJean-Jacques Hiblot struct pipe3_dpll_map {
75982082d9SJean-Jacques Hiblot 	unsigned long rate;
76982082d9SJean-Jacques Hiblot 	struct pipe3_dpll_params params;
77982082d9SJean-Jacques Hiblot };
78982082d9SJean-Jacques Hiblot 
omap_pipe3_readl(void __iomem * addr,unsigned offset)79982082d9SJean-Jacques Hiblot static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
80982082d9SJean-Jacques Hiblot {
81982082d9SJean-Jacques Hiblot 	return readl(addr + offset);
82982082d9SJean-Jacques Hiblot }
83982082d9SJean-Jacques Hiblot 
omap_pipe3_writel(void __iomem * addr,unsigned offset,u32 data)84982082d9SJean-Jacques Hiblot static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset,
85982082d9SJean-Jacques Hiblot 		u32 data)
86982082d9SJean-Jacques Hiblot {
87982082d9SJean-Jacques Hiblot 	writel(data, addr + offset);
88982082d9SJean-Jacques Hiblot }
89982082d9SJean-Jacques Hiblot 
omap_pipe3_get_dpll_params(struct omap_pipe3 * pipe3)90982082d9SJean-Jacques Hiblot static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(struct omap_pipe3
91982082d9SJean-Jacques Hiblot 									*pipe3)
92982082d9SJean-Jacques Hiblot {
93982082d9SJean-Jacques Hiblot 	u32 rate;
94982082d9SJean-Jacques Hiblot 	struct pipe3_dpll_map *dpll_map = pipe3->dpll_map;
95982082d9SJean-Jacques Hiblot 
96982082d9SJean-Jacques Hiblot 	rate = get_sys_clk_freq();
97982082d9SJean-Jacques Hiblot 
98982082d9SJean-Jacques Hiblot 	for (; dpll_map->rate; dpll_map++) {
99982082d9SJean-Jacques Hiblot 		if (rate == dpll_map->rate)
100982082d9SJean-Jacques Hiblot 			return &dpll_map->params;
101982082d9SJean-Jacques Hiblot 	}
102982082d9SJean-Jacques Hiblot 
103982082d9SJean-Jacques Hiblot 	printf("%s: No DPLL configuration for %u Hz SYS CLK\n",
104982082d9SJean-Jacques Hiblot 	       __func__, rate);
105982082d9SJean-Jacques Hiblot 	return NULL;
106982082d9SJean-Jacques Hiblot }
107982082d9SJean-Jacques Hiblot 
omap_pipe3_wait_lock(struct omap_pipe3 * pipe3)108982082d9SJean-Jacques Hiblot static int omap_pipe3_wait_lock(struct omap_pipe3 *pipe3)
109982082d9SJean-Jacques Hiblot {
110982082d9SJean-Jacques Hiblot 	u32 val;
111982082d9SJean-Jacques Hiblot 	int timeout = PLL_LOCK_TIME;
112982082d9SJean-Jacques Hiblot 
113982082d9SJean-Jacques Hiblot 	do {
114982082d9SJean-Jacques Hiblot 		mdelay(1);
115982082d9SJean-Jacques Hiblot 		val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_STATUS);
116982082d9SJean-Jacques Hiblot 		if (val & PLL_LOCK)
117982082d9SJean-Jacques Hiblot 			break;
118982082d9SJean-Jacques Hiblot 	} while (--timeout);
119982082d9SJean-Jacques Hiblot 
120982082d9SJean-Jacques Hiblot 	if (!(val & PLL_LOCK)) {
121982082d9SJean-Jacques Hiblot 		printf("%s: DPLL failed to lock\n", __func__);
122982082d9SJean-Jacques Hiblot 		return -EBUSY;
123982082d9SJean-Jacques Hiblot 	}
124982082d9SJean-Jacques Hiblot 
125982082d9SJean-Jacques Hiblot 	return 0;
126982082d9SJean-Jacques Hiblot }
127982082d9SJean-Jacques Hiblot 
omap_pipe3_dpll_program(struct omap_pipe3 * pipe3)128982082d9SJean-Jacques Hiblot static int omap_pipe3_dpll_program(struct omap_pipe3 *pipe3)
129982082d9SJean-Jacques Hiblot {
130982082d9SJean-Jacques Hiblot 	u32                     val;
131982082d9SJean-Jacques Hiblot 	struct pipe3_dpll_params *dpll_params;
132982082d9SJean-Jacques Hiblot 
133982082d9SJean-Jacques Hiblot 	dpll_params = omap_pipe3_get_dpll_params(pipe3);
134982082d9SJean-Jacques Hiblot 	if (!dpll_params) {
135982082d9SJean-Jacques Hiblot 		printf("%s: Invalid DPLL parameters\n", __func__);
136982082d9SJean-Jacques Hiblot 		return -EINVAL;
137982082d9SJean-Jacques Hiblot 	}
138982082d9SJean-Jacques Hiblot 
139982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION1);
140982082d9SJean-Jacques Hiblot 	val &= ~PLL_REGN_MASK;
141982082d9SJean-Jacques Hiblot 	val |= dpll_params->n << PLL_REGN_SHIFT;
142982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val);
143982082d9SJean-Jacques Hiblot 
144982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2);
145982082d9SJean-Jacques Hiblot 	val &= ~PLL_SELFREQDCO_MASK;
146982082d9SJean-Jacques Hiblot 	val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
147982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val);
148982082d9SJean-Jacques Hiblot 
149982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION1);
150982082d9SJean-Jacques Hiblot 	val &= ~PLL_REGM_MASK;
151982082d9SJean-Jacques Hiblot 	val |= dpll_params->m << PLL_REGM_SHIFT;
152982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val);
153982082d9SJean-Jacques Hiblot 
154982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION4);
155982082d9SJean-Jacques Hiblot 	val &= ~PLL_REGM_F_MASK;
156982082d9SJean-Jacques Hiblot 	val |= dpll_params->mf << PLL_REGM_F_SHIFT;
157982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION4, val);
158982082d9SJean-Jacques Hiblot 
159982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION3);
160982082d9SJean-Jacques Hiblot 	val &= ~PLL_SD_MASK;
161982082d9SJean-Jacques Hiblot 	val |= dpll_params->sd << PLL_SD_SHIFT;
162982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION3, val);
163982082d9SJean-Jacques Hiblot 
164982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_GO, SET_PLL_GO);
165982082d9SJean-Jacques Hiblot 
166982082d9SJean-Jacques Hiblot 	return omap_pipe3_wait_lock(pipe3);
167982082d9SJean-Jacques Hiblot }
168982082d9SJean-Jacques Hiblot 
omap_control_pipe3_power(struct omap_pipe3 * pipe3,int on)169982082d9SJean-Jacques Hiblot static void omap_control_pipe3_power(struct omap_pipe3 *pipe3, int on)
170982082d9SJean-Jacques Hiblot {
171982082d9SJean-Jacques Hiblot 	u32 val, rate;
172982082d9SJean-Jacques Hiblot 
173982082d9SJean-Jacques Hiblot 	val = readl(pipe3->power_reg);
174982082d9SJean-Jacques Hiblot 
175982082d9SJean-Jacques Hiblot 	rate = get_sys_clk_freq();
176982082d9SJean-Jacques Hiblot 	rate = rate/1000000;
177982082d9SJean-Jacques Hiblot 
178982082d9SJean-Jacques Hiblot 	if (on) {
179982082d9SJean-Jacques Hiblot 		val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
180982082d9SJean-Jacques Hiblot 				OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
181982082d9SJean-Jacques Hiblot 		val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
182982082d9SJean-Jacques Hiblot 			OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
183982082d9SJean-Jacques Hiblot 		val |= rate <<
184982082d9SJean-Jacques Hiblot 			OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
185982082d9SJean-Jacques Hiblot 	} else {
186982082d9SJean-Jacques Hiblot 		val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
187982082d9SJean-Jacques Hiblot 		val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
188982082d9SJean-Jacques Hiblot 			OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
189982082d9SJean-Jacques Hiblot 	}
190982082d9SJean-Jacques Hiblot 
191982082d9SJean-Jacques Hiblot 	writel(val, pipe3->power_reg);
192982082d9SJean-Jacques Hiblot }
193982082d9SJean-Jacques Hiblot 
pipe3_init(struct phy * phy)194982082d9SJean-Jacques Hiblot static int pipe3_init(struct phy *phy)
195982082d9SJean-Jacques Hiblot {
196982082d9SJean-Jacques Hiblot 	int ret;
197982082d9SJean-Jacques Hiblot 	u32 val;
198982082d9SJean-Jacques Hiblot 	struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
199982082d9SJean-Jacques Hiblot 
200982082d9SJean-Jacques Hiblot 	/* Program the DPLL only if not locked */
201982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_STATUS);
202982082d9SJean-Jacques Hiblot 	if (!(val & PLL_LOCK)) {
203982082d9SJean-Jacques Hiblot 		ret = omap_pipe3_dpll_program(pipe3);
204982082d9SJean-Jacques Hiblot 		if (ret)
205982082d9SJean-Jacques Hiblot 			return ret;
206982082d9SJean-Jacques Hiblot 	} else {
207982082d9SJean-Jacques Hiblot 		/* else just bring it out of IDLE mode */
208982082d9SJean-Jacques Hiblot 		val = omap_pipe3_readl(pipe3->pll_ctrl_base,
209982082d9SJean-Jacques Hiblot 				       PLL_CONFIGURATION2);
210982082d9SJean-Jacques Hiblot 		if (val & PLL_IDLE) {
211982082d9SJean-Jacques Hiblot 			val &= ~PLL_IDLE;
212982082d9SJean-Jacques Hiblot 			omap_pipe3_writel(pipe3->pll_ctrl_base,
213982082d9SJean-Jacques Hiblot 					  PLL_CONFIGURATION2, val);
214982082d9SJean-Jacques Hiblot 			ret = omap_pipe3_wait_lock(pipe3);
215982082d9SJean-Jacques Hiblot 			if (ret)
216982082d9SJean-Jacques Hiblot 				return ret;
217982082d9SJean-Jacques Hiblot 		}
218982082d9SJean-Jacques Hiblot 	}
219982082d9SJean-Jacques Hiblot 	return 0;
220982082d9SJean-Jacques Hiblot }
221982082d9SJean-Jacques Hiblot 
pipe3_power_on(struct phy * phy)222982082d9SJean-Jacques Hiblot static int pipe3_power_on(struct phy *phy)
223982082d9SJean-Jacques Hiblot {
224982082d9SJean-Jacques Hiblot 	struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
225982082d9SJean-Jacques Hiblot 
226982082d9SJean-Jacques Hiblot 	/* Power up the PHY */
227982082d9SJean-Jacques Hiblot 	omap_control_pipe3_power(pipe3, 1);
228982082d9SJean-Jacques Hiblot 
229982082d9SJean-Jacques Hiblot 	return 0;
230982082d9SJean-Jacques Hiblot }
231982082d9SJean-Jacques Hiblot 
pipe3_power_off(struct phy * phy)232982082d9SJean-Jacques Hiblot static int pipe3_power_off(struct phy *phy)
233982082d9SJean-Jacques Hiblot {
234982082d9SJean-Jacques Hiblot 	struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
235982082d9SJean-Jacques Hiblot 
236982082d9SJean-Jacques Hiblot 	/* Power down the PHY */
237982082d9SJean-Jacques Hiblot 	omap_control_pipe3_power(pipe3, 0);
238982082d9SJean-Jacques Hiblot 
239982082d9SJean-Jacques Hiblot 	return 0;
240982082d9SJean-Jacques Hiblot }
241982082d9SJean-Jacques Hiblot 
pipe3_exit(struct phy * phy)242982082d9SJean-Jacques Hiblot static int pipe3_exit(struct phy *phy)
243982082d9SJean-Jacques Hiblot {
244982082d9SJean-Jacques Hiblot 	u32 val;
245982082d9SJean-Jacques Hiblot 	int timeout = PLL_IDLE_TIME;
246982082d9SJean-Jacques Hiblot 	struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
247982082d9SJean-Jacques Hiblot 
248982082d9SJean-Jacques Hiblot 	pipe3_power_off(phy);
249982082d9SJean-Jacques Hiblot 
250982082d9SJean-Jacques Hiblot 	/* Put DPLL in IDLE mode */
251982082d9SJean-Jacques Hiblot 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2);
252982082d9SJean-Jacques Hiblot 	val |= PLL_IDLE;
253982082d9SJean-Jacques Hiblot 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val);
254982082d9SJean-Jacques Hiblot 
255982082d9SJean-Jacques Hiblot 	/* wait for LDO and Oscillator to power down */
256982082d9SJean-Jacques Hiblot 	do {
257982082d9SJean-Jacques Hiblot 		mdelay(1);
258982082d9SJean-Jacques Hiblot 		val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_STATUS);
259982082d9SJean-Jacques Hiblot 		if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
260982082d9SJean-Jacques Hiblot 			break;
261982082d9SJean-Jacques Hiblot 	} while (--timeout);
262982082d9SJean-Jacques Hiblot 
263982082d9SJean-Jacques Hiblot 	if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
264*90aa625cSMasahiro Yamada 		pr_err("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n",
265982082d9SJean-Jacques Hiblot 		      __func__, val);
266982082d9SJean-Jacques Hiblot 		return -EBUSY;
267982082d9SJean-Jacques Hiblot 	}
268982082d9SJean-Jacques Hiblot 
269982082d9SJean-Jacques Hiblot 	val = readl(pipe3->pll_reset_reg);
270982082d9SJean-Jacques Hiblot 	writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
271982082d9SJean-Jacques Hiblot 	mdelay(1);
272982082d9SJean-Jacques Hiblot 	writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
273982082d9SJean-Jacques Hiblot 	return 0;
274982082d9SJean-Jacques Hiblot }
275982082d9SJean-Jacques Hiblot 
get_reg(struct udevice * dev,const char * name)276982082d9SJean-Jacques Hiblot static void *get_reg(struct udevice *dev, const char *name)
277982082d9SJean-Jacques Hiblot {
278982082d9SJean-Jacques Hiblot 	struct udevice *syscon;
279982082d9SJean-Jacques Hiblot 	struct regmap *regmap;
280982082d9SJean-Jacques Hiblot 	const fdt32_t *cell;
281982082d9SJean-Jacques Hiblot 	int len, err;
282982082d9SJean-Jacques Hiblot 	void *base;
283982082d9SJean-Jacques Hiblot 
284982082d9SJean-Jacques Hiblot 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
285982082d9SJean-Jacques Hiblot 					   name, &syscon);
286982082d9SJean-Jacques Hiblot 	if (err) {
287*90aa625cSMasahiro Yamada 		pr_err("unable to find syscon device for %s (%d)\n",
288982082d9SJean-Jacques Hiblot 		      name, err);
289982082d9SJean-Jacques Hiblot 		return NULL;
290982082d9SJean-Jacques Hiblot 	}
291982082d9SJean-Jacques Hiblot 
292982082d9SJean-Jacques Hiblot 	regmap = syscon_get_regmap(syscon);
293982082d9SJean-Jacques Hiblot 	if (IS_ERR(regmap)) {
294*90aa625cSMasahiro Yamada 		pr_err("unable to find regmap for %s (%ld)\n",
295982082d9SJean-Jacques Hiblot 		      name, PTR_ERR(regmap));
296982082d9SJean-Jacques Hiblot 		return NULL;
297982082d9SJean-Jacques Hiblot 	}
298982082d9SJean-Jacques Hiblot 
299da409cccSSimon Glass 	cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), name,
300982082d9SJean-Jacques Hiblot 			   &len);
301982082d9SJean-Jacques Hiblot 	if (len < 2*sizeof(fdt32_t)) {
302*90aa625cSMasahiro Yamada 		pr_err("offset not available for %s\n", name);
303982082d9SJean-Jacques Hiblot 		return NULL;
304982082d9SJean-Jacques Hiblot 	}
305982082d9SJean-Jacques Hiblot 
306982082d9SJean-Jacques Hiblot 	base = regmap_get_range(regmap, 0);
307982082d9SJean-Jacques Hiblot 	if (!base)
308982082d9SJean-Jacques Hiblot 		return NULL;
309982082d9SJean-Jacques Hiblot 
310982082d9SJean-Jacques Hiblot 	return fdtdec_get_number(cell + 1, 1) + base;
311982082d9SJean-Jacques Hiblot }
312982082d9SJean-Jacques Hiblot 
pipe3_phy_probe(struct udevice * dev)313982082d9SJean-Jacques Hiblot static int pipe3_phy_probe(struct udevice *dev)
314982082d9SJean-Jacques Hiblot {
315982082d9SJean-Jacques Hiblot 	fdt_addr_t addr;
316982082d9SJean-Jacques Hiblot 	fdt_size_t sz;
317982082d9SJean-Jacques Hiblot 	struct omap_pipe3 *pipe3 = dev_get_priv(dev);
318982082d9SJean-Jacques Hiblot 
319a821c4afSSimon Glass 	addr = devfdt_get_addr_size_index(dev, 2, &sz);
320982082d9SJean-Jacques Hiblot 	if (addr == FDT_ADDR_T_NONE) {
321*90aa625cSMasahiro Yamada 		pr_err("missing pll ctrl address\n");
322982082d9SJean-Jacques Hiblot 		return -EINVAL;
323982082d9SJean-Jacques Hiblot 	}
324982082d9SJean-Jacques Hiblot 
325982082d9SJean-Jacques Hiblot 	pipe3->pll_ctrl_base = map_physmem(addr, sz, MAP_NOCACHE);
326982082d9SJean-Jacques Hiblot 	if (!pipe3->pll_ctrl_base) {
327*90aa625cSMasahiro Yamada 		pr_err("unable to remap pll ctrl\n");
328982082d9SJean-Jacques Hiblot 		return -EINVAL;
329982082d9SJean-Jacques Hiblot 	}
330982082d9SJean-Jacques Hiblot 
331982082d9SJean-Jacques Hiblot 	pipe3->power_reg = get_reg(dev, "syscon-phy-power");
332982082d9SJean-Jacques Hiblot 	if (!pipe3->power_reg)
333982082d9SJean-Jacques Hiblot 		return -EINVAL;
334982082d9SJean-Jacques Hiblot 
335982082d9SJean-Jacques Hiblot 	pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
336982082d9SJean-Jacques Hiblot 	if (!pipe3->pll_reset_reg)
337982082d9SJean-Jacques Hiblot 		return -EINVAL;
338982082d9SJean-Jacques Hiblot 
339982082d9SJean-Jacques Hiblot 	pipe3->dpll_map = (struct pipe3_dpll_map *)dev_get_driver_data(dev);
340982082d9SJean-Jacques Hiblot 
341982082d9SJean-Jacques Hiblot 	return 0;
342982082d9SJean-Jacques Hiblot }
343982082d9SJean-Jacques Hiblot 
344982082d9SJean-Jacques Hiblot static struct pipe3_dpll_map dpll_map_sata[] = {
345982082d9SJean-Jacques Hiblot 	{12000000, {1000, 7, 4, 6, 0} },        /* 12 MHz */
346982082d9SJean-Jacques Hiblot 	{16800000, {714, 7, 4, 6, 0} },         /* 16.8 MHz */
347982082d9SJean-Jacques Hiblot 	{19200000, {625, 7, 4, 6, 0} },         /* 19.2 MHz */
348982082d9SJean-Jacques Hiblot 	{20000000, {600, 7, 4, 6, 0} },         /* 20 MHz */
349982082d9SJean-Jacques Hiblot 	{26000000, {461, 7, 4, 6, 0} },         /* 26 MHz */
350982082d9SJean-Jacques Hiblot 	{38400000, {312, 7, 4, 6, 0} },         /* 38.4 MHz */
351982082d9SJean-Jacques Hiblot 	{ },                                    /* Terminator */
352982082d9SJean-Jacques Hiblot };
353982082d9SJean-Jacques Hiblot 
354982082d9SJean-Jacques Hiblot static const struct udevice_id pipe3_phy_ids[] = {
355982082d9SJean-Jacques Hiblot 	{ .compatible = "ti,phy-pipe3-sata", .data = (ulong)&dpll_map_sata },
356982082d9SJean-Jacques Hiblot 	{ }
357982082d9SJean-Jacques Hiblot };
358982082d9SJean-Jacques Hiblot 
359982082d9SJean-Jacques Hiblot static struct phy_ops pipe3_phy_ops = {
360982082d9SJean-Jacques Hiblot 	.init = pipe3_init,
361982082d9SJean-Jacques Hiblot 	.power_on = pipe3_power_on,
362982082d9SJean-Jacques Hiblot 	.power_off = pipe3_power_off,
363982082d9SJean-Jacques Hiblot 	.exit = pipe3_exit,
364982082d9SJean-Jacques Hiblot };
365982082d9SJean-Jacques Hiblot 
366982082d9SJean-Jacques Hiblot U_BOOT_DRIVER(pipe3_phy) = {
367982082d9SJean-Jacques Hiblot 	.name	= "pipe3_phy",
368982082d9SJean-Jacques Hiblot 	.id	= UCLASS_PHY,
369982082d9SJean-Jacques Hiblot 	.of_match = pipe3_phy_ids,
370982082d9SJean-Jacques Hiblot 	.ops = &pipe3_phy_ops,
371982082d9SJean-Jacques Hiblot 	.probe = pipe3_phy_probe,
372982082d9SJean-Jacques Hiblot 	.priv_auto_alloc_size = sizeof(struct omap_pipe3),
373982082d9SJean-Jacques Hiblot };
374