Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.15-rc2 328 lines 9.2 kB view raw
1/* 2 * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support 3 * 4 * Copyright (C) 2013 Samsung Electronics Co., Ltd. 5 * Author: Kamil Debski <k.debski@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12#include <linux/delay.h> 13#include <linux/io.h> 14#include <linux/phy/phy.h> 15#include <linux/regmap.h> 16#include "phy-samsung-usb2.h" 17 18/* Exynos USB PHY registers */ 19 20/* PHY power control */ 21#define EXYNOS_4x12_UPHYPWR 0x0 22 23#define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND BIT(0) 24#define EXYNOS_4x12_UPHYPWR_PHY0_PWR BIT(3) 25#define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR BIT(4) 26#define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP BIT(5) 27#define EXYNOS_4x12_UPHYPWR_PHY0 ( \ 28 EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \ 29 EXYNOS_4x12_UPHYPWR_PHY0_PWR | \ 30 EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \ 31 EXYNOS_4x12_UPHYPWR_PHY0_SLEEP) 32 33#define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND BIT(6) 34#define EXYNOS_4x12_UPHYPWR_PHY1_PWR BIT(7) 35#define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP BIT(8) 36#define EXYNOS_4x12_UPHYPWR_PHY1 ( \ 37 EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \ 38 EXYNOS_4x12_UPHYPWR_PHY1_PWR | \ 39 EXYNOS_4x12_UPHYPWR_PHY1_SLEEP) 40 41#define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND BIT(9) 42#define EXYNOS_4x12_UPHYPWR_HSIC0_PWR BIT(10) 43#define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP BIT(11) 44#define EXYNOS_4x12_UPHYPWR_HSIC0 ( \ 45 EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \ 46 EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \ 47 EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP) 48 49#define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND BIT(12) 50#define EXYNOS_4x12_UPHYPWR_HSIC1_PWR BIT(13) 51#define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP BIT(14) 52#define EXYNOS_4x12_UPHYPWR_HSIC1 ( \ 53 EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \ 54 EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \ 55 EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP) 56 57/* PHY clock control */ 58#define EXYNOS_4x12_UPHYCLK 0x4 59 60#define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK (0x7 << 0) 61#define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET 0 62#define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6 (0x0 << 0) 63#define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ (0x1 << 0) 64#define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0) 65#define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2 (0x3 << 0) 66#define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ (0x4 << 0) 67#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0) 68#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0) 69 70#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3) 71#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4) 72#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7) 73 74#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK (0x7f << 10) 75#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET 10 76#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ (0x24 << 10) 77#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ (0x1c << 10) 78#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ (0x1a << 10) 79#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10) 80#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ (0x14 << 10) 81 82/* PHY reset control */ 83#define EXYNOS_4x12_UPHYRST 0x8 84 85#define EXYNOS_4x12_URSTCON_PHY0 BIT(0) 86#define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1) 87#define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2) 88#define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3) 89#define EXYNOS_4x12_URSTCON_PHY1 BIT(4) 90#define EXYNOS_4x12_URSTCON_HSIC0 BIT(5) 91#define EXYNOS_4x12_URSTCON_HSIC1 BIT(6) 92#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7) 93#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8) 94#define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9) 95#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(10) 96 97/* Isolation, configured in the power management unit */ 98#define EXYNOS_4x12_USB_ISOL_OFFSET 0x704 99#define EXYNOS_4x12_USB_ISOL_OTG BIT(0) 100#define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET 0x708 101#define EXYNOS_4x12_USB_ISOL_HSIC0 BIT(0) 102#define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET 0x70c 103#define EXYNOS_4x12_USB_ISOL_HSIC1 BIT(0) 104 105/* Mode switching SUB Device <-> Host */ 106#define EXYNOS_4x12_MODE_SWITCH_OFFSET 0x21c 107#define EXYNOS_4x12_MODE_SWITCH_MASK 1 108#define EXYNOS_4x12_MODE_SWITCH_DEVICE 0 109#define EXYNOS_4x12_MODE_SWITCH_HOST 1 110 111enum exynos4x12_phy_id { 112 EXYNOS4x12_DEVICE, 113 EXYNOS4x12_HOST, 114 EXYNOS4x12_HSIC0, 115 EXYNOS4x12_HSIC1, 116 EXYNOS4x12_NUM_PHYS, 117}; 118 119/* 120 * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that 121 * can be written to the phy register. 122 */ 123static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg) 124{ 125 /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */ 126 127 switch (rate) { 128 case 9600 * KHZ: 129 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6; 130 break; 131 case 10 * MHZ: 132 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ; 133 break; 134 case 12 * MHZ: 135 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ; 136 break; 137 case 19200 * KHZ: 138 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2; 139 break; 140 case 20 * MHZ: 141 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ; 142 break; 143 case 24 * MHZ: 144 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ; 145 break; 146 case 50 * MHZ: 147 *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ; 148 break; 149 default: 150 return -EINVAL; 151 } 152 153 return 0; 154} 155 156static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on) 157{ 158 struct samsung_usb2_phy_driver *drv = inst->drv; 159 u32 offset; 160 u32 mask; 161 162 switch (inst->cfg->id) { 163 case EXYNOS4x12_DEVICE: 164 case EXYNOS4x12_HOST: 165 offset = EXYNOS_4x12_USB_ISOL_OFFSET; 166 mask = EXYNOS_4x12_USB_ISOL_OTG; 167 break; 168 case EXYNOS4x12_HSIC0: 169 offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET; 170 mask = EXYNOS_4x12_USB_ISOL_HSIC0; 171 break; 172 case EXYNOS4x12_HSIC1: 173 offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET; 174 mask = EXYNOS_4x12_USB_ISOL_HSIC1; 175 break; 176 default: 177 return; 178 }; 179 180 regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); 181} 182 183static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst) 184{ 185 struct samsung_usb2_phy_driver *drv = inst->drv; 186 u32 clk; 187 188 clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK); 189 clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK; 190 clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET; 191 writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK); 192} 193 194static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) 195{ 196 struct samsung_usb2_phy_driver *drv = inst->drv; 197 u32 rstbits = 0; 198 u32 phypwr = 0; 199 u32 rst; 200 u32 pwr; 201 u32 mode = 0; 202 u32 switch_mode = 0; 203 204 switch (inst->cfg->id) { 205 case EXYNOS4x12_DEVICE: 206 phypwr = EXYNOS_4x12_UPHYPWR_PHY0; 207 rstbits = EXYNOS_4x12_URSTCON_PHY0; 208 mode = EXYNOS_4x12_MODE_SWITCH_DEVICE; 209 switch_mode = 1; 210 break; 211 case EXYNOS4x12_HOST: 212 phypwr = EXYNOS_4x12_UPHYPWR_PHY1; 213 rstbits = EXYNOS_4x12_URSTCON_HOST_PHY; 214 mode = EXYNOS_4x12_MODE_SWITCH_HOST; 215 switch_mode = 1; 216 break; 217 case EXYNOS4x12_HSIC0: 218 phypwr = EXYNOS_4x12_UPHYPWR_HSIC0; 219 rstbits = EXYNOS_4x12_URSTCON_HSIC1 | 220 EXYNOS_4x12_URSTCON_HOST_LINK_P0 | 221 EXYNOS_4x12_URSTCON_HOST_PHY; 222 break; 223 case EXYNOS4x12_HSIC1: 224 phypwr = EXYNOS_4x12_UPHYPWR_HSIC1; 225 rstbits = EXYNOS_4x12_URSTCON_HSIC1 | 226 EXYNOS_4x12_URSTCON_HOST_LINK_P1; 227 break; 228 }; 229 230 if (on) { 231 if (switch_mode) 232 regmap_update_bits(drv->reg_sys, 233 EXYNOS_4x12_MODE_SWITCH_OFFSET, 234 EXYNOS_4x12_MODE_SWITCH_MASK, mode); 235 236 pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); 237 pwr &= ~phypwr; 238 writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR); 239 240 rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST); 241 rst |= rstbits; 242 writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST); 243 udelay(10); 244 rst &= ~rstbits; 245 writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST); 246 /* The following delay is necessary for the reset sequence to be 247 * completed */ 248 udelay(80); 249 } else { 250 pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); 251 pwr |= phypwr; 252 writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR); 253 } 254} 255 256static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst) 257{ 258 struct samsung_usb2_phy_driver *drv = inst->drv; 259 260 inst->enabled = 1; 261 exynos4x12_setup_clk(inst); 262 exynos4x12_phy_pwr(inst, 1); 263 exynos4x12_isol(inst, 0); 264 265 /* Power on the device, as it is necessary for HSIC to work */ 266 if (inst->cfg->id == EXYNOS4x12_HSIC0) { 267 struct samsung_usb2_phy_instance *device = 268 &drv->instances[EXYNOS4x12_DEVICE]; 269 exynos4x12_phy_pwr(device, 1); 270 exynos4x12_isol(device, 0); 271 } 272 273 return 0; 274} 275 276static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst) 277{ 278 struct samsung_usb2_phy_driver *drv = inst->drv; 279 struct samsung_usb2_phy_instance *device = 280 &drv->instances[EXYNOS4x12_DEVICE]; 281 282 inst->enabled = 0; 283 exynos4x12_isol(inst, 1); 284 exynos4x12_phy_pwr(inst, 0); 285 286 if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) { 287 exynos4x12_isol(device, 1); 288 exynos4x12_phy_pwr(device, 0); 289 } 290 291 return 0; 292} 293 294 295static const struct samsung_usb2_common_phy exynos4x12_phys[] = { 296 { 297 .label = "device", 298 .id = EXYNOS4x12_DEVICE, 299 .power_on = exynos4x12_power_on, 300 .power_off = exynos4x12_power_off, 301 }, 302 { 303 .label = "host", 304 .id = EXYNOS4x12_HOST, 305 .power_on = exynos4x12_power_on, 306 .power_off = exynos4x12_power_off, 307 }, 308 { 309 .label = "hsic0", 310 .id = EXYNOS4x12_HSIC0, 311 .power_on = exynos4x12_power_on, 312 .power_off = exynos4x12_power_off, 313 }, 314 { 315 .label = "hsic1", 316 .id = EXYNOS4x12_HSIC1, 317 .power_on = exynos4x12_power_on, 318 .power_off = exynos4x12_power_off, 319 }, 320 {}, 321}; 322 323const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = { 324 .has_mode_switch = 1, 325 .num_phys = EXYNOS4x12_NUM_PHYS, 326 .phys = exynos4x12_phys, 327 .rate_to_clk = exynos4x12_rate_to_clk, 328};