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