Merge branch 'master' of git://git.denx.de/u-boot-socfpga
[oweals/u-boot.git] / drivers / phy / ti-pipe3-phy.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
4  * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <dm/device.h>
10 #include <generic-phy.h>
11 #include <asm/io.h>
12 #include <asm/arch/sys_proto.h>
13 #include <syscon.h>
14 #include <regmap.h>
15
16 /* PLLCTRL Registers */
17 #define PLL_STATUS              0x00000004
18 #define PLL_GO                  0x00000008
19 #define PLL_CONFIGURATION1      0x0000000C
20 #define PLL_CONFIGURATION2      0x00000010
21 #define PLL_CONFIGURATION3      0x00000014
22 #define PLL_CONFIGURATION4      0x00000020
23
24 #define PLL_REGM_MASK           0x001FFE00
25 #define PLL_REGM_SHIFT          9
26 #define PLL_REGM_F_MASK         0x0003FFFF
27 #define PLL_REGM_F_SHIFT        0
28 #define PLL_REGN_MASK           0x000001FE
29 #define PLL_REGN_SHIFT          1
30 #define PLL_SELFREQDCO_MASK     0x0000000E
31 #define PLL_SELFREQDCO_SHIFT    1
32 #define PLL_SD_MASK             0x0003FC00
33 #define PLL_SD_SHIFT            10
34 #define SET_PLL_GO              0x1
35 #define PLL_TICOPWDN            BIT(16)
36 #define PLL_LDOPWDN             BIT(15)
37 #define PLL_LOCK                0x2
38 #define PLL_IDLE                0x1
39
40 /* Software rest for the SATA PLL (in CTRL_CORE_SMA_SW_0 register)*/
41 #define SATA_PLL_SOFT_RESET (1<<18)
42
43 /* PHY POWER CONTROL Register */
44 #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK         0x003FC000
45 #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT        0xE
46
47 #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK        0xFFC00000
48 #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT       0x16
49
50 #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON       0x3
51 #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF      0x0
52
53
54 #define PLL_IDLE_TIME   100     /* in milliseconds */
55 #define PLL_LOCK_TIME   100     /* in milliseconds */
56
57 struct omap_pipe3 {
58         void __iomem            *pll_ctrl_base;
59         void __iomem            *power_reg;
60         void __iomem            *pll_reset_reg;
61         struct pipe3_dpll_map   *dpll_map;
62 };
63
64
65 struct pipe3_dpll_params {
66         u16     m;
67         u8      n;
68         u8      freq:3;
69         u8      sd;
70         u32     mf;
71 };
72
73 struct pipe3_dpll_map {
74         unsigned long rate;
75         struct pipe3_dpll_params params;
76 };
77
78 static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
79 {
80         return readl(addr + offset);
81 }
82
83 static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset,
84                 u32 data)
85 {
86         writel(data, addr + offset);
87 }
88
89 static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(struct omap_pipe3
90                                                                         *pipe3)
91 {
92         u32 rate;
93         struct pipe3_dpll_map *dpll_map = pipe3->dpll_map;
94
95         rate = get_sys_clk_freq();
96
97         for (; dpll_map->rate; dpll_map++) {
98                 if (rate == dpll_map->rate)
99                         return &dpll_map->params;
100         }
101
102         printf("%s: No DPLL configuration for %u Hz SYS CLK\n",
103                __func__, rate);
104         return NULL;
105 }
106
107 static int omap_pipe3_wait_lock(struct omap_pipe3 *pipe3)
108 {
109         u32 val;
110         int timeout = PLL_LOCK_TIME;
111
112         do {
113                 mdelay(1);
114                 val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_STATUS);
115                 if (val & PLL_LOCK)
116                         break;
117         } while (--timeout);
118
119         if (!(val & PLL_LOCK)) {
120                 printf("%s: DPLL failed to lock\n", __func__);
121                 return -EBUSY;
122         }
123
124         return 0;
125 }
126
127 static int omap_pipe3_dpll_program(struct omap_pipe3 *pipe3)
128 {
129         u32                     val;
130         struct pipe3_dpll_params *dpll_params;
131
132         dpll_params = omap_pipe3_get_dpll_params(pipe3);
133         if (!dpll_params) {
134                 printf("%s: Invalid DPLL parameters\n", __func__);
135                 return -EINVAL;
136         }
137
138         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION1);
139         val &= ~PLL_REGN_MASK;
140         val |= dpll_params->n << PLL_REGN_SHIFT;
141         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val);
142
143         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2);
144         val &= ~(PLL_SELFREQDCO_MASK | PLL_IDLE);
145         val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
146         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val);
147
148         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION1);
149         val &= ~PLL_REGM_MASK;
150         val |= dpll_params->m << PLL_REGM_SHIFT;
151         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val);
152
153         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION4);
154         val &= ~PLL_REGM_F_MASK;
155         val |= dpll_params->mf << PLL_REGM_F_SHIFT;
156         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION4, val);
157
158         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION3);
159         val &= ~PLL_SD_MASK;
160         val |= dpll_params->sd << PLL_SD_SHIFT;
161         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION3, val);
162
163         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_GO, SET_PLL_GO);
164
165         return omap_pipe3_wait_lock(pipe3);
166 }
167
168 static void omap_control_pipe3_power(struct omap_pipe3 *pipe3, int on)
169 {
170         u32 val, rate;
171
172         val = readl(pipe3->power_reg);
173
174         rate = get_sys_clk_freq();
175         rate = rate/1000000;
176
177         if (on) {
178                 val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
179                                 OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
180                 val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
181                         OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
182                 val |= rate <<
183                         OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
184         } else {
185                 val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
186                 val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
187                         OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
188         }
189
190         writel(val, pipe3->power_reg);
191 }
192
193 static int pipe3_init(struct phy *phy)
194 {
195         int ret;
196         u32 val;
197         struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
198
199         /* Program the DPLL only if not locked */
200         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_STATUS);
201         if (!(val & PLL_LOCK)) {
202                 ret = omap_pipe3_dpll_program(pipe3);
203                 if (ret)
204                         return ret;
205         } else {
206                 /* else just bring it out of IDLE mode */
207                 val = omap_pipe3_readl(pipe3->pll_ctrl_base,
208                                        PLL_CONFIGURATION2);
209                 if (val & PLL_IDLE) {
210                         val &= ~PLL_IDLE;
211                         omap_pipe3_writel(pipe3->pll_ctrl_base,
212                                           PLL_CONFIGURATION2, val);
213                         ret = omap_pipe3_wait_lock(pipe3);
214                         if (ret)
215                                 return ret;
216                 }
217         }
218         return 0;
219 }
220
221 static int pipe3_power_on(struct phy *phy)
222 {
223         struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
224
225         /* Power up the PHY */
226         omap_control_pipe3_power(pipe3, 1);
227
228         return 0;
229 }
230
231 static int pipe3_power_off(struct phy *phy)
232 {
233         struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
234
235         /* Power down the PHY */
236         omap_control_pipe3_power(pipe3, 0);
237
238         return 0;
239 }
240
241 static int pipe3_exit(struct phy *phy)
242 {
243         u32 val;
244         int timeout = PLL_IDLE_TIME;
245         struct omap_pipe3 *pipe3 = dev_get_priv(phy->dev);
246
247         pipe3_power_off(phy);
248
249         /* Put DPLL in IDLE mode */
250         val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2);
251         val |= PLL_IDLE;
252         omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val);
253
254         /* wait for LDO and Oscillator to power down */
255         do {
256                 mdelay(1);
257                 val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_STATUS);
258                 if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
259                         break;
260         } while (--timeout);
261
262         if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
263                 pr_err("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n",
264                       __func__, val);
265                 return -EBUSY;
266         }
267
268         if (pipe3->pll_reset_reg) {
269                 val = readl(pipe3->pll_reset_reg);
270                 writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
271                 mdelay(1);
272                 writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
273         }
274
275         return 0;
276 }
277
278 static void *get_reg(struct udevice *dev, const char *name)
279 {
280         struct udevice *syscon;
281         struct regmap *regmap;
282         const fdt32_t *cell;
283         int len, err;
284         void *base;
285
286         err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
287                                            name, &syscon);
288         if (err) {
289                 pr_err("unable to find syscon device for %s (%d)\n",
290                       name, err);
291                 return NULL;
292         }
293
294         regmap = syscon_get_regmap(syscon);
295         if (IS_ERR(regmap)) {
296                 pr_err("unable to find regmap for %s (%ld)\n",
297                       name, PTR_ERR(regmap));
298                 return NULL;
299         }
300
301         cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), name,
302                            &len);
303         if (len < 2*sizeof(fdt32_t)) {
304                 pr_err("offset not available for %s\n", name);
305                 return NULL;
306         }
307
308         base = regmap_get_range(regmap, 0);
309         if (!base)
310                 return NULL;
311
312         return fdtdec_get_number(cell + 1, 1) + base;
313 }
314
315 static int pipe3_phy_probe(struct udevice *dev)
316 {
317         fdt_addr_t addr;
318         fdt_size_t sz;
319         struct omap_pipe3 *pipe3 = dev_get_priv(dev);
320
321         addr = devfdt_get_addr_size_index(dev, 2, &sz);
322         if (addr == FDT_ADDR_T_NONE) {
323                 pr_err("missing pll ctrl address\n");
324                 return -EINVAL;
325         }
326
327         pipe3->pll_ctrl_base = map_physmem(addr, sz, MAP_NOCACHE);
328         if (!pipe3->pll_ctrl_base) {
329                 pr_err("unable to remap pll ctrl\n");
330                 return -EINVAL;
331         }
332
333         pipe3->power_reg = get_reg(dev, "syscon-phy-power");
334         if (!pipe3->power_reg)
335                 return -EINVAL;
336
337         if (device_is_compatible(dev, "ti,phy-pipe3-sata")) {
338                 pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
339                 if (!pipe3->pll_reset_reg)
340                         return -EINVAL;
341         }
342
343         pipe3->dpll_map = (struct pipe3_dpll_map *)dev_get_driver_data(dev);
344
345         return 0;
346 }
347
348 static struct pipe3_dpll_map dpll_map_sata[] = {
349         {12000000, {1000, 7, 4, 6, 0} },        /* 12 MHz */
350         {16800000, {714, 7, 4, 6, 0} },         /* 16.8 MHz */
351         {19200000, {625, 7, 4, 6, 0} },         /* 19.2 MHz */
352         {20000000, {600, 7, 4, 6, 0} },         /* 20 MHz */
353         {26000000, {461, 7, 4, 6, 0} },         /* 26 MHz */
354         {38400000, {312, 7, 4, 6, 0} },         /* 38.4 MHz */
355         { },                                    /* Terminator */
356 };
357
358 static struct pipe3_dpll_map dpll_map_usb[] = {
359         {12000000, {1250, 5, 4, 20, 0} },       /* 12 MHz */
360         {16800000, {3125, 20, 4, 20, 0} },      /* 16.8 MHz */
361         {19200000, {1172, 8, 4, 20, 65537} },   /* 19.2 MHz */
362         {20000000, {1000, 7, 4, 10, 0} },       /* 20 MHz */
363         {26000000, {1250, 12, 4, 20, 0} },      /* 26 MHz */
364         {38400000, {3125, 47, 4, 20, 92843} },  /* 38.4 MHz */
365         { },                                    /* Terminator */
366 };
367
368 static const struct udevice_id pipe3_phy_ids[] = {
369         { .compatible = "ti,phy-pipe3-sata", .data = (ulong)&dpll_map_sata },
370         { .compatible = "ti,omap-usb3", .data = (ulong)&dpll_map_usb},
371         { }
372 };
373
374 static struct phy_ops pipe3_phy_ops = {
375         .init = pipe3_init,
376         .power_on = pipe3_power_on,
377         .power_off = pipe3_power_off,
378         .exit = pipe3_exit,
379 };
380
381 U_BOOT_DRIVER(pipe3_phy) = {
382         .name   = "pipe3_phy",
383         .id     = UCLASS_PHY,
384         .of_match = pipe3_phy_ids,
385         .ops = &pipe3_phy_ops,
386         .probe = pipe3_phy_probe,
387         .priv_auto_alloc_size = sizeof(struct omap_pipe3),
388 };