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 }; 373