]> git.sur5r.net Git - u-boot/blob - drivers/phy/ti-pipe3-phy.c
dm: spi: Update sandbox SPI emulation driver to use ofnode
[u-boot] / 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;
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         val = readl(pipe3->pll_reset_reg);
269         writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
270         mdelay(1);
271         writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
272         return 0;
273 }
274
275 static void *get_reg(struct udevice *dev, const char *name)
276 {
277         struct udevice *syscon;
278         struct regmap *regmap;
279         const fdt32_t *cell;
280         int len, err;
281         void *base;
282
283         err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
284                                            name, &syscon);
285         if (err) {
286                 pr_err("unable to find syscon device for %s (%d)\n",
287                       name, err);
288                 return NULL;
289         }
290
291         regmap = syscon_get_regmap(syscon);
292         if (IS_ERR(regmap)) {
293                 pr_err("unable to find regmap for %s (%ld)\n",
294                       name, PTR_ERR(regmap));
295                 return NULL;
296         }
297
298         cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), name,
299                            &len);
300         if (len < 2*sizeof(fdt32_t)) {
301                 pr_err("offset not available for %s\n", name);
302                 return NULL;
303         }
304
305         base = regmap_get_range(regmap, 0);
306         if (!base)
307                 return NULL;
308
309         return fdtdec_get_number(cell + 1, 1) + base;
310 }
311
312 static int pipe3_phy_probe(struct udevice *dev)
313 {
314         fdt_addr_t addr;
315         fdt_size_t sz;
316         struct omap_pipe3 *pipe3 = dev_get_priv(dev);
317
318         addr = devfdt_get_addr_size_index(dev, 2, &sz);
319         if (addr == FDT_ADDR_T_NONE) {
320                 pr_err("missing pll ctrl address\n");
321                 return -EINVAL;
322         }
323
324         pipe3->pll_ctrl_base = map_physmem(addr, sz, MAP_NOCACHE);
325         if (!pipe3->pll_ctrl_base) {
326                 pr_err("unable to remap pll ctrl\n");
327                 return -EINVAL;
328         }
329
330         pipe3->power_reg = get_reg(dev, "syscon-phy-power");
331         if (!pipe3->power_reg)
332                 return -EINVAL;
333
334         pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
335         if (!pipe3->pll_reset_reg)
336                 return -EINVAL;
337
338         pipe3->dpll_map = (struct pipe3_dpll_map *)dev_get_driver_data(dev);
339
340         return 0;
341 }
342
343 static struct pipe3_dpll_map dpll_map_sata[] = {
344         {12000000, {1000, 7, 4, 6, 0} },        /* 12 MHz */
345         {16800000, {714, 7, 4, 6, 0} },         /* 16.8 MHz */
346         {19200000, {625, 7, 4, 6, 0} },         /* 19.2 MHz */
347         {20000000, {600, 7, 4, 6, 0} },         /* 20 MHz */
348         {26000000, {461, 7, 4, 6, 0} },         /* 26 MHz */
349         {38400000, {312, 7, 4, 6, 0} },         /* 38.4 MHz */
350         { },                                    /* Terminator */
351 };
352
353 static const struct udevice_id pipe3_phy_ids[] = {
354         { .compatible = "ti,phy-pipe3-sata", .data = (ulong)&dpll_map_sata },
355         { }
356 };
357
358 static struct phy_ops pipe3_phy_ops = {
359         .init = pipe3_init,
360         .power_on = pipe3_power_on,
361         .power_off = pipe3_power_off,
362         .exit = pipe3_exit,
363 };
364
365 U_BOOT_DRIVER(pipe3_phy) = {
366         .name   = "pipe3_phy",
367         .id     = UCLASS_PHY,
368         .of_match = pipe3_phy_ids,
369         .ops = &pipe3_phy_ops,
370         .probe = pipe3_phy_probe,
371         .priv_auto_alloc_size = sizeof(struct omap_pipe3),
372 };