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