diff options
| -rw-r--r-- | Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt | 733 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt | 6 | ||||
| -rw-r--r-- | Documentation/phy.txt | 16 | ||||
| -rw-r--r-- | drivers/clk/tegra/clk-tegra210.c | 58 | ||||
| -rw-r--r-- | drivers/phy/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/phy/Makefile | 2 | ||||
| -rw-r--r-- | drivers/phy/phy-core.c | 50 | ||||
| -rw-r--r-- | drivers/phy/tegra/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/phy/tegra/Makefile | 6 | ||||
| -rw-r--r-- | drivers/phy/tegra/xusb-tegra124.c | 1752 | ||||
| -rw-r--r-- | drivers/phy/tegra/xusb-tegra210.c | 2045 | ||||
| -rw-r--r-- | drivers/phy/tegra/xusb.c | 1021 | ||||
| -rw-r--r-- | drivers/phy/tegra/xusb.h | 421 | ||||
| -rw-r--r-- | drivers/pinctrl/tegra/pinctrl-tegra-xusb.c | 20 | ||||
| -rw-r--r-- | include/linux/clk/tegra.h | 5 | ||||
| -rw-r--r-- | include/linux/phy/phy.h | 31 | ||||
| -rw-r--r-- | include/linux/phy/tegra/xusb.h | 30 | ||||
| -rw-r--r-- | include/soc/tegra/fuse.h | 1 |
18 files changed, 6173 insertions, 34 deletions
diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt new file mode 100644 index 000000000000..0bf1ae243552 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt | |||
| @@ -0,0 +1,733 @@ | |||
| 1 | Device tree binding for NVIDIA Tegra XUSB pad controller | ||
| 2 | ======================================================== | ||
| 3 | |||
| 4 | The Tegra XUSB pad controller manages a set of I/O lanes (with differential | ||
| 5 | signals) which connect directly to pins/pads on the SoC package. Each lane | ||
| 6 | is controlled by a HW block referred to as a "pad" in the Tegra hardware | ||
| 7 | documentation. Each such "pad" may control either one or multiple lanes, | ||
| 8 | and thus contains any logic common to all its lanes. Each lane can be | ||
| 9 | separately configured and powered up. | ||
| 10 | |||
| 11 | Some of the lanes are high-speed lanes, which can be used for PCIe, SATA or | ||
| 12 | super-speed USB. Other lanes are for various types of low-speed, full-speed | ||
| 13 | or high-speed USB (such as UTMI, ULPI and HSIC). The XUSB pad controller | ||
| 14 | contains a software-configurable mux that sits between the I/O controller | ||
| 15 | ports (e.g. PCIe) and the lanes. | ||
| 16 | |||
| 17 | In addition to per-lane configuration, USB 3.0 ports may require additional | ||
| 18 | settings on a per-board basis. | ||
| 19 | |||
| 20 | Pads will be represented as children of the top-level XUSB pad controller | ||
| 21 | device tree node. Each lane exposed by the pad will be represented by its | ||
| 22 | own subnode and can be referenced by users of the lane using the standard | ||
| 23 | PHY bindings, as described by the phy-bindings.txt file in this directory. | ||
| 24 | |||
| 25 | The Tegra hardware documentation refers to the connection between the XUSB | ||
| 26 | pad controller and the XUSB controller as "ports". This is confusing since | ||
| 27 | "port" is typically used to denote the physical USB receptacle. The device | ||
| 28 | tree binding in this document uses the term "port" to refer to the logical | ||
| 29 | abstraction of the signals that are routed to a USB receptacle (i.e. a PHY | ||
| 30 | for the USB signal, the VBUS power supply, the USB 2.0 companion port for | ||
| 31 | USB 3.0 receptacles, ...). | ||
| 32 | |||
| 33 | Required properties: | ||
| 34 | -------------------- | ||
| 35 | - compatible: Must be: | ||
| 36 | - Tegra124: "nvidia,tegra124-xusb-padctl" | ||
| 37 | - Tegra132: "nvidia,tegra132-xusb-padctl", "nvidia,tegra124-xusb-padctl" | ||
| 38 | - Tegra210: "nvidia,tegra210-xusb-padctl" | ||
| 39 | - reg: Physical base address and length of the controller's registers. | ||
| 40 | - resets: Must contain an entry for each entry in reset-names. | ||
| 41 | - reset-names: Must include the following entries: | ||
| 42 | - "padctl" | ||
| 43 | |||
| 44 | |||
| 45 | Pad nodes: | ||
| 46 | ========== | ||
| 47 | |||
| 48 | A required child node named "pads" contains a list of subnodes, one for each | ||
| 49 | of the pads exposed by the XUSB pad controller. Each pad may need additional | ||
| 50 | resources that can be referenced in its pad node. | ||
| 51 | |||
| 52 | The "status" property is used to enable or disable the use of a pad. If set | ||
| 53 | to "disabled", the pad will not be used on the given board. In order to use | ||
| 54 | the pad and any of its lanes, this property must be set to "okay". | ||
| 55 | |||
| 56 | For Tegra124 and Tegra132, the following pads exist: usb2, ulpi, hsic, pcie | ||
| 57 | and sata. No extra resources are required for operation of these pads. | ||
| 58 | |||
| 59 | For Tegra210, the following pads exist: usb2, hsic, pcie and sata. Below is | ||
| 60 | a description of the properties of each pad. | ||
| 61 | |||
| 62 | UTMI pad: | ||
| 63 | --------- | ||
| 64 | |||
| 65 | Required properties: | ||
| 66 | - clocks: Must contain an entry for each entry in clock-names. | ||
| 67 | - clock-names: Must contain the following entries: | ||
| 68 | - "trk": phandle and specifier referring to the USB2 tracking clock | ||
| 69 | |||
| 70 | HSIC pad: | ||
| 71 | --------- | ||
| 72 | |||
| 73 | Required properties: | ||
| 74 | - clocks: Must contain an entry for each entry in clock-names. | ||
| 75 | - clock-names: Must contain the following entries: | ||
| 76 | - "trk": phandle and specifier referring to the HSIC tracking clock | ||
| 77 | |||
| 78 | PCIe pad: | ||
| 79 | --------- | ||
| 80 | |||
| 81 | Required properties: | ||
| 82 | - clocks: Must contain an entry for each entry in clock-names. | ||
| 83 | - clock-names: Must contain the following entries: | ||
| 84 | - "pll": phandle and specifier referring to the PLLE | ||
| 85 | - resets: Must contain an entry for each entry in reset-names. | ||
| 86 | - reset-names: Must contain the following entries: | ||
| 87 | - "phy": reset for the PCIe UPHY block | ||
| 88 | |||
| 89 | SATA pad: | ||
| 90 | --------- | ||
| 91 | |||
| 92 | Required properties: | ||
| 93 | - resets: Must contain an entry for each entry in reset-names. | ||
| 94 | - reset-names: Must contain the following entries: | ||
| 95 | - "phy": reset for the SATA UPHY block | ||
| 96 | |||
| 97 | |||
| 98 | PHY nodes: | ||
| 99 | ========== | ||
| 100 | |||
| 101 | Each pad node has a child named "lanes" that contains one or more children of | ||
| 102 | its own, each representing one of the lanes controlled by the pad. | ||
| 103 | |||
| 104 | Required properties: | ||
| 105 | -------------------- | ||
| 106 | - status: Defines the operation status of the PHY. Valid values are: | ||
| 107 | - "disabled": the PHY is disabled | ||
| 108 | - "okay": the PHY is enabled | ||
| 109 | - #phy-cells: Should be 0. Since each lane represents a single PHY, there is | ||
| 110 | no need for an additional specifier. | ||
| 111 | - nvidia,function: The output function of the PHY. See below for a list of | ||
| 112 | valid functions per SoC generation. | ||
| 113 | |||
| 114 | For Tegra124 and Tegra132, the list of valid PHY nodes is given below: | ||
| 115 | - usb2: usb2-0, usb2-1, usb2-2 | ||
| 116 | - functions: "snps", "xusb", "uart" | ||
| 117 | - ulpi: ulpi-0 | ||
| 118 | - functions: "snps", "xusb" | ||
| 119 | - hsic: hsic-0, hsic-1 | ||
| 120 | - functions: "snps", "xusb" | ||
| 121 | - pcie: pcie-0, pcie-1, pcie-2, pcie-3, pcie-4 | ||
| 122 | - functions: "pcie", "usb3-ss" | ||
| 123 | - sata: sata-0 | ||
| 124 | - functions: "usb3-ss", "sata" | ||
| 125 | |||
| 126 | For Tegra210, the list of valid PHY nodes is given below: | ||
| 127 | - utmi: utmi-0, utmi-1, utmi-2, utmi-3 | ||
| 128 | - functions: "snps", "xusb", "uart" | ||
| 129 | - hsic: hsic-0, hsic-1 | ||
| 130 | - functions: "snps", "xusb" | ||
| 131 | - pcie: pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, pcie-5, pcie-6 | ||
| 132 | - functions: "pcie-x1", "usb3-ss", "pcie-x4" | ||
| 133 | - sata: sata-0 | ||
| 134 | - functions: "usb3-ss", "sata" | ||
| 135 | |||
| 136 | |||
| 137 | Port nodes: | ||
| 138 | =========== | ||
| 139 | |||
| 140 | A required child node named "ports" contains a list of all the ports exposed | ||
| 141 | by the XUSB pad controller. Per-port configuration is only required for USB. | ||
| 142 | |||
| 143 | USB2 ports: | ||
| 144 | ----------- | ||
| 145 | |||
| 146 | Required properties: | ||
| 147 | - status: Defines the operation status of the port. Valid values are: | ||
| 148 | - "disabled": the port is disabled | ||
| 149 | - "okay": the port is enabled | ||
| 150 | - mode: A string that determines the mode in which to run the port. Valid | ||
| 151 | values are: | ||
| 152 | - "host": for USB host mode | ||
| 153 | - "device": for USB device mode | ||
| 154 | - "otg": for USB OTG mode | ||
| 155 | |||
| 156 | Optional properties: | ||
| 157 | - nvidia,internal: A boolean property whose presence determines that a port | ||
| 158 | is internal. In the absence of this property the port is considered to be | ||
| 159 | external. | ||
| 160 | - vbus-supply: phandle to a regulator supplying the VBUS voltage. | ||
| 161 | |||
| 162 | ULPI ports: | ||
| 163 | ----------- | ||
| 164 | |||
| 165 | Optional properties: | ||
| 166 | - status: Defines the operation status of the port. Valid values are: | ||
| 167 | - "disabled": the port is disabled | ||
| 168 | - "okay": the port is enabled | ||
| 169 | - nvidia,internal: A boolean property whose presence determines that a port | ||
| 170 | is internal. In the absence of this property the port is considered to be | ||
| 171 | external. | ||
| 172 | - vbus-supply: phandle to a regulator supplying the VBUS voltage. | ||
| 173 | |||
| 174 | HSIC ports: | ||
| 175 | ----------- | ||
| 176 | |||
| 177 | Required properties: | ||
| 178 | - status: Defines the operation status of the port. Valid values are: | ||
| 179 | - "disabled": the port is disabled | ||
| 180 | - "okay": the port is enabled | ||
| 181 | |||
| 182 | Optional properties: | ||
| 183 | - vbus-supply: phandle to a regulator supplying the VBUS voltage. | ||
| 184 | |||
| 185 | Super-speed USB ports: | ||
| 186 | ---------------------- | ||
| 187 | |||
| 188 | Required properties: | ||
| 189 | - status: Defines the operation status of the port. Valid values are: | ||
| 190 | - "disabled": the port is disabled | ||
| 191 | - "okay": the port is enabled | ||
| 192 | - nvidia,usb2-companion: A single cell that specifies the physical port number | ||
| 193 | to map this super-speed USB port to. The range of valid port numbers varies | ||
| 194 | with the SoC generation: | ||
| 195 | - 0-2: for Tegra124 and Tegra132 | ||
| 196 | - 0-3: for Tegra210 | ||
| 197 | |||
| 198 | Optional properties: | ||
| 199 | - nvidia,internal: A boolean property whose presence determines that a port | ||
| 200 | is internal. In the absence of this property the port is considered to be | ||
| 201 | external. | ||
| 202 | |||
| 203 | For Tegra124 and Tegra132, the XUSB pad controller exposes the following | ||
| 204 | ports: | ||
| 205 | - 3x USB2: usb2-0, usb2-1, usb2-2 | ||
| 206 | - 1x ULPI: ulpi-0 | ||
| 207 | - 2x HSIC: hsic-0, hsic-1 | ||
| 208 | - 2x super-speed USB: usb3-0, usb3-1 | ||
| 209 | |||
| 210 | For Tegra210, the XUSB pad controller exposes the following ports: | ||
| 211 | - 4x USB2: usb2-0, usb2-1, usb2-2, usb2-3 | ||
| 212 | - 2x HSIC: hsic-0, hsic-1 | ||
| 213 | - 4x super-speed USB: usb3-0, usb3-1, usb3-2, usb3-3 | ||
| 214 | |||
| 215 | |||
| 216 | Examples: | ||
| 217 | ========= | ||
| 218 | |||
| 219 | Tegra124 and Tegra132: | ||
| 220 | ---------------------- | ||
| 221 | |||
| 222 | SoC include: | ||
| 223 | |||
| 224 | padctl@7009f000 { | ||
| 225 | /* for Tegra124 */ | ||
| 226 | compatible = "nvidia,tegra124-xusb-padctl"; | ||
| 227 | /* for Tegra132 */ | ||
| 228 | compatible = "nvidia,tegra132-xusb-padctl", | ||
| 229 | "nvidia,tegra124-xusb-padctl"; | ||
| 230 | reg = <0x0 0x7009f000 0x0 0x1000>; | ||
| 231 | resets = <&tegra_car 142>; | ||
| 232 | reset-names = "padctl"; | ||
| 233 | |||
| 234 | pads { | ||
| 235 | usb2 { | ||
| 236 | status = "disabled"; | ||
| 237 | |||
| 238 | lanes { | ||
| 239 | usb2-0 { | ||
| 240 | status = "disabled"; | ||
| 241 | #phy-cells = <0>; | ||
| 242 | }; | ||
| 243 | |||
| 244 | usb2-1 { | ||
| 245 | status = "disabled"; | ||
| 246 | #phy-cells = <0>; | ||
| 247 | }; | ||
| 248 | |||
| 249 | usb2-2 { | ||
| 250 | status = "disabled"; | ||
| 251 | #phy-cells = <0>; | ||
| 252 | }; | ||
| 253 | }; | ||
| 254 | }; | ||
| 255 | |||
| 256 | ulpi { | ||
| 257 | status = "disabled"; | ||
| 258 | |||
| 259 | lanes { | ||
| 260 | ulpi-0 { | ||
| 261 | status = "disabled"; | ||
| 262 | #phy-cells = <0>; | ||
| 263 | }; | ||
| 264 | }; | ||
| 265 | }; | ||
| 266 | |||
| 267 | hsic { | ||
| 268 | status = "disabled"; | ||
| 269 | |||
| 270 | lanes { | ||
| 271 | hsic-0 { | ||
| 272 | status = "disabled"; | ||
| 273 | #phy-cells = <0>; | ||
| 274 | }; | ||
| 275 | |||
| 276 | hsic-1 { | ||
| 277 | status = "disabled"; | ||
| 278 | #phy-cells = <0>; | ||
| 279 | }; | ||
| 280 | }; | ||
| 281 | }; | ||
| 282 | |||
| 283 | pcie { | ||
| 284 | status = "disabled"; | ||
| 285 | |||
| 286 | lanes { | ||
| 287 | pcie-0 { | ||
| 288 | status = "disabled"; | ||
| 289 | #phy-cells = <0>; | ||
| 290 | }; | ||
| 291 | |||
| 292 | pcie-1 { | ||
| 293 | status = "disabled"; | ||
| 294 | #phy-cells = <0>; | ||
| 295 | }; | ||
| 296 | |||
| 297 | pcie-2 { | ||
| 298 | status = "disabled"; | ||
| 299 | #phy-cells = <0>; | ||
| 300 | }; | ||
| 301 | |||
| 302 | pcie-3 { | ||
| 303 | status = "disabled"; | ||
| 304 | #phy-cells = <0>; | ||
| 305 | }; | ||
| 306 | |||
| 307 | pcie-4 { | ||
| 308 | status = "disabled"; | ||
| 309 | #phy-cells = <0>; | ||
| 310 | }; | ||
| 311 | }; | ||
| 312 | }; | ||
| 313 | |||
| 314 | sata { | ||
| 315 | status = "disabled"; | ||
| 316 | |||
| 317 | lanes { | ||
| 318 | sata-0 { | ||
| 319 | status = "disabled"; | ||
| 320 | #phy-cells = <0>; | ||
| 321 | }; | ||
| 322 | }; | ||
| 323 | }; | ||
| 324 | }; | ||
| 325 | |||
| 326 | ports { | ||
| 327 | usb2-0 { | ||
| 328 | status = "disabled"; | ||
| 329 | }; | ||
| 330 | |||
| 331 | usb2-1 { | ||
| 332 | status = "disabled"; | ||
| 333 | }; | ||
| 334 | |||
| 335 | usb2-2 { | ||
| 336 | status = "disabled"; | ||
| 337 | }; | ||
| 338 | |||
| 339 | ulpi-0 { | ||
| 340 | status = "disabled"; | ||
| 341 | }; | ||
| 342 | |||
| 343 | hsic-0 { | ||
| 344 | status = "disabled"; | ||
| 345 | }; | ||
| 346 | |||
| 347 | hsic-1 { | ||
| 348 | status = "disabled"; | ||
| 349 | }; | ||
| 350 | |||
| 351 | usb3-0 { | ||
| 352 | status = "disabled"; | ||
| 353 | }; | ||
| 354 | |||
| 355 | usb3-1 { | ||
| 356 | status = "disabled"; | ||
| 357 | }; | ||
| 358 | }; | ||
| 359 | }; | ||
| 360 | |||
| 361 | Board file: | ||
| 362 | |||
| 363 | padctl@7009f000 { | ||
| 364 | status = "okay"; | ||
| 365 | |||
| 366 | pads { | ||
| 367 | usb2 { | ||
| 368 | status = "okay"; | ||
| 369 | |||
| 370 | lanes { | ||
| 371 | usb2-0 { | ||
| 372 | nvidia,function = "xusb"; | ||
| 373 | status = "okay"; | ||
| 374 | }; | ||
| 375 | |||
| 376 | usb2-1 { | ||
| 377 | nvidia,function = "xusb"; | ||
| 378 | status = "okay"; | ||
| 379 | }; | ||
| 380 | |||
| 381 | usb2-2 { | ||
| 382 | nvidia,function = "xusb"; | ||
| 383 | status = "okay"; | ||
| 384 | }; | ||
| 385 | }; | ||
| 386 | }; | ||
| 387 | |||
| 388 | pcie { | ||
| 389 | status = "okay"; | ||
| 390 | |||
| 391 | lanes { | ||
| 392 | pcie-0 { | ||
| 393 | nvidia,function = "usb3-ss"; | ||
| 394 | status = "okay"; | ||
| 395 | }; | ||
| 396 | |||
| 397 | pcie-2 { | ||
| 398 | nvidia,function = "pcie"; | ||
| 399 | status = "okay"; | ||
| 400 | }; | ||
| 401 | |||
| 402 | pcie-4 { | ||
| 403 | nvidia,function = "pcie"; | ||
| 404 | status = "okay"; | ||
| 405 | }; | ||
| 406 | }; | ||
| 407 | }; | ||
| 408 | |||
| 409 | sata { | ||
| 410 | status = "okay"; | ||
| 411 | |||
| 412 | lanes { | ||
| 413 | sata-0 { | ||
| 414 | nvidia,function = "sata"; | ||
| 415 | status = "okay"; | ||
| 416 | }; | ||
| 417 | }; | ||
| 418 | }; | ||
| 419 | }; | ||
| 420 | |||
| 421 | ports { | ||
| 422 | /* Micro A/B */ | ||
| 423 | usb2-0 { | ||
| 424 | status = "okay"; | ||
| 425 | mode = "otg"; | ||
| 426 | }; | ||
| 427 | |||
| 428 | /* Mini PCIe */ | ||
| 429 | usb2-1 { | ||
| 430 | status = "okay"; | ||
| 431 | mode = "host"; | ||
| 432 | }; | ||
| 433 | |||
| 434 | /* USB3 */ | ||
| 435 | usb2-2 { | ||
| 436 | status = "okay"; | ||
| 437 | mode = "host"; | ||
| 438 | |||
| 439 | vbus-supply = <&vdd_usb3_vbus>; | ||
| 440 | }; | ||
| 441 | |||
| 442 | usb3-0 { | ||
| 443 | nvidia,port = <2>; | ||
| 444 | status = "okay"; | ||
| 445 | }; | ||
| 446 | }; | ||
| 447 | }; | ||
| 448 | |||
| 449 | Tegra210: | ||
| 450 | --------- | ||
| 451 | |||
| 452 | SoC include: | ||
| 453 | |||
| 454 | padctl@7009f000 { | ||
| 455 | compatible = "nvidia,tegra210-xusb-padctl"; | ||
| 456 | reg = <0x0 0x7009f000 0x0 0x1000>; | ||
| 457 | resets = <&tegra_car 142>; | ||
| 458 | reset-names = "padctl"; | ||
| 459 | |||
| 460 | status = "disabled"; | ||
| 461 | |||
| 462 | pads { | ||
| 463 | usb2 { | ||
| 464 | clocks = <&tegra_car TEGRA210_CLK_USB2_TRK>; | ||
| 465 | clock-names = "trk"; | ||
| 466 | status = "disabled"; | ||
| 467 | |||
| 468 | lanes { | ||
| 469 | usb2-0 { | ||
| 470 | status = "disabled"; | ||
| 471 | #phy-cells = <0>; | ||
| 472 | }; | ||
| 473 | |||
| 474 | usb2-1 { | ||
| 475 | status = "disabled"; | ||
| 476 | #phy-cells = <0>; | ||
| 477 | }; | ||
| 478 | |||
| 479 | usb2-2 { | ||
| 480 | status = "disabled"; | ||
| 481 | #phy-cells = <0>; | ||
| 482 | }; | ||
| 483 | |||
| 484 | usb2-3 { | ||
| 485 | status = "disabled"; | ||
| 486 | #phy-cells = <0>; | ||
| 487 | }; | ||
| 488 | }; | ||
| 489 | }; | ||
| 490 | |||
| 491 | hsic { | ||
| 492 | clocks = <&tegra_car TEGRA210_CLK_HSIC_TRK>; | ||
| 493 | clock-names = "trk"; | ||
| 494 | status = "disabled"; | ||
| 495 | |||
| 496 | lanes { | ||
| 497 | hsic-0 { | ||
| 498 | status = "disabled"; | ||
| 499 | #phy-cells = <0>; | ||
| 500 | }; | ||
| 501 | |||
| 502 | hsic-1 { | ||
| 503 | status = "disabled"; | ||
| 504 | #phy-cells = <0>; | ||
| 505 | }; | ||
| 506 | }; | ||
| 507 | }; | ||
| 508 | |||
| 509 | pcie { | ||
| 510 | clocks = <&tegra_car TEGRA210_CLK_PLL_E>; | ||
| 511 | clock-names = "pll"; | ||
| 512 | resets = <&tegra_car 205>; | ||
| 513 | reset-names = "phy"; | ||
| 514 | status = "disabled"; | ||
| 515 | |||
| 516 | lanes { | ||
| 517 | pcie-0 { | ||
| 518 | status = "disabled"; | ||
| 519 | #phy-cells = <0>; | ||
| 520 | }; | ||
| 521 | |||
| 522 | pcie-1 { | ||
| 523 | status = "disabled"; | ||
| 524 | #phy-cells = <0>; | ||
| 525 | }; | ||
| 526 | |||
| 527 | pcie-2 { | ||
| 528 | status = "disabled"; | ||
| 529 | #phy-cells = <0>; | ||
| 530 | }; | ||
| 531 | |||
| 532 | pcie-3 { | ||
| 533 | status = "disabled"; | ||
| 534 | #phy-cells = <0>; | ||
| 535 | }; | ||
| 536 | |||
| 537 | pcie-4 { | ||
| 538 | status = "disabled"; | ||
| 539 | #phy-cells = <0>; | ||
| 540 | }; | ||
| 541 | |||
| 542 | pcie-5 { | ||
| 543 | status = "disabled"; | ||
| 544 | #phy-cells = <0>; | ||
| 545 | }; | ||
| 546 | |||
| 547 | pcie-6 { | ||
| 548 | status = "disabled"; | ||
| 549 | #phy-cells = <0>; | ||
| 550 | }; | ||
| 551 | }; | ||
| 552 | }; | ||
| 553 | |||
| 554 | sata { | ||
| 555 | clocks = <&tegra_car TEGRA210_CLK_PLL_E>; | ||
| 556 | clock-names = "pll"; | ||
| 557 | resets = <&tegra_car 204>; | ||
| 558 | reset-names = "phy"; | ||
| 559 | status = "disabled"; | ||
| 560 | |||
| 561 | lanes { | ||
| 562 | sata-0 { | ||
| 563 | status = "disabled"; | ||
| 564 | #phy-cells = <0>; | ||
| 565 | }; | ||
| 566 | }; | ||
| 567 | }; | ||
| 568 | }; | ||
| 569 | |||
| 570 | ports { | ||
| 571 | usb2-0 { | ||
| 572 | status = "disabled"; | ||
| 573 | }; | ||
| 574 | |||
| 575 | usb2-1 { | ||
| 576 | status = "disabled"; | ||
| 577 | }; | ||
| 578 | |||
| 579 | usb2-2 { | ||
| 580 | status = "disabled"; | ||
| 581 | }; | ||
| 582 | |||
| 583 | usb2-3 { | ||
| 584 | status = "disabled"; | ||
| 585 | }; | ||
| 586 | |||
| 587 | hsic-0 { | ||
| 588 | status = "disabled"; | ||
| 589 | }; | ||
| 590 | |||
| 591 | hsic-1 { | ||
| 592 | status = "disabled"; | ||
| 593 | }; | ||
| 594 | |||
| 595 | usb3-0 { | ||
| 596 | status = "disabled"; | ||
| 597 | }; | ||
| 598 | |||
| 599 | usb3-1 { | ||
| 600 | status = "disabled"; | ||
| 601 | }; | ||
| 602 | |||
| 603 | usb3-2 { | ||
| 604 | status = "disabled"; | ||
| 605 | }; | ||
| 606 | |||
| 607 | usb3-3 { | ||
| 608 | status = "disabled"; | ||
| 609 | }; | ||
| 610 | }; | ||
| 611 | }; | ||
| 612 | |||
| 613 | Board file: | ||
| 614 | |||
| 615 | padctl@7009f000 { | ||
| 616 | status = "okay"; | ||
| 617 | |||
| 618 | pads { | ||
| 619 | usb2 { | ||
| 620 | status = "okay"; | ||
| 621 | |||
| 622 | lanes { | ||
| 623 | usb2-0 { | ||
| 624 | nvidia,function = "xusb"; | ||
| 625 | status = "okay"; | ||
| 626 | }; | ||
| 627 | |||
| 628 | usb2-1 { | ||
| 629 | nvidia,function = "xusb"; | ||
| 630 | status = "okay"; | ||
| 631 | }; | ||
| 632 | |||
| 633 | usb2-2 { | ||
| 634 | nvidia,function = "xusb"; | ||
| 635 | status = "okay"; | ||
| 636 | }; | ||
| 637 | |||
| 638 | usb2-3 { | ||
| 639 | nvidia,function = "xusb"; | ||
| 640 | status = "okay"; | ||
| 641 | }; | ||
| 642 | }; | ||
| 643 | }; | ||
| 644 | |||
| 645 | pcie { | ||
| 646 | status = "okay"; | ||
| 647 | |||
| 648 | lanes { | ||
| 649 | pcie-0 { | ||
| 650 | nvidia,function = "pcie-x1"; | ||
| 651 | status = "okay"; | ||
| 652 | }; | ||
| 653 | |||
| 654 | pcie-1 { | ||
| 655 | nvidia,function = "pcie-x4"; | ||
| 656 | status = "okay"; | ||
| 657 | }; | ||
| 658 | |||
| 659 | pcie-2 { | ||
| 660 | nvidia,function = "pcie-x4"; | ||
| 661 | status = "okay"; | ||
| 662 | }; | ||
| 663 | |||
| 664 | pcie-3 { | ||
| 665 | nvidia,function = "pcie-x4"; | ||
| 666 | status = "okay"; | ||
| 667 | }; | ||
| 668 | |||
| 669 | pcie-4 { | ||
| 670 | nvidia,function = "pcie-x4"; | ||
| 671 | status = "okay"; | ||
| 672 | }; | ||
| 673 | |||
| 674 | pcie-5 { | ||
| 675 | nvidia,function = "usb3-ss"; | ||
| 676 | status = "okay"; | ||
| 677 | }; | ||
| 678 | |||
| 679 | pcie-6 { | ||
| 680 | nvidia,function = "usb3-ss"; | ||
| 681 | status = "okay"; | ||
| 682 | }; | ||
| 683 | }; | ||
| 684 | }; | ||
| 685 | |||
| 686 | sata { | ||
| 687 | status = "okay"; | ||
| 688 | |||
| 689 | lanes { | ||
| 690 | sata-0 { | ||
| 691 | nvidia,function = "sata"; | ||
| 692 | status = "okay"; | ||
| 693 | }; | ||
| 694 | }; | ||
| 695 | }; | ||
| 696 | }; | ||
| 697 | |||
| 698 | ports { | ||
| 699 | usb2-0 { | ||
| 700 | status = "okay"; | ||
| 701 | mode = "otg"; | ||
| 702 | }; | ||
| 703 | |||
| 704 | usb2-1 { | ||
| 705 | status = "okay"; | ||
| 706 | vbus-supply = <&vdd_5v0_rtl>; | ||
| 707 | mode = "host"; | ||
| 708 | }; | ||
| 709 | |||
| 710 | usb2-2 { | ||
| 711 | status = "okay"; | ||
| 712 | vbus-supply = <&vdd_usb_vbus>; | ||
| 713 | mode = "host"; | ||
| 714 | }; | ||
| 715 | |||
| 716 | usb2-3 { | ||
| 717 | status = "okay"; | ||
| 718 | mode = "host"; | ||
| 719 | }; | ||
| 720 | |||
| 721 | usb3-0 { | ||
| 722 | status = "okay"; | ||
| 723 | nvidia,lanes = "pcie-6"; | ||
| 724 | nvidia,port = <1>; | ||
| 725 | }; | ||
| 726 | |||
| 727 | usb3-1 { | ||
| 728 | status = "okay"; | ||
| 729 | nvidia,lanes = "pcie-5"; | ||
| 730 | nvidia,port = <2>; | ||
| 731 | }; | ||
| 732 | }; | ||
| 733 | }; | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt index 30676ded85bb..8a6223dbc143 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt | |||
| @@ -1,6 +1,12 @@ | |||
| 1 | Device tree binding for NVIDIA Tegra XUSB pad controller | 1 | Device tree binding for NVIDIA Tegra XUSB pad controller |
| 2 | ======================================================== | 2 | ======================================================== |
| 3 | 3 | ||
| 4 | NOTE: It turns out that this binding isn't an accurate description of the XUSB | ||
| 5 | pad controller. While the description is good enough for the functional subset | ||
| 6 | required for PCIe and SATA, it lacks the flexibility to represent the features | ||
| 7 | needed for USB. For the new binding, see ../phy/nvidia,tegra-xusb-padctl.txt. | ||
| 8 | The binding described in this file is deprecated and should not be used. | ||
| 9 | |||
| 4 | The Tegra XUSB pad controller manages a set of lanes, each of which can be | 10 | The Tegra XUSB pad controller manages a set of lanes, each of which can be |
| 5 | assigned to one out of a set of different pads. Some of these pads have an | 11 | assigned to one out of a set of different pads. Some of these pads have an |
| 6 | associated PHY that must be powered up before the pad can be used. | 12 | associated PHY that must be powered up before the pad can be used. |
diff --git a/Documentation/phy.txt b/Documentation/phy.txt index b388c5af9e72..0aa994bd9a91 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt | |||
| @@ -31,16 +31,28 @@ should provide its own implementation of of_xlate. of_xlate is used only for | |||
| 31 | dt boot case. | 31 | dt boot case. |
| 32 | 32 | ||
| 33 | #define of_phy_provider_register(dev, xlate) \ | 33 | #define of_phy_provider_register(dev, xlate) \ |
| 34 | __of_phy_provider_register((dev), THIS_MODULE, (xlate)) | 34 | __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate)) |
| 35 | 35 | ||
| 36 | #define devm_of_phy_provider_register(dev, xlate) \ | 36 | #define devm_of_phy_provider_register(dev, xlate) \ |
| 37 | __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate)) | 37 | __devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate)) |
| 38 | 38 | ||
| 39 | of_phy_provider_register and devm_of_phy_provider_register macros can be used to | 39 | of_phy_provider_register and devm_of_phy_provider_register macros can be used to |
| 40 | register the phy_provider and it takes device and of_xlate as | 40 | register the phy_provider and it takes device and of_xlate as |
| 41 | arguments. For the dt boot case, all PHY providers should use one of the above | 41 | arguments. For the dt boot case, all PHY providers should use one of the above |
| 42 | 2 macros to register the PHY provider. | 42 | 2 macros to register the PHY provider. |
| 43 | 43 | ||
| 44 | Often the device tree nodes associated with a PHY provider will contain a set | ||
| 45 | of children that each represent a single PHY. Some bindings may nest the child | ||
| 46 | nodes within extra levels for context and extensibility, in which case the low | ||
| 47 | level of_phy_provider_register_full() and devm_of_phy_provider_register_full() | ||
| 48 | macros can be used to override the node containing the children. | ||
| 49 | |||
| 50 | #define of_phy_provider_register_full(dev, children, xlate) \ | ||
| 51 | __of_phy_provider_register(dev, children, THIS_MODULE, xlate) | ||
| 52 | |||
| 53 | #define devm_of_phy_provider_register_full(dev, children, xlate) \ | ||
| 54 | __devm_of_phy_provider_register_full(dev, children, THIS_MODULE, xlate) | ||
| 55 | |||
| 44 | void devm_of_phy_provider_unregister(struct device *dev, | 56 | void devm_of_phy_provider_unregister(struct device *dev, |
| 45 | struct phy_provider *phy_provider); | 57 | struct phy_provider *phy_provider); |
| 46 | void of_phy_provider_unregister(struct phy_provider *phy_provider); | 58 | void of_phy_provider_unregister(struct phy_provider *phy_provider); |
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 637041fd53ad..3d0edee1f9fe 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c | |||
| @@ -175,6 +175,19 @@ | |||
| 175 | #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) | 175 | #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) |
| 176 | #define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) | 176 | #define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) |
| 177 | 177 | ||
| 178 | #define SATA_PLL_CFG0 0x490 | ||
| 179 | #define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0) | ||
| 180 | #define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2) | ||
| 181 | #define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13) | ||
| 182 | #define SATA_PLL_CFG0_SEQ_ENABLE BIT(24) | ||
| 183 | |||
| 184 | #define XUSBIO_PLL_CFG0 0x51c | ||
| 185 | #define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0) | ||
| 186 | #define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL BIT(2) | ||
| 187 | #define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET BIT(6) | ||
| 188 | #define XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13) | ||
| 189 | #define XUSBIO_PLL_CFG0_SEQ_ENABLE BIT(24) | ||
| 190 | |||
| 178 | #define UTMIPLL_HW_PWRDN_CFG0 0x52c | 191 | #define UTMIPLL_HW_PWRDN_CFG0 0x52c |
| 179 | #define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31) | 192 | #define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31) |
| 180 | #define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) | 193 | #define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) |
| @@ -416,6 +429,51 @@ static const char *mux_pllmcp_clkm[] = { | |||
| 416 | #define PLLU_MISC0_WRITE_MASK 0xbfffffff | 429 | #define PLLU_MISC0_WRITE_MASK 0xbfffffff |
| 417 | #define PLLU_MISC1_WRITE_MASK 0x00000007 | 430 | #define PLLU_MISC1_WRITE_MASK 0x00000007 |
| 418 | 431 | ||
| 432 | void tegra210_xusb_pll_hw_control_enable(void) | ||
| 433 | { | ||
| 434 | u32 val; | ||
| 435 | |||
| 436 | val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0); | ||
| 437 | val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL | | ||
| 438 | XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL); | ||
| 439 | val |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET | | ||
| 440 | XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ; | ||
| 441 | writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0); | ||
| 442 | } | ||
| 443 | EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_control_enable); | ||
| 444 | |||
| 445 | void tegra210_xusb_pll_hw_sequence_start(void) | ||
| 446 | { | ||
| 447 | u32 val; | ||
| 448 | |||
| 449 | val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0); | ||
| 450 | val |= XUSBIO_PLL_CFG0_SEQ_ENABLE; | ||
| 451 | writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0); | ||
| 452 | } | ||
| 453 | EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_sequence_start); | ||
| 454 | |||
| 455 | void tegra210_sata_pll_hw_control_enable(void) | ||
| 456 | { | ||
| 457 | u32 val; | ||
| 458 | |||
| 459 | val = readl_relaxed(clk_base + SATA_PLL_CFG0); | ||
| 460 | val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL; | ||
| 461 | val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET | | ||
| 462 | SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ; | ||
| 463 | writel_relaxed(val, clk_base + SATA_PLL_CFG0); | ||
| 464 | } | ||
| 465 | EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_control_enable); | ||
| 466 | |||
| 467 | void tegra210_sata_pll_hw_sequence_start(void) | ||
| 468 | { | ||
| 469 | u32 val; | ||
| 470 | |||
| 471 | val = readl_relaxed(clk_base + SATA_PLL_CFG0); | ||
| 472 | val |= SATA_PLL_CFG0_SEQ_ENABLE; | ||
| 473 | writel_relaxed(val, clk_base + SATA_PLL_CFG0); | ||
| 474 | } | ||
| 475 | EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start); | ||
| 476 | |||
| 419 | static inline void _pll_misc_chk_default(void __iomem *base, | 477 | static inline void _pll_misc_chk_default(void __iomem *base, |
| 420 | struct tegra_clk_pll_params *params, | 478 | struct tegra_clk_pll_params *params, |
| 421 | u8 misc_num, u32 default_val, u32 mask) | 479 | u8 misc_num, u32 default_val, u32 mask) |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 26566db09de0..27e5f6ee9a2a 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
| @@ -421,4 +421,6 @@ config PHY_CYGNUS_PCIE | |||
| 421 | Enable this to support the Broadcom Cygnus PCIe PHY. | 421 | Enable this to support the Broadcom Cygnus PCIe PHY. |
| 422 | If unsure, say N. | 422 | If unsure, say N. |
| 423 | 423 | ||
| 424 | source "drivers/phy/tegra/Kconfig" | ||
| 425 | |||
| 424 | endmenu | 426 | endmenu |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 24596a96a887..d4f06e69fd9a 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
| @@ -52,3 +52,5 @@ obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o | |||
| 52 | obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o | 52 | obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o |
| 53 | obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o | 53 | obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o |
| 54 | obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o | 54 | obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o |
| 55 | |||
| 56 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ | ||
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index e7e574dc667a..b72e9a3b6429 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
| @@ -141,7 +141,7 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node) | |||
| 141 | if (phy_provider->dev->of_node == node) | 141 | if (phy_provider->dev->of_node == node) |
| 142 | return phy_provider; | 142 | return phy_provider; |
| 143 | 143 | ||
| 144 | for_each_child_of_node(phy_provider->dev->of_node, child) | 144 | for_each_child_of_node(phy_provider->children, child) |
| 145 | if (child == node) | 145 | if (child == node) |
| 146 | return phy_provider; | 146 | return phy_provider; |
| 147 | } | 147 | } |
| @@ -811,24 +811,59 @@ EXPORT_SYMBOL_GPL(devm_phy_destroy); | |||
| 811 | /** | 811 | /** |
| 812 | * __of_phy_provider_register() - create/register phy provider with the framework | 812 | * __of_phy_provider_register() - create/register phy provider with the framework |
| 813 | * @dev: struct device of the phy provider | 813 | * @dev: struct device of the phy provider |
| 814 | * @children: device node containing children (if different from dev->of_node) | ||
| 814 | * @owner: the module owner containing of_xlate | 815 | * @owner: the module owner containing of_xlate |
| 815 | * @of_xlate: function pointer to obtain phy instance from phy provider | 816 | * @of_xlate: function pointer to obtain phy instance from phy provider |
| 816 | * | 817 | * |
| 817 | * Creates struct phy_provider from dev and of_xlate function pointer. | 818 | * Creates struct phy_provider from dev and of_xlate function pointer. |
| 818 | * This is used in the case of dt boot for finding the phy instance from | 819 | * This is used in the case of dt boot for finding the phy instance from |
| 819 | * phy provider. | 820 | * phy provider. |
| 821 | * | ||
| 822 | * If the PHY provider doesn't nest children directly but uses a separate | ||
| 823 | * child node to contain the individual children, the @children parameter | ||
| 824 | * can be used to override the default. If NULL, the default (dev->of_node) | ||
| 825 | * will be used. If non-NULL, the device node must be a child (or further | ||
| 826 | * descendant) of dev->of_node. Otherwise an ERR_PTR()-encoded -EINVAL | ||
| 827 | * error code is returned. | ||
| 820 | */ | 828 | */ |
| 821 | struct phy_provider *__of_phy_provider_register(struct device *dev, | 829 | struct phy_provider *__of_phy_provider_register(struct device *dev, |
| 822 | struct module *owner, struct phy * (*of_xlate)(struct device *dev, | 830 | struct device_node *children, struct module *owner, |
| 823 | struct of_phandle_args *args)) | 831 | struct phy * (*of_xlate)(struct device *dev, |
| 832 | struct of_phandle_args *args)) | ||
| 824 | { | 833 | { |
| 825 | struct phy_provider *phy_provider; | 834 | struct phy_provider *phy_provider; |
| 826 | 835 | ||
| 836 | /* | ||
| 837 | * If specified, the device node containing the children must itself | ||
| 838 | * be the provider's device node or a child (or further descendant) | ||
| 839 | * thereof. | ||
| 840 | */ | ||
| 841 | if (children) { | ||
| 842 | struct device_node *parent = of_node_get(children), *next; | ||
| 843 | |||
| 844 | while (parent) { | ||
| 845 | if (parent == dev->of_node) | ||
| 846 | break; | ||
| 847 | |||
| 848 | next = of_get_parent(parent); | ||
| 849 | of_node_put(parent); | ||
| 850 | parent = next; | ||
| 851 | } | ||
| 852 | |||
| 853 | if (!parent) | ||
| 854 | return ERR_PTR(-EINVAL); | ||
| 855 | |||
| 856 | of_node_put(parent); | ||
| 857 | } else { | ||
| 858 | children = dev->of_node; | ||
| 859 | } | ||
| 860 | |||
| 827 | phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL); | 861 | phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL); |
| 828 | if (!phy_provider) | 862 | if (!phy_provider) |
| 829 | return ERR_PTR(-ENOMEM); | 863 | return ERR_PTR(-ENOMEM); |
| 830 | 864 | ||
| 831 | phy_provider->dev = dev; | 865 | phy_provider->dev = dev; |
| 866 | phy_provider->children = of_node_get(children); | ||
| 832 | phy_provider->owner = owner; | 867 | phy_provider->owner = owner; |
| 833 | phy_provider->of_xlate = of_xlate; | 868 | phy_provider->of_xlate = of_xlate; |
| 834 | 869 | ||
| @@ -854,8 +889,9 @@ EXPORT_SYMBOL_GPL(__of_phy_provider_register); | |||
| 854 | * on the devres data, then, devres data is freed. | 889 | * on the devres data, then, devres data is freed. |
| 855 | */ | 890 | */ |
| 856 | struct phy_provider *__devm_of_phy_provider_register(struct device *dev, | 891 | struct phy_provider *__devm_of_phy_provider_register(struct device *dev, |
| 857 | struct module *owner, struct phy * (*of_xlate)(struct device *dev, | 892 | struct device_node *children, struct module *owner, |
| 858 | struct of_phandle_args *args)) | 893 | struct phy * (*of_xlate)(struct device *dev, |
| 894 | struct of_phandle_args *args)) | ||
| 859 | { | 895 | { |
| 860 | struct phy_provider **ptr, *phy_provider; | 896 | struct phy_provider **ptr, *phy_provider; |
| 861 | 897 | ||
| @@ -863,7 +899,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev, | |||
| 863 | if (!ptr) | 899 | if (!ptr) |
| 864 | return ERR_PTR(-ENOMEM); | 900 | return ERR_PTR(-ENOMEM); |
| 865 | 901 | ||
| 866 | phy_provider = __of_phy_provider_register(dev, owner, of_xlate); | 902 | phy_provider = __of_phy_provider_register(dev, children, owner, |
| 903 | of_xlate); | ||
| 867 | if (!IS_ERR(phy_provider)) { | 904 | if (!IS_ERR(phy_provider)) { |
| 868 | *ptr = phy_provider; | 905 | *ptr = phy_provider; |
| 869 | devres_add(dev, ptr); | 906 | devres_add(dev, ptr); |
| @@ -888,6 +925,7 @@ void of_phy_provider_unregister(struct phy_provider *phy_provider) | |||
| 888 | 925 | ||
| 889 | mutex_lock(&phy_provider_mutex); | 926 | mutex_lock(&phy_provider_mutex); |
| 890 | list_del(&phy_provider->list); | 927 | list_del(&phy_provider->list); |
| 928 | of_node_put(phy_provider->children); | ||
| 891 | kfree(phy_provider); | 929 | kfree(phy_provider); |
| 892 | mutex_unlock(&phy_provider_mutex); | 930 | mutex_unlock(&phy_provider_mutex); |
| 893 | } | 931 | } |
diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig new file mode 100644 index 000000000000..a3b1de953fb7 --- /dev/null +++ b/drivers/phy/tegra/Kconfig | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | config PHY_TEGRA_XUSB | ||
| 2 | tristate "NVIDIA Tegra XUSB pad controller driver" | ||
| 3 | depends on ARCH_TEGRA | ||
| 4 | help | ||
| 5 | Choose this option if you have an NVIDIA Tegra SoC. | ||
| 6 | |||
| 7 | To compile this driver as a module, choose M here: the module will | ||
| 8 | be called phy-tegra-xusb. | ||
diff --git a/drivers/phy/tegra/Makefile b/drivers/phy/tegra/Makefile new file mode 100644 index 000000000000..898589238fd9 --- /dev/null +++ b/drivers/phy/tegra/Makefile | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | obj-$(CONFIG_PHY_TEGRA_XUSB) += phy-tegra-xusb.o | ||
| 2 | |||
| 3 | phy-tegra-xusb-y += xusb.o | ||
| 4 | phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_124_SOC) += xusb-tegra124.o | ||
| 5 | phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_132_SOC) += xusb-tegra124.o | ||
| 6 | phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_210_SOC) += xusb-tegra210.o | ||
diff --git a/drivers/phy/tegra/xusb-tegra124.c b/drivers/phy/tegra/xusb-tegra124.c new file mode 100644 index 000000000000..119957249a51 --- /dev/null +++ b/drivers/phy/tegra/xusb-tegra124.c | |||
| @@ -0,0 +1,1752 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/mailbox_client.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/phy/phy.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/regulator/consumer.h> | ||
| 22 | #include <linux/reset.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | |||
| 25 | #include <soc/tegra/fuse.h> | ||
| 26 | |||
| 27 | #include "xusb.h" | ||
| 28 | |||
| 29 | #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0) | ||
| 30 | #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f | ||
| 31 | #define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13 | ||
| 32 | #define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3 | ||
| 33 | #define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11 | ||
| 34 | #define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3 | ||
| 35 | #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7 | ||
| 36 | #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf | ||
| 37 | |||
| 38 | #define XUSB_PADCTL_USB2_PORT_CAP 0x008 | ||
| 39 | #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4) | ||
| 40 | #define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3 | ||
| 41 | #define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0 | ||
| 42 | #define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1 | ||
| 43 | #define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2 | ||
| 44 | #define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3 | ||
| 45 | |||
| 46 | #define XUSB_PADCTL_SS_PORT_MAP 0x014 | ||
| 47 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 4) + 3)) | ||
| 48 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 4) | ||
| 49 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 4)) | ||
| 50 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 4)) | ||
| 51 | #define XUSB_PADCTL_SS_PORT_MAP_PORT_MAP_MASK 0x7 | ||
| 52 | |||
| 53 | #define XUSB_PADCTL_ELPG_PROGRAM 0x01c | ||
| 54 | #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) | ||
| 55 | #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) | ||
| 56 | #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) | ||
| 57 | #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4)) | ||
| 58 | #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \ | ||
| 59 | (1 << (17 + (x) * 4)) | ||
| 60 | #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4)) | ||
| 61 | |||
| 62 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 | ||
| 63 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) | ||
| 64 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) | ||
| 65 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) | ||
| 66 | |||
| 67 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 | ||
| 68 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) | ||
| 69 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) | ||
| 70 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) | ||
| 71 | |||
| 72 | #define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4) | ||
| 73 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24 | ||
| 74 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff | ||
| 75 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL 0x24 | ||
| 76 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16 | ||
| 77 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f | ||
| 78 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8 | ||
| 79 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f | ||
| 80 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8 | ||
| 81 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff | ||
| 82 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL 0xf070 | ||
| 83 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4 | ||
| 84 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0xf | ||
| 85 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL 0xf | ||
| 86 | |||
| 87 | #define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4) | ||
| 88 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24 | ||
| 89 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f | ||
| 90 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16 | ||
| 91 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f | ||
| 92 | #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL 0x002008ee | ||
| 93 | |||
| 94 | #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \ | ||
| 95 | 0x0f8 + (x) * 4) | ||
| 96 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28 | ||
| 97 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3 | ||
| 98 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL 0x1 | ||
| 99 | |||
| 100 | #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \ | ||
| 101 | 0x11c + (x) * 4) | ||
| 102 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8) | ||
| 103 | |||
| 104 | #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \ | ||
| 105 | 0x128 + (x) * 4) | ||
| 106 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24 | ||
| 107 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f | ||
| 108 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f | ||
| 109 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f | ||
| 110 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16 | ||
| 111 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff | ||
| 112 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21 | ||
| 113 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32 | ||
| 114 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33 | ||
| 115 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48 | ||
| 116 | #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1 | ||
| 117 | |||
| 118 | #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4) | ||
| 119 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21) | ||
| 120 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20) | ||
| 121 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19) | ||
| 122 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14 | ||
| 123 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3 | ||
| 124 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(x) ((x) ? 0x0 : 0x3) | ||
| 125 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6 | ||
| 126 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f | ||
| 127 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL 0x0e | ||
| 128 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 | ||
| 129 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f | ||
| 130 | |||
| 131 | #define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4) | ||
| 132 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9 | ||
| 133 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3 | ||
| 134 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 | ||
| 135 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7 | ||
| 136 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) | ||
| 137 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1) | ||
| 138 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0) | ||
| 139 | |||
| 140 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8 | ||
| 141 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12) | ||
| 142 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2 | ||
| 143 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 | ||
| 144 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x5 | ||
| 145 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 | ||
| 146 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3 | ||
| 147 | |||
| 148 | #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4) | ||
| 149 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12 | ||
| 150 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7 | ||
| 151 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8 | ||
| 152 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7 | ||
| 153 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4 | ||
| 154 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7 | ||
| 155 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0 | ||
| 156 | #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7 | ||
| 157 | |||
| 158 | #define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4) | ||
| 159 | #define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10) | ||
| 160 | #define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9) | ||
| 161 | #define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8) | ||
| 162 | #define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7) | ||
| 163 | #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5) | ||
| 164 | #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4) | ||
| 165 | #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3) | ||
| 166 | #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2) | ||
| 167 | #define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0) | ||
| 168 | |||
| 169 | #define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4) | ||
| 170 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4 | ||
| 171 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7 | ||
| 172 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 | ||
| 173 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7 | ||
| 174 | |||
| 175 | #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0 | ||
| 176 | #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f | ||
| 177 | |||
| 178 | #define XUSB_PADCTL_USB3_PAD_MUX 0x134 | ||
| 179 | #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) | ||
| 180 | #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (6 + (x))) | ||
| 181 | |||
| 182 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 | ||
| 183 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) | ||
| 184 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) | ||
| 185 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20 | ||
| 186 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3 | ||
| 187 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) | ||
| 188 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) | ||
| 189 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) | ||
| 190 | |||
| 191 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c | ||
| 192 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20 | ||
| 193 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf | ||
| 194 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16 | ||
| 195 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf | ||
| 196 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12) | ||
| 197 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4) | ||
| 198 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0 | ||
| 199 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7 | ||
| 200 | |||
| 201 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140 | ||
| 202 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7) | ||
| 203 | |||
| 204 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 | ||
| 205 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) | ||
| 206 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) | ||
| 207 | |||
| 208 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c | ||
| 209 | |||
| 210 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158 | ||
| 211 | |||
| 212 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c | ||
| 213 | |||
| 214 | struct tegra124_xusb_fuse_calibration { | ||
| 215 | u32 hs_curr_level[3]; | ||
| 216 | u32 hs_iref_cap; | ||
| 217 | u32 hs_term_range_adj; | ||
| 218 | u32 hs_squelch_level; | ||
| 219 | }; | ||
| 220 | |||
| 221 | struct tegra124_xusb_padctl { | ||
| 222 | struct tegra_xusb_padctl base; | ||
| 223 | |||
| 224 | struct tegra124_xusb_fuse_calibration fuse; | ||
| 225 | }; | ||
| 226 | |||
| 227 | static inline struct tegra124_xusb_padctl * | ||
| 228 | to_tegra124_xusb_padctl(struct tegra_xusb_padctl *padctl) | ||
| 229 | { | ||
| 230 | return container_of(padctl, struct tegra124_xusb_padctl, base); | ||
| 231 | } | ||
| 232 | |||
| 233 | static int tegra124_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) | ||
| 234 | { | ||
| 235 | u32 value; | ||
| 236 | |||
| 237 | mutex_lock(&padctl->lock); | ||
| 238 | |||
| 239 | if (padctl->enable++ > 0) | ||
| 240 | goto out; | ||
| 241 | |||
| 242 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 243 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; | ||
| 244 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 245 | |||
| 246 | usleep_range(100, 200); | ||
| 247 | |||
| 248 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 249 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; | ||
| 250 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 251 | |||
| 252 | usleep_range(100, 200); | ||
| 253 | |||
| 254 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 255 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; | ||
| 256 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 257 | |||
| 258 | out: | ||
| 259 | mutex_unlock(&padctl->lock); | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int tegra124_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) | ||
| 264 | { | ||
| 265 | u32 value; | ||
| 266 | |||
| 267 | mutex_lock(&padctl->lock); | ||
| 268 | |||
| 269 | if (WARN_ON(padctl->enable == 0)) | ||
| 270 | goto out; | ||
| 271 | |||
| 272 | if (--padctl->enable > 0) | ||
| 273 | goto out; | ||
| 274 | |||
| 275 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 276 | value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; | ||
| 277 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 278 | |||
| 279 | usleep_range(100, 200); | ||
| 280 | |||
| 281 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 282 | value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; | ||
| 283 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 284 | |||
| 285 | usleep_range(100, 200); | ||
| 286 | |||
| 287 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 288 | value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; | ||
| 289 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 290 | |||
| 291 | out: | ||
| 292 | mutex_unlock(&padctl->lock); | ||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int tegra124_usb3_save_context(struct tegra_xusb_padctl *padctl, | ||
| 297 | unsigned int index) | ||
| 298 | { | ||
| 299 | struct tegra_xusb_usb3_port *port; | ||
| 300 | struct tegra_xusb_lane *lane; | ||
| 301 | u32 value, offset; | ||
| 302 | |||
| 303 | port = tegra_xusb_find_usb3_port(padctl, index); | ||
| 304 | if (!port) | ||
| 305 | return -ENODEV; | ||
| 306 | |||
| 307 | port->context_saved = true; | ||
| 308 | lane = port->base.lane; | ||
| 309 | |||
| 310 | if (lane->pad == padctl->pcie) | ||
| 311 | offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane->index); | ||
| 312 | else | ||
| 313 | offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6; | ||
| 314 | |||
| 315 | value = padctl_readl(padctl, offset); | ||
| 316 | value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << | ||
| 317 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); | ||
| 318 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP << | ||
| 319 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; | ||
| 320 | padctl_writel(padctl, value, offset); | ||
| 321 | |||
| 322 | value = padctl_readl(padctl, offset) >> | ||
| 323 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; | ||
| 324 | port->tap1 = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK; | ||
| 325 | |||
| 326 | value = padctl_readl(padctl, offset); | ||
| 327 | value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << | ||
| 328 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); | ||
| 329 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP << | ||
| 330 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; | ||
| 331 | padctl_writel(padctl, value, offset); | ||
| 332 | |||
| 333 | value = padctl_readl(padctl, offset) >> | ||
| 334 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; | ||
| 335 | port->amp = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK; | ||
| 336 | |||
| 337 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); | ||
| 338 | value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << | ||
| 339 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | | ||
| 340 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << | ||
| 341 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); | ||
| 342 | value |= (port->tap1 << | ||
| 343 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | | ||
| 344 | (port->amp << | ||
| 345 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); | ||
| 346 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); | ||
| 347 | |||
| 348 | value = padctl_readl(padctl, offset); | ||
| 349 | value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << | ||
| 350 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); | ||
| 351 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z << | ||
| 352 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; | ||
| 353 | padctl_writel(padctl, value, offset); | ||
| 354 | |||
| 355 | value = padctl_readl(padctl, offset); | ||
| 356 | value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << | ||
| 357 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); | ||
| 358 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z << | ||
| 359 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; | ||
| 360 | padctl_writel(padctl, value, offset); | ||
| 361 | |||
| 362 | value = padctl_readl(padctl, offset) >> | ||
| 363 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; | ||
| 364 | port->ctle_g = value & | ||
| 365 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; | ||
| 366 | |||
| 367 | value = padctl_readl(padctl, offset); | ||
| 368 | value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << | ||
| 369 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); | ||
| 370 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z << | ||
| 371 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; | ||
| 372 | padctl_writel(padctl, value, offset); | ||
| 373 | |||
| 374 | value = padctl_readl(padctl, offset) >> | ||
| 375 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; | ||
| 376 | port->ctle_z = value & | ||
| 377 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; | ||
| 378 | |||
| 379 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); | ||
| 380 | value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << | ||
| 381 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | | ||
| 382 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << | ||
| 383 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); | ||
| 384 | value |= (port->ctle_g << | ||
| 385 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | | ||
| 386 | (port->ctle_z << | ||
| 387 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); | ||
| 388 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); | ||
| 389 | |||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | static int tegra124_hsic_set_idle(struct tegra_xusb_padctl *padctl, | ||
| 394 | unsigned int index, bool idle) | ||
| 395 | { | ||
| 396 | u32 value; | ||
| 397 | |||
| 398 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 399 | |||
| 400 | if (idle) | ||
| 401 | value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | | ||
| 402 | XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; | ||
| 403 | else | ||
| 404 | value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | | ||
| 405 | XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE); | ||
| 406 | |||
| 407 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | |||
| 412 | #define TEGRA124_LANE(_name, _offset, _shift, _mask, _type) \ | ||
| 413 | { \ | ||
| 414 | .name = _name, \ | ||
| 415 | .offset = _offset, \ | ||
| 416 | .shift = _shift, \ | ||
| 417 | .mask = _mask, \ | ||
| 418 | .num_funcs = ARRAY_SIZE(tegra124_##_type##_functions), \ | ||
| 419 | .funcs = tegra124_##_type##_functions, \ | ||
| 420 | } | ||
| 421 | |||
| 422 | static const char * const tegra124_usb2_functions[] = { | ||
| 423 | "snps", | ||
| 424 | "xusb", | ||
| 425 | "uart", | ||
| 426 | }; | ||
| 427 | |||
| 428 | static const struct tegra_xusb_lane_soc tegra124_usb2_lanes[] = { | ||
| 429 | TEGRA124_LANE("usb2-0", 0x004, 0, 0x3, usb2), | ||
| 430 | TEGRA124_LANE("usb2-1", 0x004, 2, 0x3, usb2), | ||
| 431 | TEGRA124_LANE("usb2-2", 0x004, 4, 0x3, usb2), | ||
| 432 | }; | ||
| 433 | |||
| 434 | static struct tegra_xusb_lane * | ||
| 435 | tegra124_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 436 | unsigned int index) | ||
| 437 | { | ||
| 438 | struct tegra_xusb_usb2_lane *usb2; | ||
| 439 | int err; | ||
| 440 | |||
| 441 | usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); | ||
| 442 | if (!usb2) | ||
| 443 | return ERR_PTR(-ENOMEM); | ||
| 444 | |||
| 445 | INIT_LIST_HEAD(&usb2->base.list); | ||
| 446 | usb2->base.soc = &pad->soc->lanes[index]; | ||
| 447 | usb2->base.index = index; | ||
| 448 | usb2->base.pad = pad; | ||
| 449 | usb2->base.np = np; | ||
| 450 | |||
| 451 | err = tegra_xusb_lane_parse_dt(&usb2->base, np); | ||
| 452 | if (err < 0) { | ||
| 453 | kfree(usb2); | ||
| 454 | return ERR_PTR(err); | ||
| 455 | } | ||
| 456 | |||
| 457 | return &usb2->base; | ||
| 458 | } | ||
| 459 | |||
| 460 | static void tegra124_usb2_lane_remove(struct tegra_xusb_lane *lane) | ||
| 461 | { | ||
| 462 | struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); | ||
| 463 | |||
| 464 | kfree(usb2); | ||
| 465 | } | ||
| 466 | |||
| 467 | static const struct tegra_xusb_lane_ops tegra124_usb2_lane_ops = { | ||
| 468 | .probe = tegra124_usb2_lane_probe, | ||
| 469 | .remove = tegra124_usb2_lane_remove, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static int tegra124_usb2_phy_init(struct phy *phy) | ||
| 473 | { | ||
| 474 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 475 | |||
| 476 | return tegra124_xusb_padctl_enable(lane->pad->padctl); | ||
| 477 | } | ||
| 478 | |||
| 479 | static int tegra124_usb2_phy_exit(struct phy *phy) | ||
| 480 | { | ||
| 481 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 482 | |||
| 483 | return tegra124_xusb_padctl_disable(lane->pad->padctl); | ||
| 484 | } | ||
| 485 | |||
| 486 | static int tegra124_usb2_phy_power_on(struct phy *phy) | ||
| 487 | { | ||
| 488 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 489 | struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); | ||
| 490 | struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); | ||
| 491 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 492 | struct tegra124_xusb_padctl *priv; | ||
| 493 | struct tegra_xusb_usb2_port *port; | ||
| 494 | unsigned int index = lane->index; | ||
| 495 | u32 value; | ||
| 496 | int err; | ||
| 497 | |||
| 498 | port = tegra_xusb_find_usb2_port(padctl, index); | ||
| 499 | if (!port) { | ||
| 500 | dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); | ||
| 501 | return -ENODEV; | ||
| 502 | } | ||
| 503 | |||
| 504 | priv = to_tegra124_xusb_padctl(padctl); | ||
| 505 | |||
| 506 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 507 | value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << | ||
| 508 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | | ||
| 509 | (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << | ||
| 510 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); | ||
| 511 | value |= (priv->fuse.hs_squelch_level << | ||
| 512 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | | ||
| 513 | (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << | ||
| 514 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); | ||
| 515 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 516 | |||
| 517 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); | ||
| 518 | value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK << | ||
| 519 | XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index)); | ||
| 520 | value |= XUSB_PADCTL_USB2_PORT_CAP_HOST << | ||
| 521 | XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index); | ||
| 522 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); | ||
| 523 | |||
| 524 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); | ||
| 525 | value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << | ||
| 526 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | | ||
| 527 | (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK << | ||
| 528 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) | | ||
| 529 | (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK << | ||
| 530 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) | | ||
| 531 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | | ||
| 532 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | | ||
| 533 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); | ||
| 534 | value |= (priv->fuse.hs_curr_level[index] + | ||
| 535 | usb2->hs_curr_level_offset) << | ||
| 536 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; | ||
| 537 | value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL << | ||
| 538 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT; | ||
| 539 | value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(index) << | ||
| 540 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT; | ||
| 541 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); | ||
| 542 | |||
| 543 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); | ||
| 544 | value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << | ||
| 545 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | | ||
| 546 | (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK << | ||
| 547 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) | | ||
| 548 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | | ||
| 549 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP | | ||
| 550 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP); | ||
| 551 | value |= (priv->fuse.hs_term_range_adj << | ||
| 552 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | | ||
| 553 | (priv->fuse.hs_iref_cap << | ||
| 554 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT); | ||
| 555 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); | ||
| 556 | |||
| 557 | err = regulator_enable(port->supply); | ||
| 558 | if (err) | ||
| 559 | return err; | ||
| 560 | |||
| 561 | mutex_lock(&pad->lock); | ||
| 562 | |||
| 563 | if (pad->enable++ > 0) | ||
| 564 | goto out; | ||
| 565 | |||
| 566 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 567 | value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; | ||
| 568 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 569 | |||
| 570 | out: | ||
| 571 | mutex_unlock(&pad->lock); | ||
| 572 | return 0; | ||
| 573 | } | ||
| 574 | |||
| 575 | static int tegra124_usb2_phy_power_off(struct phy *phy) | ||
| 576 | { | ||
| 577 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 578 | struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); | ||
| 579 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 580 | struct tegra_xusb_usb2_port *port; | ||
| 581 | u32 value; | ||
| 582 | |||
| 583 | port = tegra_xusb_find_usb2_port(padctl, lane->index); | ||
| 584 | if (!port) { | ||
| 585 | dev_err(&phy->dev, "no port found for USB2 lane %u\n", | ||
| 586 | lane->index); | ||
| 587 | return -ENODEV; | ||
| 588 | } | ||
| 589 | |||
| 590 | mutex_lock(&pad->lock); | ||
| 591 | |||
| 592 | if (WARN_ON(pad->enable == 0)) | ||
| 593 | goto out; | ||
| 594 | |||
| 595 | if (--pad->enable > 0) | ||
| 596 | goto out; | ||
| 597 | |||
| 598 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 599 | value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; | ||
| 600 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 601 | |||
| 602 | out: | ||
| 603 | regulator_disable(port->supply); | ||
| 604 | mutex_unlock(&pad->lock); | ||
| 605 | return 0; | ||
| 606 | } | ||
| 607 | |||
| 608 | static const struct phy_ops tegra124_usb2_phy_ops = { | ||
| 609 | .init = tegra124_usb2_phy_init, | ||
| 610 | .exit = tegra124_usb2_phy_exit, | ||
| 611 | .power_on = tegra124_usb2_phy_power_on, | ||
| 612 | .power_off = tegra124_usb2_phy_power_off, | ||
| 613 | .owner = THIS_MODULE, | ||
| 614 | }; | ||
| 615 | |||
| 616 | static struct tegra_xusb_pad * | ||
| 617 | tegra124_usb2_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 618 | const struct tegra_xusb_pad_soc *soc, | ||
| 619 | struct device_node *np) | ||
| 620 | { | ||
| 621 | struct tegra_xusb_usb2_pad *usb2; | ||
| 622 | struct tegra_xusb_pad *pad; | ||
| 623 | int err; | ||
| 624 | |||
| 625 | usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); | ||
| 626 | if (!usb2) | ||
| 627 | return ERR_PTR(-ENOMEM); | ||
| 628 | |||
| 629 | mutex_init(&usb2->lock); | ||
| 630 | |||
| 631 | pad = &usb2->base; | ||
| 632 | pad->ops = &tegra124_usb2_lane_ops; | ||
| 633 | pad->soc = soc; | ||
| 634 | |||
| 635 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 636 | if (err < 0) { | ||
| 637 | kfree(usb2); | ||
| 638 | goto out; | ||
| 639 | } | ||
| 640 | |||
| 641 | err = tegra_xusb_pad_register(pad, &tegra124_usb2_phy_ops); | ||
| 642 | if (err < 0) | ||
| 643 | goto unregister; | ||
| 644 | |||
| 645 | dev_set_drvdata(&pad->dev, pad); | ||
| 646 | |||
| 647 | return pad; | ||
| 648 | |||
| 649 | unregister: | ||
| 650 | device_unregister(&pad->dev); | ||
| 651 | out: | ||
| 652 | return ERR_PTR(err); | ||
| 653 | } | ||
| 654 | |||
| 655 | static void tegra124_usb2_pad_remove(struct tegra_xusb_pad *pad) | ||
| 656 | { | ||
| 657 | struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); | ||
| 658 | |||
| 659 | kfree(usb2); | ||
| 660 | } | ||
| 661 | |||
| 662 | static const struct tegra_xusb_pad_ops tegra124_usb2_ops = { | ||
| 663 | .probe = tegra124_usb2_pad_probe, | ||
| 664 | .remove = tegra124_usb2_pad_remove, | ||
| 665 | }; | ||
| 666 | |||
| 667 | static const struct tegra_xusb_pad_soc tegra124_usb2_pad = { | ||
| 668 | .name = "usb2", | ||
| 669 | .num_lanes = ARRAY_SIZE(tegra124_usb2_lanes), | ||
| 670 | .lanes = tegra124_usb2_lanes, | ||
| 671 | .ops = &tegra124_usb2_ops, | ||
| 672 | }; | ||
| 673 | |||
| 674 | static const char * const tegra124_ulpi_functions[] = { | ||
| 675 | "snps", | ||
| 676 | "xusb", | ||
| 677 | }; | ||
| 678 | |||
| 679 | static const struct tegra_xusb_lane_soc tegra124_ulpi_lanes[] = { | ||
| 680 | TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, ulpi), | ||
| 681 | }; | ||
| 682 | |||
| 683 | static struct tegra_xusb_lane * | ||
| 684 | tegra124_ulpi_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 685 | unsigned int index) | ||
| 686 | { | ||
| 687 | struct tegra_xusb_ulpi_lane *ulpi; | ||
| 688 | int err; | ||
| 689 | |||
| 690 | ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); | ||
| 691 | if (!ulpi) | ||
| 692 | return ERR_PTR(-ENOMEM); | ||
| 693 | |||
| 694 | INIT_LIST_HEAD(&ulpi->base.list); | ||
| 695 | ulpi->base.soc = &pad->soc->lanes[index]; | ||
| 696 | ulpi->base.index = index; | ||
| 697 | ulpi->base.pad = pad; | ||
| 698 | ulpi->base.np = np; | ||
| 699 | |||
| 700 | err = tegra_xusb_lane_parse_dt(&ulpi->base, np); | ||
| 701 | if (err < 0) { | ||
| 702 | kfree(ulpi); | ||
| 703 | return ERR_PTR(err); | ||
| 704 | } | ||
| 705 | |||
| 706 | return &ulpi->base; | ||
| 707 | } | ||
| 708 | |||
| 709 | static void tegra124_ulpi_lane_remove(struct tegra_xusb_lane *lane) | ||
| 710 | { | ||
| 711 | struct tegra_xusb_ulpi_lane *ulpi = to_ulpi_lane(lane); | ||
| 712 | |||
| 713 | kfree(ulpi); | ||
| 714 | } | ||
| 715 | |||
| 716 | static const struct tegra_xusb_lane_ops tegra124_ulpi_lane_ops = { | ||
| 717 | .probe = tegra124_ulpi_lane_probe, | ||
| 718 | .remove = tegra124_ulpi_lane_remove, | ||
| 719 | }; | ||
| 720 | |||
| 721 | static int tegra124_ulpi_phy_init(struct phy *phy) | ||
| 722 | { | ||
| 723 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 724 | |||
| 725 | return tegra124_xusb_padctl_enable(lane->pad->padctl); | ||
| 726 | } | ||
| 727 | |||
| 728 | static int tegra124_ulpi_phy_exit(struct phy *phy) | ||
| 729 | { | ||
| 730 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 731 | |||
| 732 | return tegra124_xusb_padctl_disable(lane->pad->padctl); | ||
| 733 | } | ||
| 734 | |||
| 735 | static int tegra124_ulpi_phy_power_on(struct phy *phy) | ||
| 736 | { | ||
| 737 | return 0; | ||
| 738 | } | ||
| 739 | |||
| 740 | static int tegra124_ulpi_phy_power_off(struct phy *phy) | ||
| 741 | { | ||
| 742 | return 0; | ||
| 743 | } | ||
| 744 | |||
| 745 | static const struct phy_ops tegra124_ulpi_phy_ops = { | ||
| 746 | .init = tegra124_ulpi_phy_init, | ||
| 747 | .exit = tegra124_ulpi_phy_exit, | ||
| 748 | .power_on = tegra124_ulpi_phy_power_on, | ||
| 749 | .power_off = tegra124_ulpi_phy_power_off, | ||
| 750 | .owner = THIS_MODULE, | ||
| 751 | }; | ||
| 752 | |||
| 753 | static struct tegra_xusb_pad * | ||
| 754 | tegra124_ulpi_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 755 | const struct tegra_xusb_pad_soc *soc, | ||
| 756 | struct device_node *np) | ||
| 757 | { | ||
| 758 | struct tegra_xusb_ulpi_pad *ulpi; | ||
| 759 | struct tegra_xusb_pad *pad; | ||
| 760 | int err; | ||
| 761 | |||
| 762 | ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); | ||
| 763 | if (!ulpi) | ||
| 764 | return ERR_PTR(-ENOMEM); | ||
| 765 | |||
| 766 | pad = &ulpi->base; | ||
| 767 | pad->ops = &tegra124_ulpi_lane_ops; | ||
| 768 | pad->soc = soc; | ||
| 769 | |||
| 770 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 771 | if (err < 0) { | ||
| 772 | kfree(ulpi); | ||
| 773 | goto out; | ||
| 774 | } | ||
| 775 | |||
| 776 | err = tegra_xusb_pad_register(pad, &tegra124_ulpi_phy_ops); | ||
| 777 | if (err < 0) | ||
| 778 | goto unregister; | ||
| 779 | |||
| 780 | dev_set_drvdata(&pad->dev, pad); | ||
| 781 | |||
| 782 | return pad; | ||
| 783 | |||
| 784 | unregister: | ||
| 785 | device_unregister(&pad->dev); | ||
| 786 | out: | ||
| 787 | return ERR_PTR(err); | ||
| 788 | } | ||
| 789 | |||
| 790 | static void tegra124_ulpi_pad_remove(struct tegra_xusb_pad *pad) | ||
| 791 | { | ||
| 792 | struct tegra_xusb_ulpi_pad *ulpi = to_ulpi_pad(pad); | ||
| 793 | |||
| 794 | kfree(ulpi); | ||
| 795 | } | ||
| 796 | |||
| 797 | static const struct tegra_xusb_pad_ops tegra124_ulpi_ops = { | ||
| 798 | .probe = tegra124_ulpi_pad_probe, | ||
| 799 | .remove = tegra124_ulpi_pad_remove, | ||
| 800 | }; | ||
| 801 | |||
| 802 | static const struct tegra_xusb_pad_soc tegra124_ulpi_pad = { | ||
| 803 | .name = "ulpi", | ||
| 804 | .num_lanes = ARRAY_SIZE(tegra124_ulpi_lanes), | ||
| 805 | .lanes = tegra124_ulpi_lanes, | ||
| 806 | .ops = &tegra124_ulpi_ops, | ||
| 807 | }; | ||
| 808 | |||
| 809 | static const char * const tegra124_hsic_functions[] = { | ||
| 810 | "snps", | ||
| 811 | "xusb", | ||
| 812 | }; | ||
| 813 | |||
| 814 | static const struct tegra_xusb_lane_soc tegra124_hsic_lanes[] = { | ||
| 815 | TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, hsic), | ||
| 816 | TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, hsic), | ||
| 817 | }; | ||
| 818 | |||
| 819 | static struct tegra_xusb_lane * | ||
| 820 | tegra124_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 821 | unsigned int index) | ||
| 822 | { | ||
| 823 | struct tegra_xusb_hsic_lane *hsic; | ||
| 824 | int err; | ||
| 825 | |||
| 826 | hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); | ||
| 827 | if (!hsic) | ||
| 828 | return ERR_PTR(-ENOMEM); | ||
| 829 | |||
| 830 | INIT_LIST_HEAD(&hsic->base.list); | ||
| 831 | hsic->base.soc = &pad->soc->lanes[index]; | ||
| 832 | hsic->base.index = index; | ||
| 833 | hsic->base.pad = pad; | ||
| 834 | hsic->base.np = np; | ||
| 835 | |||
| 836 | err = tegra_xusb_lane_parse_dt(&hsic->base, np); | ||
| 837 | if (err < 0) { | ||
| 838 | kfree(hsic); | ||
| 839 | return ERR_PTR(err); | ||
| 840 | } | ||
| 841 | |||
| 842 | return &hsic->base; | ||
| 843 | } | ||
| 844 | |||
| 845 | static void tegra124_hsic_lane_remove(struct tegra_xusb_lane *lane) | ||
| 846 | { | ||
| 847 | struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); | ||
| 848 | |||
| 849 | kfree(hsic); | ||
| 850 | } | ||
| 851 | |||
| 852 | static const struct tegra_xusb_lane_ops tegra124_hsic_lane_ops = { | ||
| 853 | .probe = tegra124_hsic_lane_probe, | ||
| 854 | .remove = tegra124_hsic_lane_remove, | ||
| 855 | }; | ||
| 856 | |||
| 857 | static int tegra124_hsic_phy_init(struct phy *phy) | ||
| 858 | { | ||
| 859 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 860 | |||
| 861 | return tegra124_xusb_padctl_enable(lane->pad->padctl); | ||
| 862 | } | ||
| 863 | |||
| 864 | static int tegra124_hsic_phy_exit(struct phy *phy) | ||
| 865 | { | ||
| 866 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 867 | |||
| 868 | return tegra124_xusb_padctl_disable(lane->pad->padctl); | ||
| 869 | } | ||
| 870 | |||
| 871 | static int tegra124_hsic_phy_power_on(struct phy *phy) | ||
| 872 | { | ||
| 873 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 874 | struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); | ||
| 875 | struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); | ||
| 876 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 877 | unsigned int index = lane->index; | ||
| 878 | u32 value; | ||
| 879 | int err; | ||
| 880 | |||
| 881 | err = regulator_enable(pad->supply); | ||
| 882 | if (err) | ||
| 883 | return err; | ||
| 884 | |||
| 885 | padctl_writel(padctl, hsic->strobe_trim, | ||
| 886 | XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); | ||
| 887 | |||
| 888 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 889 | |||
| 890 | if (hsic->auto_term) | ||
| 891 | value |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; | ||
| 892 | else | ||
| 893 | value &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; | ||
| 894 | |||
| 895 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 896 | |||
| 897 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 898 | value &= ~((XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK << | ||
| 899 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | | ||
| 900 | (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK << | ||
| 901 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | | ||
| 902 | (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK << | ||
| 903 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | | ||
| 904 | (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK << | ||
| 905 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT)); | ||
| 906 | value |= (hsic->tx_rtune_n << | ||
| 907 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | | ||
| 908 | (hsic->tx_rtune_p << | ||
| 909 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | | ||
| 910 | (hsic->tx_rslew_n << | ||
| 911 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | | ||
| 912 | (hsic->tx_rslew_p << | ||
| 913 | XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT); | ||
| 914 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 915 | |||
| 916 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); | ||
| 917 | value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << | ||
| 918 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | | ||
| 919 | (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << | ||
| 920 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); | ||
| 921 | value |= (hsic->rx_strobe_trim << | ||
| 922 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | | ||
| 923 | (hsic->rx_data_trim << | ||
| 924 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); | ||
| 925 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); | ||
| 926 | |||
| 927 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 928 | value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE | | ||
| 929 | XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA | | ||
| 930 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | | ||
| 931 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | | ||
| 932 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | | ||
| 933 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX); | ||
| 934 | value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | | ||
| 935 | XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; | ||
| 936 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 937 | |||
| 938 | return 0; | ||
| 939 | } | ||
| 940 | |||
| 941 | static int tegra124_hsic_phy_power_off(struct phy *phy) | ||
| 942 | { | ||
| 943 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 944 | struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); | ||
| 945 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 946 | unsigned int index = lane->index; | ||
| 947 | u32 value; | ||
| 948 | |||
| 949 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 950 | value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | | ||
| 951 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | | ||
| 952 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | | ||
| 953 | XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX; | ||
| 954 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 955 | |||
| 956 | regulator_disable(pad->supply); | ||
| 957 | |||
| 958 | return 0; | ||
| 959 | } | ||
| 960 | |||
| 961 | static const struct phy_ops tegra124_hsic_phy_ops = { | ||
| 962 | .init = tegra124_hsic_phy_init, | ||
| 963 | .exit = tegra124_hsic_phy_exit, | ||
| 964 | .power_on = tegra124_hsic_phy_power_on, | ||
| 965 | .power_off = tegra124_hsic_phy_power_off, | ||
| 966 | .owner = THIS_MODULE, | ||
| 967 | }; | ||
| 968 | |||
| 969 | static struct tegra_xusb_pad * | ||
| 970 | tegra124_hsic_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 971 | const struct tegra_xusb_pad_soc *soc, | ||
| 972 | struct device_node *np) | ||
| 973 | { | ||
| 974 | struct tegra_xusb_hsic_pad *hsic; | ||
| 975 | struct tegra_xusb_pad *pad; | ||
| 976 | int err; | ||
| 977 | |||
| 978 | hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); | ||
| 979 | if (!hsic) | ||
| 980 | return ERR_PTR(-ENOMEM); | ||
| 981 | |||
| 982 | pad = &hsic->base; | ||
| 983 | pad->ops = &tegra124_hsic_lane_ops; | ||
| 984 | pad->soc = soc; | ||
| 985 | |||
| 986 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 987 | if (err < 0) { | ||
| 988 | kfree(hsic); | ||
| 989 | goto out; | ||
| 990 | } | ||
| 991 | |||
| 992 | err = tegra_xusb_pad_register(pad, &tegra124_hsic_phy_ops); | ||
| 993 | if (err < 0) | ||
| 994 | goto unregister; | ||
| 995 | |||
| 996 | dev_set_drvdata(&pad->dev, pad); | ||
| 997 | |||
| 998 | return pad; | ||
| 999 | |||
| 1000 | unregister: | ||
| 1001 | device_unregister(&pad->dev); | ||
| 1002 | out: | ||
| 1003 | return ERR_PTR(err); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | static void tegra124_hsic_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1007 | { | ||
| 1008 | struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); | ||
| 1009 | |||
| 1010 | kfree(hsic); | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | static const struct tegra_xusb_pad_ops tegra124_hsic_ops = { | ||
| 1014 | .probe = tegra124_hsic_pad_probe, | ||
| 1015 | .remove = tegra124_hsic_pad_remove, | ||
| 1016 | }; | ||
| 1017 | |||
| 1018 | static const struct tegra_xusb_pad_soc tegra124_hsic_pad = { | ||
| 1019 | .name = "hsic", | ||
| 1020 | .num_lanes = ARRAY_SIZE(tegra124_hsic_lanes), | ||
| 1021 | .lanes = tegra124_hsic_lanes, | ||
| 1022 | .ops = &tegra124_hsic_ops, | ||
| 1023 | }; | ||
| 1024 | |||
| 1025 | static const char * const tegra124_pcie_functions[] = { | ||
| 1026 | "pcie", | ||
| 1027 | "usb3-ss", | ||
| 1028 | "sata", | ||
| 1029 | }; | ||
| 1030 | |||
| 1031 | static const struct tegra_xusb_lane_soc tegra124_pcie_lanes[] = { | ||
| 1032 | TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, pcie), | ||
| 1033 | TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, pcie), | ||
| 1034 | TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, pcie), | ||
| 1035 | TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, pcie), | ||
| 1036 | TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, pcie), | ||
| 1037 | }; | ||
| 1038 | |||
| 1039 | static struct tegra_xusb_lane * | ||
| 1040 | tegra124_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 1041 | unsigned int index) | ||
| 1042 | { | ||
| 1043 | struct tegra_xusb_pcie_lane *pcie; | ||
| 1044 | int err; | ||
| 1045 | |||
| 1046 | pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); | ||
| 1047 | if (!pcie) | ||
| 1048 | return ERR_PTR(-ENOMEM); | ||
| 1049 | |||
| 1050 | INIT_LIST_HEAD(&pcie->base.list); | ||
| 1051 | pcie->base.soc = &pad->soc->lanes[index]; | ||
| 1052 | pcie->base.index = index; | ||
| 1053 | pcie->base.pad = pad; | ||
| 1054 | pcie->base.np = np; | ||
| 1055 | |||
| 1056 | err = tegra_xusb_lane_parse_dt(&pcie->base, np); | ||
| 1057 | if (err < 0) { | ||
| 1058 | kfree(pcie); | ||
| 1059 | return ERR_PTR(err); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | return &pcie->base; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | static void tegra124_pcie_lane_remove(struct tegra_xusb_lane *lane) | ||
| 1066 | { | ||
| 1067 | struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); | ||
| 1068 | |||
| 1069 | kfree(pcie); | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | static const struct tegra_xusb_lane_ops tegra124_pcie_lane_ops = { | ||
| 1073 | .probe = tegra124_pcie_lane_probe, | ||
| 1074 | .remove = tegra124_pcie_lane_remove, | ||
| 1075 | }; | ||
| 1076 | |||
| 1077 | static int tegra124_pcie_phy_init(struct phy *phy) | ||
| 1078 | { | ||
| 1079 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1080 | |||
| 1081 | return tegra124_xusb_padctl_enable(lane->pad->padctl); | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | static int tegra124_pcie_phy_exit(struct phy *phy) | ||
| 1085 | { | ||
| 1086 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1087 | |||
| 1088 | return tegra124_xusb_padctl_disable(lane->pad->padctl); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | static int tegra124_pcie_phy_power_on(struct phy *phy) | ||
| 1092 | { | ||
| 1093 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1094 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1095 | unsigned long timeout; | ||
| 1096 | int err = -ETIMEDOUT; | ||
| 1097 | u32 value; | ||
| 1098 | |||
| 1099 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1100 | value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; | ||
| 1101 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1102 | |||
| 1103 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); | ||
| 1104 | value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | | ||
| 1105 | XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | | ||
| 1106 | XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; | ||
| 1107 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); | ||
| 1108 | |||
| 1109 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1110 | value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; | ||
| 1111 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1112 | |||
| 1113 | timeout = jiffies + msecs_to_jiffies(50); | ||
| 1114 | |||
| 1115 | while (time_before(jiffies, timeout)) { | ||
| 1116 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1117 | if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { | ||
| 1118 | err = 0; | ||
| 1119 | break; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | usleep_range(100, 200); | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1126 | value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); | ||
| 1127 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1128 | |||
| 1129 | return err; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | static int tegra124_pcie_phy_power_off(struct phy *phy) | ||
| 1133 | { | ||
| 1134 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1135 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1136 | u32 value; | ||
| 1137 | |||
| 1138 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1139 | value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); | ||
| 1140 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1141 | |||
| 1142 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1143 | value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; | ||
| 1144 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | ||
| 1145 | |||
| 1146 | return 0; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | static const struct phy_ops tegra124_pcie_phy_ops = { | ||
| 1150 | .init = tegra124_pcie_phy_init, | ||
| 1151 | .exit = tegra124_pcie_phy_exit, | ||
| 1152 | .power_on = tegra124_pcie_phy_power_on, | ||
| 1153 | .power_off = tegra124_pcie_phy_power_off, | ||
| 1154 | .owner = THIS_MODULE, | ||
| 1155 | }; | ||
| 1156 | |||
| 1157 | static struct tegra_xusb_pad * | ||
| 1158 | tegra124_pcie_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 1159 | const struct tegra_xusb_pad_soc *soc, | ||
| 1160 | struct device_node *np) | ||
| 1161 | { | ||
| 1162 | struct tegra_xusb_pcie_pad *pcie; | ||
| 1163 | struct tegra_xusb_pad *pad; | ||
| 1164 | int err; | ||
| 1165 | |||
| 1166 | pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); | ||
| 1167 | if (!pcie) | ||
| 1168 | return ERR_PTR(-ENOMEM); | ||
| 1169 | |||
| 1170 | pad = &pcie->base; | ||
| 1171 | pad->ops = &tegra124_pcie_lane_ops; | ||
| 1172 | pad->soc = soc; | ||
| 1173 | |||
| 1174 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 1175 | if (err < 0) { | ||
| 1176 | kfree(pcie); | ||
| 1177 | goto out; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | err = tegra_xusb_pad_register(pad, &tegra124_pcie_phy_ops); | ||
| 1181 | if (err < 0) | ||
| 1182 | goto unregister; | ||
| 1183 | |||
| 1184 | dev_set_drvdata(&pad->dev, pad); | ||
| 1185 | |||
| 1186 | return pad; | ||
| 1187 | |||
| 1188 | unregister: | ||
| 1189 | device_unregister(&pad->dev); | ||
| 1190 | out: | ||
| 1191 | return ERR_PTR(err); | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | static void tegra124_pcie_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1195 | { | ||
| 1196 | struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); | ||
| 1197 | |||
| 1198 | kfree(pcie); | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | static const struct tegra_xusb_pad_ops tegra124_pcie_ops = { | ||
| 1202 | .probe = tegra124_pcie_pad_probe, | ||
| 1203 | .remove = tegra124_pcie_pad_remove, | ||
| 1204 | }; | ||
| 1205 | |||
| 1206 | static const struct tegra_xusb_pad_soc tegra124_pcie_pad = { | ||
| 1207 | .name = "pcie", | ||
| 1208 | .num_lanes = ARRAY_SIZE(tegra124_pcie_lanes), | ||
| 1209 | .lanes = tegra124_pcie_lanes, | ||
| 1210 | .ops = &tegra124_pcie_ops, | ||
| 1211 | }; | ||
| 1212 | |||
| 1213 | static const struct tegra_xusb_lane_soc tegra124_sata_lanes[] = { | ||
| 1214 | TEGRA124_LANE("sata-0", 0x134, 26, 0x3, pcie), | ||
| 1215 | }; | ||
| 1216 | |||
| 1217 | static struct tegra_xusb_lane * | ||
| 1218 | tegra124_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 1219 | unsigned int index) | ||
| 1220 | { | ||
| 1221 | struct tegra_xusb_sata_lane *sata; | ||
| 1222 | int err; | ||
| 1223 | |||
| 1224 | sata = kzalloc(sizeof(*sata), GFP_KERNEL); | ||
| 1225 | if (!sata) | ||
| 1226 | return ERR_PTR(-ENOMEM); | ||
| 1227 | |||
| 1228 | INIT_LIST_HEAD(&sata->base.list); | ||
| 1229 | sata->base.soc = &pad->soc->lanes[index]; | ||
| 1230 | sata->base.index = index; | ||
| 1231 | sata->base.pad = pad; | ||
| 1232 | sata->base.np = np; | ||
| 1233 | |||
| 1234 | err = tegra_xusb_lane_parse_dt(&sata->base, np); | ||
| 1235 | if (err < 0) { | ||
| 1236 | kfree(sata); | ||
| 1237 | return ERR_PTR(err); | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | return &sata->base; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | static void tegra124_sata_lane_remove(struct tegra_xusb_lane *lane) | ||
| 1244 | { | ||
| 1245 | struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); | ||
| 1246 | |||
| 1247 | kfree(sata); | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | static const struct tegra_xusb_lane_ops tegra124_sata_lane_ops = { | ||
| 1251 | .probe = tegra124_sata_lane_probe, | ||
| 1252 | .remove = tegra124_sata_lane_remove, | ||
| 1253 | }; | ||
| 1254 | |||
| 1255 | static int tegra124_sata_phy_init(struct phy *phy) | ||
| 1256 | { | ||
| 1257 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1258 | |||
| 1259 | return tegra124_xusb_padctl_enable(lane->pad->padctl); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | static int tegra124_sata_phy_exit(struct phy *phy) | ||
| 1263 | { | ||
| 1264 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1265 | |||
| 1266 | return tegra124_xusb_padctl_disable(lane->pad->padctl); | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static int tegra124_sata_phy_power_on(struct phy *phy) | ||
| 1270 | { | ||
| 1271 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1272 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1273 | unsigned long timeout; | ||
| 1274 | int err = -ETIMEDOUT; | ||
| 1275 | u32 value; | ||
| 1276 | |||
| 1277 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | ||
| 1278 | value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; | ||
| 1279 | value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; | ||
| 1280 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | ||
| 1281 | |||
| 1282 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1283 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; | ||
| 1284 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; | ||
| 1285 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1286 | |||
| 1287 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1288 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; | ||
| 1289 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1290 | |||
| 1291 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1292 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; | ||
| 1293 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1294 | |||
| 1295 | timeout = jiffies + msecs_to_jiffies(50); | ||
| 1296 | |||
| 1297 | while (time_before(jiffies, timeout)) { | ||
| 1298 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1299 | if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { | ||
| 1300 | err = 0; | ||
| 1301 | break; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | usleep_range(100, 200); | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1308 | value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); | ||
| 1309 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1310 | |||
| 1311 | return err; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | static int tegra124_sata_phy_power_off(struct phy *phy) | ||
| 1315 | { | ||
| 1316 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1317 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1318 | u32 value; | ||
| 1319 | |||
| 1320 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1321 | value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); | ||
| 1322 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1323 | |||
| 1324 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1325 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; | ||
| 1326 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1327 | |||
| 1328 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1329 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; | ||
| 1330 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1331 | |||
| 1332 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1333 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; | ||
| 1334 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; | ||
| 1335 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1336 | |||
| 1337 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | ||
| 1338 | value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; | ||
| 1339 | value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; | ||
| 1340 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | ||
| 1341 | |||
| 1342 | return 0; | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static const struct phy_ops tegra124_sata_phy_ops = { | ||
| 1346 | .init = tegra124_sata_phy_init, | ||
| 1347 | .exit = tegra124_sata_phy_exit, | ||
| 1348 | .power_on = tegra124_sata_phy_power_on, | ||
| 1349 | .power_off = tegra124_sata_phy_power_off, | ||
| 1350 | .owner = THIS_MODULE, | ||
| 1351 | }; | ||
| 1352 | |||
| 1353 | static struct tegra_xusb_pad * | ||
| 1354 | tegra124_sata_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 1355 | const struct tegra_xusb_pad_soc *soc, | ||
| 1356 | struct device_node *np) | ||
| 1357 | { | ||
| 1358 | struct tegra_xusb_sata_pad *sata; | ||
| 1359 | struct tegra_xusb_pad *pad; | ||
| 1360 | int err; | ||
| 1361 | |||
| 1362 | sata = kzalloc(sizeof(*sata), GFP_KERNEL); | ||
| 1363 | if (!sata) | ||
| 1364 | return ERR_PTR(-ENOMEM); | ||
| 1365 | |||
| 1366 | pad = &sata->base; | ||
| 1367 | pad->ops = &tegra124_sata_lane_ops; | ||
| 1368 | pad->soc = soc; | ||
| 1369 | |||
| 1370 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 1371 | if (err < 0) { | ||
| 1372 | kfree(sata); | ||
| 1373 | goto out; | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | err = tegra_xusb_pad_register(pad, &tegra124_sata_phy_ops); | ||
| 1377 | if (err < 0) | ||
| 1378 | goto unregister; | ||
| 1379 | |||
| 1380 | dev_set_drvdata(&pad->dev, pad); | ||
| 1381 | |||
| 1382 | return pad; | ||
| 1383 | |||
| 1384 | unregister: | ||
| 1385 | device_unregister(&pad->dev); | ||
| 1386 | out: | ||
| 1387 | return ERR_PTR(err); | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | static void tegra124_sata_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1391 | { | ||
| 1392 | struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); | ||
| 1393 | |||
| 1394 | kfree(sata); | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | static const struct tegra_xusb_pad_ops tegra124_sata_ops = { | ||
| 1398 | .probe = tegra124_sata_pad_probe, | ||
| 1399 | .remove = tegra124_sata_pad_remove, | ||
| 1400 | }; | ||
| 1401 | |||
| 1402 | static const struct tegra_xusb_pad_soc tegra124_sata_pad = { | ||
| 1403 | .name = "sata", | ||
| 1404 | .num_lanes = ARRAY_SIZE(tegra124_sata_lanes), | ||
| 1405 | .lanes = tegra124_sata_lanes, | ||
| 1406 | .ops = &tegra124_sata_ops, | ||
| 1407 | }; | ||
| 1408 | |||
| 1409 | static const struct tegra_xusb_pad_soc *tegra124_pads[] = { | ||
| 1410 | &tegra124_usb2_pad, | ||
| 1411 | &tegra124_ulpi_pad, | ||
| 1412 | &tegra124_hsic_pad, | ||
| 1413 | &tegra124_pcie_pad, | ||
| 1414 | &tegra124_sata_pad, | ||
| 1415 | }; | ||
| 1416 | |||
| 1417 | static int tegra124_usb2_port_enable(struct tegra_xusb_port *port) | ||
| 1418 | { | ||
| 1419 | return 0; | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | static void tegra124_usb2_port_disable(struct tegra_xusb_port *port) | ||
| 1423 | { | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | static struct tegra_xusb_lane * | ||
| 1427 | tegra124_usb2_port_map(struct tegra_xusb_port *port) | ||
| 1428 | { | ||
| 1429 | return tegra_xusb_find_lane(port->padctl, "usb2", port->index); | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | static const struct tegra_xusb_port_ops tegra124_usb2_port_ops = { | ||
| 1433 | .enable = tegra124_usb2_port_enable, | ||
| 1434 | .disable = tegra124_usb2_port_disable, | ||
| 1435 | .map = tegra124_usb2_port_map, | ||
| 1436 | }; | ||
| 1437 | |||
| 1438 | static int tegra124_ulpi_port_enable(struct tegra_xusb_port *port) | ||
| 1439 | { | ||
| 1440 | return 0; | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | static void tegra124_ulpi_port_disable(struct tegra_xusb_port *port) | ||
| 1444 | { | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | static struct tegra_xusb_lane * | ||
| 1448 | tegra124_ulpi_port_map(struct tegra_xusb_port *port) | ||
| 1449 | { | ||
| 1450 | return tegra_xusb_find_lane(port->padctl, "ulpi", port->index); | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | static const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = { | ||
| 1454 | .enable = tegra124_ulpi_port_enable, | ||
| 1455 | .disable = tegra124_ulpi_port_disable, | ||
| 1456 | .map = tegra124_ulpi_port_map, | ||
| 1457 | }; | ||
| 1458 | |||
| 1459 | static int tegra124_hsic_port_enable(struct tegra_xusb_port *port) | ||
| 1460 | { | ||
| 1461 | return 0; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | static void tegra124_hsic_port_disable(struct tegra_xusb_port *port) | ||
| 1465 | { | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | static struct tegra_xusb_lane * | ||
| 1469 | tegra124_hsic_port_map(struct tegra_xusb_port *port) | ||
| 1470 | { | ||
| 1471 | return tegra_xusb_find_lane(port->padctl, "hsic", port->index); | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | static const struct tegra_xusb_port_ops tegra124_hsic_port_ops = { | ||
| 1475 | .enable = tegra124_hsic_port_enable, | ||
| 1476 | .disable = tegra124_hsic_port_disable, | ||
| 1477 | .map = tegra124_hsic_port_map, | ||
| 1478 | }; | ||
| 1479 | |||
| 1480 | static int tegra124_usb3_port_enable(struct tegra_xusb_port *port) | ||
| 1481 | { | ||
| 1482 | struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); | ||
| 1483 | struct tegra_xusb_padctl *padctl = port->padctl; | ||
| 1484 | struct tegra_xusb_lane *lane = usb3->base.lane; | ||
| 1485 | unsigned int index = port->index, offset; | ||
| 1486 | int ret = 0; | ||
| 1487 | u32 value; | ||
| 1488 | |||
| 1489 | value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1490 | |||
| 1491 | if (!usb3->internal) | ||
| 1492 | value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); | ||
| 1493 | else | ||
| 1494 | value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); | ||
| 1495 | |||
| 1496 | value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); | ||
| 1497 | value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); | ||
| 1498 | padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1499 | |||
| 1500 | /* | ||
| 1501 | * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks | ||
| 1502 | * and conditionalize based on mux function? This seems to work, but | ||
| 1503 | * might not be the exact proper sequence. | ||
| 1504 | */ | ||
| 1505 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); | ||
| 1506 | value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK << | ||
| 1507 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | | ||
| 1508 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK << | ||
| 1509 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) | | ||
| 1510 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK << | ||
| 1511 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT)); | ||
| 1512 | value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL << | ||
| 1513 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | | ||
| 1514 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL << | ||
| 1515 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) | | ||
| 1516 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL << | ||
| 1517 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT); | ||
| 1518 | |||
| 1519 | if (usb3->context_saved) { | ||
| 1520 | value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << | ||
| 1521 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | | ||
| 1522 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << | ||
| 1523 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); | ||
| 1524 | value |= (usb3->ctle_g << | ||
| 1525 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | | ||
| 1526 | (usb3->ctle_z << | ||
| 1527 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); | ||
| 1531 | |||
| 1532 | value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL; | ||
| 1533 | |||
| 1534 | if (usb3->context_saved) { | ||
| 1535 | value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << | ||
| 1536 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | | ||
| 1537 | (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << | ||
| 1538 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); | ||
| 1539 | value |= (usb3->tap1 << | ||
| 1540 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | | ||
| 1541 | (usb3->amp << | ||
| 1542 | XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); | ||
| 1546 | |||
| 1547 | if (lane->pad == padctl->pcie) | ||
| 1548 | offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index); | ||
| 1549 | else | ||
| 1550 | offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2; | ||
| 1551 | |||
| 1552 | value = padctl_readl(padctl, offset); | ||
| 1553 | value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK << | ||
| 1554 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT); | ||
| 1555 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL << | ||
| 1556 | XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT; | ||
| 1557 | padctl_writel(padctl, value, offset); | ||
| 1558 | |||
| 1559 | if (lane->pad == padctl->pcie) | ||
| 1560 | offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index); | ||
| 1561 | else | ||
| 1562 | offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5; | ||
| 1563 | |||
| 1564 | value = padctl_readl(padctl, offset); | ||
| 1565 | value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN; | ||
| 1566 | padctl_writel(padctl, value, offset); | ||
| 1567 | |||
| 1568 | /* Enable SATA PHY when SATA lane is used */ | ||
| 1569 | if (lane->pad == padctl->sata) { | ||
| 1570 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1571 | value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK << | ||
| 1572 | XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT); | ||
| 1573 | value |= 0x2 << | ||
| 1574 | XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT; | ||
| 1575 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | ||
| 1576 | |||
| 1577 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); | ||
| 1578 | value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK << | ||
| 1579 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | | ||
| 1580 | (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK << | ||
| 1581 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | | ||
| 1582 | (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK << | ||
| 1583 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | | ||
| 1584 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN); | ||
| 1585 | value |= (0x7 << | ||
| 1586 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | | ||
| 1587 | (0x8 << | ||
| 1588 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | | ||
| 1589 | (0x8 << | ||
| 1590 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | | ||
| 1591 | XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL; | ||
| 1592 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); | ||
| 1593 | |||
| 1594 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); | ||
| 1595 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS; | ||
| 1596 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1600 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index); | ||
| 1601 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1602 | |||
| 1603 | usleep_range(100, 200); | ||
| 1604 | |||
| 1605 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1606 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index); | ||
| 1607 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1608 | |||
| 1609 | usleep_range(100, 200); | ||
| 1610 | |||
| 1611 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1612 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index); | ||
| 1613 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1614 | |||
| 1615 | return ret; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | static void tegra124_usb3_port_disable(struct tegra_xusb_port *port) | ||
| 1619 | { | ||
| 1620 | struct tegra_xusb_padctl *padctl = port->padctl; | ||
| 1621 | u32 value; | ||
| 1622 | |||
| 1623 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1624 | value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port->index); | ||
| 1625 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1626 | |||
| 1627 | usleep_range(100, 200); | ||
| 1628 | |||
| 1629 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1630 | value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(port->index); | ||
| 1631 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1632 | |||
| 1633 | usleep_range(250, 350); | ||
| 1634 | |||
| 1635 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1636 | value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port->index); | ||
| 1637 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | ||
| 1638 | |||
| 1639 | value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1640 | value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(port->index); | ||
| 1641 | value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->index, 0x7); | ||
| 1642 | padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | static const struct tegra_xusb_lane_map tegra124_usb3_map[] = { | ||
| 1646 | { 0, "pcie", 0 }, | ||
| 1647 | { 1, "pcie", 1 }, | ||
| 1648 | { 1, "sata", 0 }, | ||
| 1649 | { 0, NULL, 0 }, | ||
| 1650 | }; | ||
| 1651 | |||
| 1652 | static struct tegra_xusb_lane * | ||
| 1653 | tegra124_usb3_port_map(struct tegra_xusb_port *port) | ||
| 1654 | { | ||
| 1655 | return tegra_xusb_port_find_lane(port, tegra124_usb3_map, "usb3-ss"); | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | static const struct tegra_xusb_port_ops tegra124_usb3_port_ops = { | ||
| 1659 | .enable = tegra124_usb3_port_enable, | ||
| 1660 | .disable = tegra124_usb3_port_disable, | ||
| 1661 | .map = tegra124_usb3_port_map, | ||
| 1662 | }; | ||
| 1663 | |||
| 1664 | static int | ||
| 1665 | tegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration *fuse) | ||
| 1666 | { | ||
| 1667 | unsigned int i; | ||
| 1668 | int err; | ||
| 1669 | u32 value; | ||
| 1670 | |||
| 1671 | err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); | ||
| 1672 | if (err < 0) | ||
| 1673 | return err; | ||
| 1674 | |||
| 1675 | for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { | ||
| 1676 | fuse->hs_curr_level[i] = | ||
| 1677 | (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & | ||
| 1678 | FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; | ||
| 1679 | } | ||
| 1680 | fuse->hs_iref_cap = | ||
| 1681 | (value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) & | ||
| 1682 | FUSE_SKU_CALIB_HS_IREF_CAP_MASK; | ||
| 1683 | fuse->hs_term_range_adj = | ||
| 1684 | (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & | ||
| 1685 | FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; | ||
| 1686 | fuse->hs_squelch_level = | ||
| 1687 | (value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) & | ||
| 1688 | FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK; | ||
| 1689 | |||
| 1690 | return 0; | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | static struct tegra_xusb_padctl * | ||
| 1694 | tegra124_xusb_padctl_probe(struct device *dev, | ||
| 1695 | const struct tegra_xusb_padctl_soc *soc) | ||
| 1696 | { | ||
| 1697 | struct tegra124_xusb_padctl *padctl; | ||
| 1698 | int err; | ||
| 1699 | |||
| 1700 | padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); | ||
| 1701 | if (!padctl) | ||
| 1702 | return ERR_PTR(-ENOMEM); | ||
| 1703 | |||
| 1704 | padctl->base.dev = dev; | ||
| 1705 | padctl->base.soc = soc; | ||
| 1706 | |||
| 1707 | err = tegra124_xusb_read_fuse_calibration(&padctl->fuse); | ||
| 1708 | if (err < 0) | ||
| 1709 | return ERR_PTR(err); | ||
| 1710 | |||
| 1711 | return &padctl->base; | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | static void tegra124_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) | ||
| 1715 | { | ||
| 1716 | } | ||
| 1717 | |||
| 1718 | static const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = { | ||
| 1719 | .probe = tegra124_xusb_padctl_probe, | ||
| 1720 | .remove = tegra124_xusb_padctl_remove, | ||
| 1721 | .usb3_save_context = tegra124_usb3_save_context, | ||
| 1722 | .hsic_set_idle = tegra124_hsic_set_idle, | ||
| 1723 | }; | ||
| 1724 | |||
| 1725 | const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = { | ||
| 1726 | .num_pads = ARRAY_SIZE(tegra124_pads), | ||
| 1727 | .pads = tegra124_pads, | ||
| 1728 | .ports = { | ||
| 1729 | .usb2 = { | ||
| 1730 | .ops = &tegra124_usb2_port_ops, | ||
| 1731 | .count = 3, | ||
| 1732 | }, | ||
| 1733 | .ulpi = { | ||
| 1734 | .ops = &tegra124_ulpi_port_ops, | ||
| 1735 | .count = 1, | ||
| 1736 | }, | ||
| 1737 | .hsic = { | ||
| 1738 | .ops = &tegra124_hsic_port_ops, | ||
| 1739 | .count = 2, | ||
| 1740 | }, | ||
| 1741 | .usb3 = { | ||
| 1742 | .ops = &tegra124_usb3_port_ops, | ||
| 1743 | .count = 2, | ||
| 1744 | }, | ||
| 1745 | }, | ||
| 1746 | .ops = &tegra124_xusb_padctl_ops, | ||
| 1747 | }; | ||
| 1748 | EXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc); | ||
| 1749 | |||
| 1750 | MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); | ||
| 1751 | MODULE_DESCRIPTION("NVIDIA Tegra 124 XUSB Pad Controller driver"); | ||
| 1752 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/tegra/xusb-tegra210.c b/drivers/phy/tegra/xusb-tegra210.c new file mode 100644 index 000000000000..9d0689ebd28c --- /dev/null +++ b/drivers/phy/tegra/xusb-tegra210.c | |||
| @@ -0,0 +1,2045 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. | ||
| 3 | * Copyright (C) 2015 Google, Inc. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/clk/tegra.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/mailbox_client.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/phy/phy.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/regulator/consumer.h> | ||
| 25 | #include <linux/reset.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | |||
| 28 | #include <soc/tegra/fuse.h> | ||
| 29 | |||
| 30 | #include "xusb.h" | ||
| 31 | |||
| 32 | #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) \ | ||
| 33 | ((x) ? (11 + ((x) - 1) * 6) : 0) | ||
| 34 | #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f | ||
| 35 | #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7 | ||
| 36 | #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf | ||
| 37 | |||
| 38 | #define FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT 0 | ||
| 39 | #define FUSE_USB_CALIB_EXT_RPD_CTRL_MASK 0x1f | ||
| 40 | |||
| 41 | #define XUSB_PADCTL_USB2_PAD_MUX 0x004 | ||
| 42 | #define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT 16 | ||
| 43 | #define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK 0x3 | ||
| 44 | #define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB 0x1 | ||
| 45 | #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT 18 | ||
| 46 | #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK 0x3 | ||
| 47 | #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB 0x1 | ||
| 48 | |||
| 49 | #define XUSB_PADCTL_USB2_PORT_CAP 0x008 | ||
| 50 | #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(x) (0x1 << ((x) * 4)) | ||
| 51 | #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(x) (0x3 << ((x) * 4)) | ||
| 52 | |||
| 53 | #define XUSB_PADCTL_SS_PORT_MAP 0x014 | ||
| 54 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 5) + 4)) | ||
| 55 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5) | ||
| 56 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5)) | ||
| 57 | #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5)) | ||
| 58 | |||
| 59 | #define XUSB_PADCTL_ELPG_PROGRAM1 0x024 | ||
| 60 | #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31) | ||
| 61 | #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30) | ||
| 62 | #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN (1 << 29) | ||
| 63 | #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(x) (1 << (2 + (x) * 3)) | ||
| 64 | #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(x) \ | ||
| 65 | (1 << (1 + (x) * 3)) | ||
| 66 | #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(x) (1 << ((x) * 3)) | ||
| 67 | |||
| 68 | #define XUSB_PADCTL_USB3_PAD_MUX 0x028 | ||
| 69 | #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) | ||
| 70 | #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (8 + (x))) | ||
| 71 | |||
| 72 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(x) (0x084 + (x) * 0x40) | ||
| 73 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT 7 | ||
| 74 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK 0x3 | ||
| 75 | #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18 (1 << 6) | ||
| 76 | |||
| 77 | #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x088 + (x) * 0x40) | ||
| 78 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 29) | ||
| 79 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 27) | ||
| 80 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 26) | ||
| 81 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 | ||
| 82 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f | ||
| 83 | |||
| 84 | #define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x08c + (x) * 0x40) | ||
| 85 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT 26 | ||
| 86 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK 0x1f | ||
| 87 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 | ||
| 88 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0xf | ||
| 89 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) | ||
| 90 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1) | ||
| 91 | #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0) | ||
| 92 | |||
| 93 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284 | ||
| 94 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11) | ||
| 95 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 3 | ||
| 96 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 | ||
| 97 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x7 | ||
| 98 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 | ||
| 99 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x7 | ||
| 100 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL 0x2 | ||
| 101 | |||
| 102 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1 0x288 | ||
| 103 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK (1 << 26) | ||
| 104 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT 19 | ||
| 105 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK 0x7f | ||
| 106 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL 0x0a | ||
| 107 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12 | ||
| 108 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f | ||
| 109 | #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e | ||
| 110 | |||
| 111 | #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20) | ||
| 112 | #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18) | ||
| 113 | #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 (1 << 17) | ||
| 114 | #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 (1 << 16) | ||
| 115 | #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE (1 << 15) | ||
| 116 | #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 (1 << 14) | ||
| 117 | #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 (1 << 13) | ||
| 118 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE (1 << 9) | ||
| 119 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 (1 << 8) | ||
| 120 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 (1 << 7) | ||
| 121 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE (1 << 6) | ||
| 122 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 (1 << 5) | ||
| 123 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 (1 << 4) | ||
| 124 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE (1 << 3) | ||
| 125 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 (1 << 2) | ||
| 126 | #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 (1 << 1) | ||
| 127 | |||
| 128 | #define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x304 + (x) * 0x20) | ||
| 129 | #define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT 0 | ||
| 130 | #define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK 0xf | ||
| 131 | |||
| 132 | #define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x308 + (x) * 0x20) | ||
| 133 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 8 | ||
| 134 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0xf | ||
| 135 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 | ||
| 136 | #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0xff | ||
| 137 | |||
| 138 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL 0x340 | ||
| 139 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK (1 << 19) | ||
| 140 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT 12 | ||
| 141 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK 0x7f | ||
| 142 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL 0x0a | ||
| 143 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT 5 | ||
| 144 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK 0x7f | ||
| 145 | #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL 0x1e | ||
| 146 | |||
| 147 | #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x344 | ||
| 148 | |||
| 149 | #define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360 | ||
| 150 | #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT 20 | ||
| 151 | #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK 0xff | ||
| 152 | #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL 0x19 | ||
| 153 | #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL 0x1e | ||
| 154 | #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT 16 | ||
| 155 | #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK 0x3 | ||
| 156 | #define XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS (1 << 15) | ||
| 157 | #define XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD (1 << 4) | ||
| 158 | #define XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE (1 << 3) | ||
| 159 | #define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT 1 | ||
| 160 | #define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK 0x3 | ||
| 161 | #define XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ (1 << 0) | ||
| 162 | |||
| 163 | #define XUSB_PADCTL_UPHY_PLL_P0_CTL2 0x364 | ||
| 164 | #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT 4 | ||
| 165 | #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK 0xffffff | ||
| 166 | #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL 0x136 | ||
| 167 | #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD (1 << 2) | ||
| 168 | #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE (1 << 1) | ||
| 169 | #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN (1 << 0) | ||
| 170 | |||
| 171 | #define XUSB_PADCTL_UPHY_PLL_P0_CTL4 0x36c | ||
| 172 | #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN (1 << 15) | ||
| 173 | #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT 12 | ||
| 174 | #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK 0x3 | ||
| 175 | #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL 0x2 | ||
| 176 | #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL 0x0 | ||
| 177 | #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN (1 << 8) | ||
| 178 | #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT 4 | ||
| 179 | #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK 0xf | ||
| 180 | |||
| 181 | #define XUSB_PADCTL_UPHY_PLL_P0_CTL5 0x370 | ||
| 182 | #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT 16 | ||
| 183 | #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK 0xff | ||
| 184 | #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL 0x2a | ||
| 185 | |||
| 186 | #define XUSB_PADCTL_UPHY_PLL_P0_CTL8 0x37c | ||
| 187 | #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE (1 << 31) | ||
| 188 | #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD (1 << 15) | ||
| 189 | #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN (1 << 13) | ||
| 190 | #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN (1 << 12) | ||
| 191 | |||
| 192 | #define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(x) (0x460 + (x) * 0x40) | ||
| 193 | #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT 20 | ||
| 194 | #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK 0x3 | ||
| 195 | #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL 0x1 | ||
| 196 | #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18) | ||
| 197 | #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13) | ||
| 198 | |||
| 199 | #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860 | ||
| 200 | |||
| 201 | #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864 | ||
| 202 | |||
| 203 | #define XUSB_PADCTL_UPHY_PLL_S0_CTL4 0x86c | ||
| 204 | |||
| 205 | #define XUSB_PADCTL_UPHY_PLL_S0_CTL5 0x870 | ||
| 206 | |||
| 207 | #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c | ||
| 208 | |||
| 209 | #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960 | ||
| 210 | |||
| 211 | #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40) | ||
| 212 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16 | ||
| 213 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK 0x3 | ||
| 214 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL 0x2 | ||
| 215 | |||
| 216 | #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(x) (0xa64 + (x) * 0x40) | ||
| 217 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT 0 | ||
| 218 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK 0xffff | ||
| 219 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL 0x00fc | ||
| 220 | |||
| 221 | #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(x) (0xa68 + (x) * 0x40) | ||
| 222 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL 0xc0077f1f | ||
| 223 | |||
| 224 | #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(x) (0xa6c + (x) * 0x40) | ||
| 225 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT 16 | ||
| 226 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK 0xffff | ||
| 227 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL 0x01c7 | ||
| 228 | |||
| 229 | #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(x) (0xa74 + (x) * 0x40) | ||
| 230 | #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL 0xfcf01368 | ||
| 231 | |||
| 232 | struct tegra210_xusb_fuse_calibration { | ||
| 233 | u32 hs_curr_level[4]; | ||
| 234 | u32 hs_term_range_adj; | ||
| 235 | u32 rpd_ctrl; | ||
| 236 | }; | ||
| 237 | |||
| 238 | struct tegra210_xusb_padctl { | ||
| 239 | struct tegra_xusb_padctl base; | ||
| 240 | |||
| 241 | struct tegra210_xusb_fuse_calibration fuse; | ||
| 242 | }; | ||
| 243 | |||
| 244 | static inline struct tegra210_xusb_padctl * | ||
| 245 | to_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl) | ||
| 246 | { | ||
| 247 | return container_of(padctl, struct tegra210_xusb_padctl, base); | ||
| 248 | } | ||
| 249 | |||
| 250 | /* must be called under padctl->lock */ | ||
| 251 | static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl) | ||
| 252 | { | ||
| 253 | struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); | ||
| 254 | unsigned long timeout; | ||
| 255 | u32 value; | ||
| 256 | int err; | ||
| 257 | |||
| 258 | if (pcie->enable > 0) { | ||
| 259 | pcie->enable++; | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | err = clk_prepare_enable(pcie->pll); | ||
| 264 | if (err < 0) | ||
| 265 | return err; | ||
| 266 | |||
| 267 | err = reset_control_deassert(pcie->rst); | ||
| 268 | if (err < 0) | ||
| 269 | goto disable; | ||
| 270 | |||
| 271 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 272 | value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK << | ||
| 273 | XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT); | ||
| 274 | value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL << | ||
| 275 | XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT; | ||
| 276 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 277 | |||
| 278 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5); | ||
| 279 | value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK << | ||
| 280 | XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT); | ||
| 281 | value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL << | ||
| 282 | XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT; | ||
| 283 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5); | ||
| 284 | |||
| 285 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 286 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; | ||
| 287 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 288 | |||
| 289 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 290 | value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; | ||
| 291 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 292 | |||
| 293 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 294 | value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; | ||
| 295 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 296 | |||
| 297 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); | ||
| 298 | value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK << | ||
| 299 | XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | | ||
| 300 | (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK << | ||
| 301 | XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT)); | ||
| 302 | value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL << | ||
| 303 | XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | | ||
| 304 | XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN; | ||
| 305 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); | ||
| 306 | |||
| 307 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 308 | value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK << | ||
| 309 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) | | ||
| 310 | (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK << | ||
| 311 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT)); | ||
| 312 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL << | ||
| 313 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; | ||
| 314 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 315 | |||
| 316 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 317 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ; | ||
| 318 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 319 | |||
| 320 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 321 | value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK << | ||
| 322 | XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT); | ||
| 323 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 324 | |||
| 325 | usleep_range(10, 20); | ||
| 326 | |||
| 327 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); | ||
| 328 | value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN; | ||
| 329 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); | ||
| 330 | |||
| 331 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 332 | value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; | ||
| 333 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 334 | |||
| 335 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 336 | |||
| 337 | while (time_before(jiffies, timeout)) { | ||
| 338 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 339 | if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE) | ||
| 340 | break; | ||
| 341 | |||
| 342 | usleep_range(10, 20); | ||
| 343 | } | ||
| 344 | |||
| 345 | if (time_after_eq(jiffies, timeout)) { | ||
| 346 | err = -ETIMEDOUT; | ||
| 347 | goto reset; | ||
| 348 | } | ||
| 349 | |||
| 350 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 351 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; | ||
| 352 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 353 | |||
| 354 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 355 | |||
| 356 | while (time_before(jiffies, timeout)) { | ||
| 357 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 358 | if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)) | ||
| 359 | break; | ||
| 360 | |||
| 361 | usleep_range(10, 20); | ||
| 362 | } | ||
| 363 | |||
| 364 | if (time_after_eq(jiffies, timeout)) { | ||
| 365 | err = -ETIMEDOUT; | ||
| 366 | goto reset; | ||
| 367 | } | ||
| 368 | |||
| 369 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 370 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE; | ||
| 371 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 372 | |||
| 373 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 374 | |||
| 375 | while (time_before(jiffies, timeout)) { | ||
| 376 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 377 | if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS) | ||
| 378 | break; | ||
| 379 | |||
| 380 | usleep_range(10, 20); | ||
| 381 | } | ||
| 382 | |||
| 383 | if (time_after_eq(jiffies, timeout)) { | ||
| 384 | err = -ETIMEDOUT; | ||
| 385 | goto reset; | ||
| 386 | } | ||
| 387 | |||
| 388 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 389 | value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN | | ||
| 390 | XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; | ||
| 391 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 392 | |||
| 393 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 394 | |||
| 395 | while (time_before(jiffies, timeout)) { | ||
| 396 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 397 | if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE) | ||
| 398 | break; | ||
| 399 | |||
| 400 | usleep_range(10, 20); | ||
| 401 | } | ||
| 402 | |||
| 403 | if (time_after_eq(jiffies, timeout)) { | ||
| 404 | err = -ETIMEDOUT; | ||
| 405 | goto reset; | ||
| 406 | } | ||
| 407 | |||
| 408 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 409 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN; | ||
| 410 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 411 | |||
| 412 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 413 | |||
| 414 | while (time_before(jiffies, timeout)) { | ||
| 415 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 416 | if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)) | ||
| 417 | break; | ||
| 418 | |||
| 419 | usleep_range(10, 20); | ||
| 420 | } | ||
| 421 | |||
| 422 | if (time_after_eq(jiffies, timeout)) { | ||
| 423 | err = -ETIMEDOUT; | ||
| 424 | goto reset; | ||
| 425 | } | ||
| 426 | |||
| 427 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 428 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; | ||
| 429 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 430 | |||
| 431 | tegra210_xusb_pll_hw_control_enable(); | ||
| 432 | |||
| 433 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 434 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; | ||
| 435 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); | ||
| 436 | |||
| 437 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 438 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; | ||
| 439 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); | ||
| 440 | |||
| 441 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 442 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; | ||
| 443 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); | ||
| 444 | |||
| 445 | usleep_range(10, 20); | ||
| 446 | |||
| 447 | tegra210_xusb_pll_hw_sequence_start(); | ||
| 448 | |||
| 449 | pcie->enable++; | ||
| 450 | |||
| 451 | return 0; | ||
| 452 | |||
| 453 | reset: | ||
| 454 | reset_control_assert(pcie->rst); | ||
| 455 | disable: | ||
| 456 | clk_disable_unprepare(pcie->pll); | ||
| 457 | return err; | ||
| 458 | } | ||
| 459 | |||
| 460 | static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl) | ||
| 461 | { | ||
| 462 | struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); | ||
| 463 | |||
| 464 | mutex_lock(&padctl->lock); | ||
| 465 | |||
| 466 | if (WARN_ON(pcie->enable == 0)) | ||
| 467 | goto unlock; | ||
| 468 | |||
| 469 | if (--pcie->enable > 0) | ||
| 470 | goto unlock; | ||
| 471 | |||
| 472 | reset_control_assert(pcie->rst); | ||
| 473 | clk_disable_unprepare(pcie->pll); | ||
| 474 | |||
| 475 | unlock: | ||
| 476 | mutex_unlock(&padctl->lock); | ||
| 477 | } | ||
| 478 | |||
| 479 | /* must be called under padctl->lock */ | ||
| 480 | static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb) | ||
| 481 | { | ||
| 482 | struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); | ||
| 483 | unsigned long timeout; | ||
| 484 | u32 value; | ||
| 485 | int err; | ||
| 486 | |||
| 487 | if (sata->enable > 0) { | ||
| 488 | sata->enable++; | ||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | err = clk_prepare_enable(sata->pll); | ||
| 493 | if (err < 0) | ||
| 494 | return err; | ||
| 495 | |||
| 496 | err = reset_control_deassert(sata->rst); | ||
| 497 | if (err < 0) | ||
| 498 | goto disable; | ||
| 499 | |||
| 500 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 501 | value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK << | ||
| 502 | XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT); | ||
| 503 | value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL << | ||
| 504 | XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT; | ||
| 505 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 506 | |||
| 507 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL5); | ||
| 508 | value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK << | ||
| 509 | XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT); | ||
| 510 | value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL << | ||
| 511 | XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT; | ||
| 512 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL5); | ||
| 513 | |||
| 514 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 515 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; | ||
| 516 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 517 | |||
| 518 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 519 | value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; | ||
| 520 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 521 | |||
| 522 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 523 | value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; | ||
| 524 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 525 | |||
| 526 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4); | ||
| 527 | value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK << | ||
| 528 | XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | | ||
| 529 | (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK << | ||
| 530 | XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT)); | ||
| 531 | value |= XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN; | ||
| 532 | |||
| 533 | if (usb) | ||
| 534 | value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL << | ||
| 535 | XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT); | ||
| 536 | else | ||
| 537 | value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL << | ||
| 538 | XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT); | ||
| 539 | |||
| 540 | /* XXX PLL0_XDIGCLK_EN */ | ||
| 541 | /* | ||
| 542 | value &= ~(1 << 19); | ||
| 543 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4); | ||
| 544 | */ | ||
| 545 | |||
| 546 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 547 | value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK << | ||
| 548 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) | | ||
| 549 | (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK << | ||
| 550 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT)); | ||
| 551 | |||
| 552 | if (usb) | ||
| 553 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL << | ||
| 554 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; | ||
| 555 | else | ||
| 556 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL << | ||
| 557 | XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; | ||
| 558 | |||
| 559 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 560 | |||
| 561 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 562 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ; | ||
| 563 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 564 | |||
| 565 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 566 | value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK << | ||
| 567 | XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT); | ||
| 568 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 569 | |||
| 570 | usleep_range(10, 20); | ||
| 571 | |||
| 572 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4); | ||
| 573 | value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN; | ||
| 574 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4); | ||
| 575 | |||
| 576 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 577 | value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; | ||
| 578 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 579 | |||
| 580 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 581 | |||
| 582 | while (time_before(jiffies, timeout)) { | ||
| 583 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 584 | if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE) | ||
| 585 | break; | ||
| 586 | |||
| 587 | usleep_range(10, 20); | ||
| 588 | } | ||
| 589 | |||
| 590 | if (time_after_eq(jiffies, timeout)) { | ||
| 591 | err = -ETIMEDOUT; | ||
| 592 | goto reset; | ||
| 593 | } | ||
| 594 | |||
| 595 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 596 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; | ||
| 597 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 598 | |||
| 599 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 600 | |||
| 601 | while (time_before(jiffies, timeout)) { | ||
| 602 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 603 | if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)) | ||
| 604 | break; | ||
| 605 | |||
| 606 | usleep_range(10, 20); | ||
| 607 | } | ||
| 608 | |||
| 609 | if (time_after_eq(jiffies, timeout)) { | ||
| 610 | err = -ETIMEDOUT; | ||
| 611 | goto reset; | ||
| 612 | } | ||
| 613 | |||
| 614 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 615 | value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE; | ||
| 616 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 617 | |||
| 618 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 619 | |||
| 620 | while (time_before(jiffies, timeout)) { | ||
| 621 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 622 | if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS) | ||
| 623 | break; | ||
| 624 | |||
| 625 | usleep_range(10, 20); | ||
| 626 | } | ||
| 627 | |||
| 628 | if (time_after_eq(jiffies, timeout)) { | ||
| 629 | err = -ETIMEDOUT; | ||
| 630 | goto reset; | ||
| 631 | } | ||
| 632 | |||
| 633 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 634 | value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN | | ||
| 635 | XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; | ||
| 636 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 637 | |||
| 638 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 639 | |||
| 640 | while (time_before(jiffies, timeout)) { | ||
| 641 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 642 | if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE) | ||
| 643 | break; | ||
| 644 | |||
| 645 | usleep_range(10, 20); | ||
| 646 | } | ||
| 647 | |||
| 648 | if (time_after_eq(jiffies, timeout)) { | ||
| 649 | err = -ETIMEDOUT; | ||
| 650 | goto reset; | ||
| 651 | } | ||
| 652 | |||
| 653 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 654 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN; | ||
| 655 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 656 | |||
| 657 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 658 | |||
| 659 | while (time_before(jiffies, timeout)) { | ||
| 660 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 661 | if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)) | ||
| 662 | break; | ||
| 663 | |||
| 664 | usleep_range(10, 20); | ||
| 665 | } | ||
| 666 | |||
| 667 | if (time_after_eq(jiffies, timeout)) { | ||
| 668 | err = -ETIMEDOUT; | ||
| 669 | goto reset; | ||
| 670 | } | ||
| 671 | |||
| 672 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 673 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; | ||
| 674 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 675 | |||
| 676 | tegra210_sata_pll_hw_control_enable(); | ||
| 677 | |||
| 678 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 679 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; | ||
| 680 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); | ||
| 681 | |||
| 682 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 683 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; | ||
| 684 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); | ||
| 685 | |||
| 686 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 687 | value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; | ||
| 688 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); | ||
| 689 | |||
| 690 | usleep_range(10, 20); | ||
| 691 | |||
| 692 | tegra210_sata_pll_hw_sequence_start(); | ||
| 693 | |||
| 694 | sata->enable++; | ||
| 695 | |||
| 696 | return 0; | ||
| 697 | |||
| 698 | reset: | ||
| 699 | reset_control_assert(sata->rst); | ||
| 700 | disable: | ||
| 701 | clk_disable_unprepare(sata->pll); | ||
| 702 | return err; | ||
| 703 | } | ||
| 704 | |||
| 705 | static void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl) | ||
| 706 | { | ||
| 707 | struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); | ||
| 708 | |||
| 709 | mutex_lock(&padctl->lock); | ||
| 710 | |||
| 711 | if (WARN_ON(sata->enable == 0)) | ||
| 712 | goto unlock; | ||
| 713 | |||
| 714 | if (--sata->enable > 0) | ||
| 715 | goto unlock; | ||
| 716 | |||
| 717 | reset_control_assert(sata->rst); | ||
| 718 | clk_disable_unprepare(sata->pll); | ||
| 719 | |||
| 720 | unlock: | ||
| 721 | mutex_unlock(&padctl->lock); | ||
| 722 | } | ||
| 723 | |||
| 724 | static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) | ||
| 725 | { | ||
| 726 | u32 value; | ||
| 727 | |||
| 728 | mutex_lock(&padctl->lock); | ||
| 729 | |||
| 730 | if (padctl->enable++ > 0) | ||
| 731 | goto out; | ||
| 732 | |||
| 733 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 734 | value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; | ||
| 735 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 736 | |||
| 737 | usleep_range(100, 200); | ||
| 738 | |||
| 739 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 740 | value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY; | ||
| 741 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 742 | |||
| 743 | usleep_range(100, 200); | ||
| 744 | |||
| 745 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 746 | value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; | ||
| 747 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 748 | |||
| 749 | out: | ||
| 750 | mutex_unlock(&padctl->lock); | ||
| 751 | return 0; | ||
| 752 | } | ||
| 753 | |||
| 754 | static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) | ||
| 755 | { | ||
| 756 | u32 value; | ||
| 757 | |||
| 758 | mutex_lock(&padctl->lock); | ||
| 759 | |||
| 760 | if (WARN_ON(padctl->enable == 0)) | ||
| 761 | goto out; | ||
| 762 | |||
| 763 | if (--padctl->enable > 0) | ||
| 764 | goto out; | ||
| 765 | |||
| 766 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 767 | value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; | ||
| 768 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 769 | |||
| 770 | usleep_range(100, 200); | ||
| 771 | |||
| 772 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 773 | value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY; | ||
| 774 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 775 | |||
| 776 | usleep_range(100, 200); | ||
| 777 | |||
| 778 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 779 | value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; | ||
| 780 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 781 | |||
| 782 | out: | ||
| 783 | mutex_unlock(&padctl->lock); | ||
| 784 | return 0; | ||
| 785 | } | ||
| 786 | |||
| 787 | static int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl, | ||
| 788 | unsigned int index, bool idle) | ||
| 789 | { | ||
| 790 | u32 value; | ||
| 791 | |||
| 792 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 793 | |||
| 794 | value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 | | ||
| 795 | XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 | | ||
| 796 | XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE); | ||
| 797 | |||
| 798 | if (idle) | ||
| 799 | value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | | ||
| 800 | XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | | ||
| 801 | XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE; | ||
| 802 | else | ||
| 803 | value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | | ||
| 804 | XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | | ||
| 805 | XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE); | ||
| 806 | |||
| 807 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 808 | |||
| 809 | return 0; | ||
| 810 | } | ||
| 811 | |||
| 812 | static int tegra210_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, | ||
| 813 | unsigned int index, bool enable) | ||
| 814 | { | ||
| 815 | struct tegra_xusb_port *port; | ||
| 816 | struct tegra_xusb_lane *lane; | ||
| 817 | u32 value, offset; | ||
| 818 | |||
| 819 | port = tegra_xusb_find_port(padctl, "usb3", index); | ||
| 820 | if (!port) | ||
| 821 | return -ENODEV; | ||
| 822 | |||
| 823 | lane = port->lane; | ||
| 824 | |||
| 825 | if (lane->pad == padctl->pcie) | ||
| 826 | offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(lane->index); | ||
| 827 | else | ||
| 828 | offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1; | ||
| 829 | |||
| 830 | value = padctl_readl(padctl, offset); | ||
| 831 | |||
| 832 | value &= ~((XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK << | ||
| 833 | XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) | | ||
| 834 | XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN | | ||
| 835 | XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD); | ||
| 836 | |||
| 837 | if (!enable) { | ||
| 838 | value |= (XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL << | ||
| 839 | XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) | | ||
| 840 | XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN | | ||
| 841 | XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD; | ||
| 842 | } | ||
| 843 | |||
| 844 | padctl_writel(padctl, value, offset); | ||
| 845 | |||
| 846 | return 0; | ||
| 847 | } | ||
| 848 | |||
| 849 | #define TEGRA210_LANE(_name, _offset, _shift, _mask, _type) \ | ||
| 850 | { \ | ||
| 851 | .name = _name, \ | ||
| 852 | .offset = _offset, \ | ||
| 853 | .shift = _shift, \ | ||
| 854 | .mask = _mask, \ | ||
| 855 | .num_funcs = ARRAY_SIZE(tegra210_##_type##_functions), \ | ||
| 856 | .funcs = tegra210_##_type##_functions, \ | ||
| 857 | } | ||
| 858 | |||
| 859 | static const char *tegra210_usb2_functions[] = { | ||
| 860 | "snps", | ||
| 861 | "xusb", | ||
| 862 | "uart" | ||
| 863 | }; | ||
| 864 | |||
| 865 | static const struct tegra_xusb_lane_soc tegra210_usb2_lanes[] = { | ||
| 866 | TEGRA210_LANE("usb2-0", 0x004, 0, 0x3, usb2), | ||
| 867 | TEGRA210_LANE("usb2-1", 0x004, 2, 0x3, usb2), | ||
| 868 | TEGRA210_LANE("usb2-2", 0x004, 4, 0x3, usb2), | ||
| 869 | TEGRA210_LANE("usb2-3", 0x004, 6, 0x3, usb2), | ||
| 870 | }; | ||
| 871 | |||
| 872 | static struct tegra_xusb_lane * | ||
| 873 | tegra210_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 874 | unsigned int index) | ||
| 875 | { | ||
| 876 | struct tegra_xusb_usb2_lane *usb2; | ||
| 877 | int err; | ||
| 878 | |||
| 879 | usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); | ||
| 880 | if (!usb2) | ||
| 881 | return ERR_PTR(-ENOMEM); | ||
| 882 | |||
| 883 | INIT_LIST_HEAD(&usb2->base.list); | ||
| 884 | usb2->base.soc = &pad->soc->lanes[index]; | ||
| 885 | usb2->base.index = index; | ||
| 886 | usb2->base.pad = pad; | ||
| 887 | usb2->base.np = np; | ||
| 888 | |||
| 889 | err = tegra_xusb_lane_parse_dt(&usb2->base, np); | ||
| 890 | if (err < 0) { | ||
| 891 | kfree(usb2); | ||
| 892 | return ERR_PTR(err); | ||
| 893 | } | ||
| 894 | |||
| 895 | return &usb2->base; | ||
| 896 | } | ||
| 897 | |||
| 898 | static void tegra210_usb2_lane_remove(struct tegra_xusb_lane *lane) | ||
| 899 | { | ||
| 900 | struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); | ||
| 901 | |||
| 902 | kfree(usb2); | ||
| 903 | } | ||
| 904 | |||
| 905 | static const struct tegra_xusb_lane_ops tegra210_usb2_lane_ops = { | ||
| 906 | .probe = tegra210_usb2_lane_probe, | ||
| 907 | .remove = tegra210_usb2_lane_remove, | ||
| 908 | }; | ||
| 909 | |||
| 910 | static int tegra210_usb2_phy_init(struct phy *phy) | ||
| 911 | { | ||
| 912 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 913 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 914 | u32 value; | ||
| 915 | |||
| 916 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); | ||
| 917 | value &= ~(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK << | ||
| 918 | XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT); | ||
| 919 | value |= XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB << | ||
| 920 | XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT; | ||
| 921 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); | ||
| 922 | |||
| 923 | return tegra210_xusb_padctl_enable(padctl); | ||
| 924 | } | ||
| 925 | |||
| 926 | static int tegra210_usb2_phy_exit(struct phy *phy) | ||
| 927 | { | ||
| 928 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 929 | |||
| 930 | return tegra210_xusb_padctl_disable(lane->pad->padctl); | ||
| 931 | } | ||
| 932 | |||
| 933 | static int tegra210_usb2_phy_power_on(struct phy *phy) | ||
| 934 | { | ||
| 935 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 936 | struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); | ||
| 937 | struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); | ||
| 938 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 939 | struct tegra210_xusb_padctl *priv; | ||
| 940 | struct tegra_xusb_usb2_port *port; | ||
| 941 | unsigned int index = lane->index; | ||
| 942 | u32 value; | ||
| 943 | int err; | ||
| 944 | |||
| 945 | port = tegra_xusb_find_usb2_port(padctl, index); | ||
| 946 | if (!port) { | ||
| 947 | dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); | ||
| 948 | return -ENODEV; | ||
| 949 | } | ||
| 950 | |||
| 951 | priv = to_tegra210_xusb_padctl(padctl); | ||
| 952 | |||
| 953 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 954 | value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << | ||
| 955 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | | ||
| 956 | (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << | ||
| 957 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); | ||
| 958 | value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << | ||
| 959 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); | ||
| 960 | |||
| 961 | if (tegra_sku_info.revision < TEGRA_REVISION_A02) | ||
| 962 | value |= | ||
| 963 | (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL << | ||
| 964 | XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT); | ||
| 965 | |||
| 966 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 967 | |||
| 968 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); | ||
| 969 | value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index); | ||
| 970 | value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index); | ||
| 971 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); | ||
| 972 | |||
| 973 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); | ||
| 974 | value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << | ||
| 975 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | | ||
| 976 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | | ||
| 977 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | | ||
| 978 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); | ||
| 979 | value |= (priv->fuse.hs_curr_level[index] + | ||
| 980 | usb2->hs_curr_level_offset) << | ||
| 981 | XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; | ||
| 982 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); | ||
| 983 | |||
| 984 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); | ||
| 985 | value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << | ||
| 986 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | | ||
| 987 | (XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK << | ||
| 988 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT) | | ||
| 989 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | | ||
| 990 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD | | ||
| 991 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD); | ||
| 992 | value |= (priv->fuse.hs_term_range_adj << | ||
| 993 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | | ||
| 994 | (priv->fuse.rpd_ctrl << | ||
| 995 | XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT); | ||
| 996 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); | ||
| 997 | |||
| 998 | value = padctl_readl(padctl, | ||
| 999 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); | ||
| 1000 | value &= ~(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK << | ||
| 1001 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT); | ||
| 1002 | value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18; | ||
| 1003 | padctl_writel(padctl, value, | ||
| 1004 | XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); | ||
| 1005 | |||
| 1006 | err = regulator_enable(port->supply); | ||
| 1007 | if (err) | ||
| 1008 | return err; | ||
| 1009 | |||
| 1010 | mutex_lock(&padctl->lock); | ||
| 1011 | |||
| 1012 | if (pad->enable > 0) { | ||
| 1013 | pad->enable++; | ||
| 1014 | mutex_unlock(&padctl->lock); | ||
| 1015 | return 0; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | err = clk_prepare_enable(pad->clk); | ||
| 1019 | if (err) | ||
| 1020 | goto disable_regulator; | ||
| 1021 | |||
| 1022 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); | ||
| 1023 | value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK << | ||
| 1024 | XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) | | ||
| 1025 | (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK << | ||
| 1026 | XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT)); | ||
| 1027 | value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL << | ||
| 1028 | XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) | | ||
| 1029 | (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL << | ||
| 1030 | XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT); | ||
| 1031 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); | ||
| 1032 | |||
| 1033 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 1034 | value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; | ||
| 1035 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 1036 | |||
| 1037 | udelay(1); | ||
| 1038 | |||
| 1039 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); | ||
| 1040 | value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK; | ||
| 1041 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); | ||
| 1042 | |||
| 1043 | udelay(50); | ||
| 1044 | |||
| 1045 | clk_disable_unprepare(pad->clk); | ||
| 1046 | |||
| 1047 | pad->enable++; | ||
| 1048 | mutex_unlock(&padctl->lock); | ||
| 1049 | |||
| 1050 | return 0; | ||
| 1051 | |||
| 1052 | disable_regulator: | ||
| 1053 | regulator_disable(port->supply); | ||
| 1054 | mutex_unlock(&padctl->lock); | ||
| 1055 | return err; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | static int tegra210_usb2_phy_power_off(struct phy *phy) | ||
| 1059 | { | ||
| 1060 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1061 | struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); | ||
| 1062 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1063 | struct tegra_xusb_usb2_port *port; | ||
| 1064 | u32 value; | ||
| 1065 | |||
| 1066 | port = tegra_xusb_find_usb2_port(padctl, lane->index); | ||
| 1067 | if (!port) { | ||
| 1068 | dev_err(&phy->dev, "no port found for USB2 lane %u\n", | ||
| 1069 | lane->index); | ||
| 1070 | return -ENODEV; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | mutex_lock(&padctl->lock); | ||
| 1074 | |||
| 1075 | if (WARN_ON(pad->enable == 0)) | ||
| 1076 | goto out; | ||
| 1077 | |||
| 1078 | if (--pad->enable > 0) | ||
| 1079 | goto out; | ||
| 1080 | |||
| 1081 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 1082 | value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; | ||
| 1083 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); | ||
| 1084 | |||
| 1085 | out: | ||
| 1086 | regulator_disable(port->supply); | ||
| 1087 | mutex_unlock(&padctl->lock); | ||
| 1088 | return 0; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | static const struct phy_ops tegra210_usb2_phy_ops = { | ||
| 1092 | .init = tegra210_usb2_phy_init, | ||
| 1093 | .exit = tegra210_usb2_phy_exit, | ||
| 1094 | .power_on = tegra210_usb2_phy_power_on, | ||
| 1095 | .power_off = tegra210_usb2_phy_power_off, | ||
| 1096 | .owner = THIS_MODULE, | ||
| 1097 | }; | ||
| 1098 | |||
| 1099 | static struct tegra_xusb_pad * | ||
| 1100 | tegra210_usb2_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 1101 | const struct tegra_xusb_pad_soc *soc, | ||
| 1102 | struct device_node *np) | ||
| 1103 | { | ||
| 1104 | struct tegra_xusb_usb2_pad *usb2; | ||
| 1105 | struct tegra_xusb_pad *pad; | ||
| 1106 | int err; | ||
| 1107 | |||
| 1108 | usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); | ||
| 1109 | if (!usb2) | ||
| 1110 | return ERR_PTR(-ENOMEM); | ||
| 1111 | |||
| 1112 | pad = &usb2->base; | ||
| 1113 | pad->ops = &tegra210_usb2_lane_ops; | ||
| 1114 | pad->soc = soc; | ||
| 1115 | |||
| 1116 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 1117 | if (err < 0) { | ||
| 1118 | kfree(usb2); | ||
| 1119 | goto out; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | usb2->clk = devm_clk_get(&pad->dev, "trk"); | ||
| 1123 | if (IS_ERR(usb2->clk)) { | ||
| 1124 | err = PTR_ERR(usb2->clk); | ||
| 1125 | dev_err(&pad->dev, "failed to get trk clock: %d\n", err); | ||
| 1126 | goto unregister; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | err = tegra_xusb_pad_register(pad, &tegra210_usb2_phy_ops); | ||
| 1130 | if (err < 0) | ||
| 1131 | goto unregister; | ||
| 1132 | |||
| 1133 | dev_set_drvdata(&pad->dev, pad); | ||
| 1134 | |||
| 1135 | return pad; | ||
| 1136 | |||
| 1137 | unregister: | ||
| 1138 | device_unregister(&pad->dev); | ||
| 1139 | out: | ||
| 1140 | return ERR_PTR(err); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | static void tegra210_usb2_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1144 | { | ||
| 1145 | struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); | ||
| 1146 | |||
| 1147 | kfree(usb2); | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | static const struct tegra_xusb_pad_ops tegra210_usb2_ops = { | ||
| 1151 | .probe = tegra210_usb2_pad_probe, | ||
| 1152 | .remove = tegra210_usb2_pad_remove, | ||
| 1153 | }; | ||
| 1154 | |||
| 1155 | static const struct tegra_xusb_pad_soc tegra210_usb2_pad = { | ||
| 1156 | .name = "usb2", | ||
| 1157 | .num_lanes = ARRAY_SIZE(tegra210_usb2_lanes), | ||
| 1158 | .lanes = tegra210_usb2_lanes, | ||
| 1159 | .ops = &tegra210_usb2_ops, | ||
| 1160 | }; | ||
| 1161 | |||
| 1162 | static const char *tegra210_hsic_functions[] = { | ||
| 1163 | "snps", | ||
| 1164 | "xusb", | ||
| 1165 | }; | ||
| 1166 | |||
| 1167 | static const struct tegra_xusb_lane_soc tegra210_hsic_lanes[] = { | ||
| 1168 | TEGRA210_LANE("hsic-0", 0x004, 14, 0x1, hsic), | ||
| 1169 | }; | ||
| 1170 | |||
| 1171 | static struct tegra_xusb_lane * | ||
| 1172 | tegra210_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 1173 | unsigned int index) | ||
| 1174 | { | ||
| 1175 | struct tegra_xusb_hsic_lane *hsic; | ||
| 1176 | int err; | ||
| 1177 | |||
| 1178 | hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); | ||
| 1179 | if (!hsic) | ||
| 1180 | return ERR_PTR(-ENOMEM); | ||
| 1181 | |||
| 1182 | INIT_LIST_HEAD(&hsic->base.list); | ||
| 1183 | hsic->base.soc = &pad->soc->lanes[index]; | ||
| 1184 | hsic->base.index = index; | ||
| 1185 | hsic->base.pad = pad; | ||
| 1186 | hsic->base.np = np; | ||
| 1187 | |||
| 1188 | err = tegra_xusb_lane_parse_dt(&hsic->base, np); | ||
| 1189 | if (err < 0) { | ||
| 1190 | kfree(hsic); | ||
| 1191 | return ERR_PTR(err); | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | return &hsic->base; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | static void tegra210_hsic_lane_remove(struct tegra_xusb_lane *lane) | ||
| 1198 | { | ||
| 1199 | struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); | ||
| 1200 | |||
| 1201 | kfree(hsic); | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | static const struct tegra_xusb_lane_ops tegra210_hsic_lane_ops = { | ||
| 1205 | .probe = tegra210_hsic_lane_probe, | ||
| 1206 | .remove = tegra210_hsic_lane_remove, | ||
| 1207 | }; | ||
| 1208 | |||
| 1209 | static int tegra210_hsic_phy_init(struct phy *phy) | ||
| 1210 | { | ||
| 1211 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1212 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1213 | u32 value; | ||
| 1214 | |||
| 1215 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); | ||
| 1216 | value &= ~(XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK << | ||
| 1217 | XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT); | ||
| 1218 | value |= XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB << | ||
| 1219 | XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT; | ||
| 1220 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); | ||
| 1221 | |||
| 1222 | return tegra210_xusb_padctl_enable(padctl); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static int tegra210_hsic_phy_exit(struct phy *phy) | ||
| 1226 | { | ||
| 1227 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1228 | |||
| 1229 | return tegra210_xusb_padctl_disable(lane->pad->padctl); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static int tegra210_hsic_phy_power_on(struct phy *phy) | ||
| 1233 | { | ||
| 1234 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1235 | struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); | ||
| 1236 | struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); | ||
| 1237 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1238 | struct tegra210_xusb_padctl *priv; | ||
| 1239 | unsigned int index = lane->index; | ||
| 1240 | u32 value; | ||
| 1241 | int err; | ||
| 1242 | |||
| 1243 | priv = to_tegra210_xusb_padctl(padctl); | ||
| 1244 | |||
| 1245 | err = regulator_enable(pad->supply); | ||
| 1246 | if (err) | ||
| 1247 | return err; | ||
| 1248 | |||
| 1249 | padctl_writel(padctl, hsic->strobe_trim, | ||
| 1250 | XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); | ||
| 1251 | |||
| 1252 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 1253 | value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK << | ||
| 1254 | XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT); | ||
| 1255 | value |= (hsic->tx_rtune_p << | ||
| 1256 | XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT); | ||
| 1257 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 1258 | |||
| 1259 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); | ||
| 1260 | value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << | ||
| 1261 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | | ||
| 1262 | (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << | ||
| 1263 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); | ||
| 1264 | value |= (hsic->rx_strobe_trim << | ||
| 1265 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | | ||
| 1266 | (hsic->rx_data_trim << | ||
| 1267 | XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); | ||
| 1268 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); | ||
| 1269 | |||
| 1270 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 1271 | value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 | | ||
| 1272 | XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 | | ||
| 1273 | XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE | | ||
| 1274 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 | | ||
| 1275 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 | | ||
| 1276 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE | | ||
| 1277 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 | | ||
| 1278 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 | | ||
| 1279 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE | | ||
| 1280 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 | | ||
| 1281 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 | | ||
| 1282 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE); | ||
| 1283 | value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | | ||
| 1284 | XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | | ||
| 1285 | XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE; | ||
| 1286 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 1287 | |||
| 1288 | err = clk_prepare_enable(pad->clk); | ||
| 1289 | if (err) | ||
| 1290 | goto disable; | ||
| 1291 | |||
| 1292 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL); | ||
| 1293 | value &= ~((XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK << | ||
| 1294 | XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) | | ||
| 1295 | (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK << | ||
| 1296 | XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT)); | ||
| 1297 | value |= (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL << | ||
| 1298 | XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) | | ||
| 1299 | (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL << | ||
| 1300 | XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT); | ||
| 1301 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL); | ||
| 1302 | |||
| 1303 | udelay(1); | ||
| 1304 | |||
| 1305 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL); | ||
| 1306 | value &= ~XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK; | ||
| 1307 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL); | ||
| 1308 | |||
| 1309 | udelay(50); | ||
| 1310 | |||
| 1311 | clk_disable_unprepare(pad->clk); | ||
| 1312 | |||
| 1313 | return 0; | ||
| 1314 | |||
| 1315 | disable: | ||
| 1316 | regulator_disable(pad->supply); | ||
| 1317 | return err; | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | static int tegra210_hsic_phy_power_off(struct phy *phy) | ||
| 1321 | { | ||
| 1322 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1323 | struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); | ||
| 1324 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1325 | unsigned int index = lane->index; | ||
| 1326 | u32 value; | ||
| 1327 | |||
| 1328 | value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); | ||
| 1329 | value |= XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 | | ||
| 1330 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 | | ||
| 1331 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE | | ||
| 1332 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 | | ||
| 1333 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 | | ||
| 1334 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE | | ||
| 1335 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 | | ||
| 1336 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 | | ||
| 1337 | XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE; | ||
| 1338 | padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); | ||
| 1339 | |||
| 1340 | regulator_disable(pad->supply); | ||
| 1341 | |||
| 1342 | return 0; | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static const struct phy_ops tegra210_hsic_phy_ops = { | ||
| 1346 | .init = tegra210_hsic_phy_init, | ||
| 1347 | .exit = tegra210_hsic_phy_exit, | ||
| 1348 | .power_on = tegra210_hsic_phy_power_on, | ||
| 1349 | .power_off = tegra210_hsic_phy_power_off, | ||
| 1350 | .owner = THIS_MODULE, | ||
| 1351 | }; | ||
| 1352 | |||
| 1353 | static struct tegra_xusb_pad * | ||
| 1354 | tegra210_hsic_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 1355 | const struct tegra_xusb_pad_soc *soc, | ||
| 1356 | struct device_node *np) | ||
| 1357 | { | ||
| 1358 | struct tegra_xusb_hsic_pad *hsic; | ||
| 1359 | struct tegra_xusb_pad *pad; | ||
| 1360 | int err; | ||
| 1361 | |||
| 1362 | hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); | ||
| 1363 | if (!hsic) | ||
| 1364 | return ERR_PTR(-ENOMEM); | ||
| 1365 | |||
| 1366 | pad = &hsic->base; | ||
| 1367 | pad->ops = &tegra210_hsic_lane_ops; | ||
| 1368 | pad->soc = soc; | ||
| 1369 | |||
| 1370 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 1371 | if (err < 0) { | ||
| 1372 | kfree(hsic); | ||
| 1373 | goto out; | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | hsic->clk = devm_clk_get(&pad->dev, "trk"); | ||
| 1377 | if (IS_ERR(hsic->clk)) { | ||
| 1378 | err = PTR_ERR(hsic->clk); | ||
| 1379 | dev_err(&pad->dev, "failed to get trk clock: %d\n", err); | ||
| 1380 | goto unregister; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | err = tegra_xusb_pad_register(pad, &tegra210_hsic_phy_ops); | ||
| 1384 | if (err < 0) | ||
| 1385 | goto unregister; | ||
| 1386 | |||
| 1387 | dev_set_drvdata(&pad->dev, pad); | ||
| 1388 | |||
| 1389 | return pad; | ||
| 1390 | |||
| 1391 | unregister: | ||
| 1392 | device_unregister(&pad->dev); | ||
| 1393 | out: | ||
| 1394 | return ERR_PTR(err); | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | static void tegra210_hsic_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1398 | { | ||
| 1399 | struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); | ||
| 1400 | |||
| 1401 | kfree(hsic); | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | static const struct tegra_xusb_pad_ops tegra210_hsic_ops = { | ||
| 1405 | .probe = tegra210_hsic_pad_probe, | ||
| 1406 | .remove = tegra210_hsic_pad_remove, | ||
| 1407 | }; | ||
| 1408 | |||
| 1409 | static const struct tegra_xusb_pad_soc tegra210_hsic_pad = { | ||
| 1410 | .name = "hsic", | ||
| 1411 | .num_lanes = ARRAY_SIZE(tegra210_hsic_lanes), | ||
| 1412 | .lanes = tegra210_hsic_lanes, | ||
| 1413 | .ops = &tegra210_hsic_ops, | ||
| 1414 | }; | ||
| 1415 | |||
| 1416 | static const char *tegra210_pcie_functions[] = { | ||
| 1417 | "pcie-x1", | ||
| 1418 | "usb3-ss", | ||
| 1419 | "sata", | ||
| 1420 | "pcie-x4", | ||
| 1421 | }; | ||
| 1422 | |||
| 1423 | static const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = { | ||
| 1424 | TEGRA210_LANE("pcie-0", 0x028, 12, 0x3, pcie), | ||
| 1425 | TEGRA210_LANE("pcie-1", 0x028, 14, 0x3, pcie), | ||
| 1426 | TEGRA210_LANE("pcie-2", 0x028, 16, 0x3, pcie), | ||
| 1427 | TEGRA210_LANE("pcie-3", 0x028, 18, 0x3, pcie), | ||
| 1428 | TEGRA210_LANE("pcie-4", 0x028, 20, 0x3, pcie), | ||
| 1429 | TEGRA210_LANE("pcie-5", 0x028, 22, 0x3, pcie), | ||
| 1430 | TEGRA210_LANE("pcie-6", 0x028, 24, 0x3, pcie), | ||
| 1431 | }; | ||
| 1432 | |||
| 1433 | static struct tegra_xusb_lane * | ||
| 1434 | tegra210_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 1435 | unsigned int index) | ||
| 1436 | { | ||
| 1437 | struct tegra_xusb_pcie_lane *pcie; | ||
| 1438 | int err; | ||
| 1439 | |||
| 1440 | pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); | ||
| 1441 | if (!pcie) | ||
| 1442 | return ERR_PTR(-ENOMEM); | ||
| 1443 | |||
| 1444 | INIT_LIST_HEAD(&pcie->base.list); | ||
| 1445 | pcie->base.soc = &pad->soc->lanes[index]; | ||
| 1446 | pcie->base.index = index; | ||
| 1447 | pcie->base.pad = pad; | ||
| 1448 | pcie->base.np = np; | ||
| 1449 | |||
| 1450 | err = tegra_xusb_lane_parse_dt(&pcie->base, np); | ||
| 1451 | if (err < 0) { | ||
| 1452 | kfree(pcie); | ||
| 1453 | return ERR_PTR(err); | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | return &pcie->base; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | static void tegra210_pcie_lane_remove(struct tegra_xusb_lane *lane) | ||
| 1460 | { | ||
| 1461 | struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); | ||
| 1462 | |||
| 1463 | kfree(pcie); | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = { | ||
| 1467 | .probe = tegra210_pcie_lane_probe, | ||
| 1468 | .remove = tegra210_pcie_lane_remove, | ||
| 1469 | }; | ||
| 1470 | |||
| 1471 | static int tegra210_pcie_phy_init(struct phy *phy) | ||
| 1472 | { | ||
| 1473 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1474 | |||
| 1475 | return tegra210_xusb_padctl_enable(lane->pad->padctl); | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | static int tegra210_pcie_phy_exit(struct phy *phy) | ||
| 1479 | { | ||
| 1480 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1481 | |||
| 1482 | return tegra210_xusb_padctl_disable(lane->pad->padctl); | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | static int tegra210_pcie_phy_power_on(struct phy *phy) | ||
| 1486 | { | ||
| 1487 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1488 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1489 | u32 value; | ||
| 1490 | int err; | ||
| 1491 | |||
| 1492 | mutex_lock(&padctl->lock); | ||
| 1493 | |||
| 1494 | err = tegra210_pex_uphy_enable(padctl); | ||
| 1495 | if (err < 0) | ||
| 1496 | goto unlock; | ||
| 1497 | |||
| 1498 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1499 | value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); | ||
| 1500 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1501 | |||
| 1502 | unlock: | ||
| 1503 | mutex_unlock(&padctl->lock); | ||
| 1504 | return err; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | static int tegra210_pcie_phy_power_off(struct phy *phy) | ||
| 1508 | { | ||
| 1509 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1510 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1511 | u32 value; | ||
| 1512 | |||
| 1513 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1514 | value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); | ||
| 1515 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1516 | |||
| 1517 | tegra210_pex_uphy_disable(padctl); | ||
| 1518 | |||
| 1519 | return 0; | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | static const struct phy_ops tegra210_pcie_phy_ops = { | ||
| 1523 | .init = tegra210_pcie_phy_init, | ||
| 1524 | .exit = tegra210_pcie_phy_exit, | ||
| 1525 | .power_on = tegra210_pcie_phy_power_on, | ||
| 1526 | .power_off = tegra210_pcie_phy_power_off, | ||
| 1527 | .owner = THIS_MODULE, | ||
| 1528 | }; | ||
| 1529 | |||
| 1530 | static struct tegra_xusb_pad * | ||
| 1531 | tegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 1532 | const struct tegra_xusb_pad_soc *soc, | ||
| 1533 | struct device_node *np) | ||
| 1534 | { | ||
| 1535 | struct tegra_xusb_pcie_pad *pcie; | ||
| 1536 | struct tegra_xusb_pad *pad; | ||
| 1537 | int err; | ||
| 1538 | |||
| 1539 | pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); | ||
| 1540 | if (!pcie) | ||
| 1541 | return ERR_PTR(-ENOMEM); | ||
| 1542 | |||
| 1543 | pad = &pcie->base; | ||
| 1544 | pad->ops = &tegra210_pcie_lane_ops; | ||
| 1545 | pad->soc = soc; | ||
| 1546 | |||
| 1547 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 1548 | if (err < 0) { | ||
| 1549 | kfree(pcie); | ||
| 1550 | goto out; | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | pcie->pll = devm_clk_get(&pad->dev, "pll"); | ||
| 1554 | if (IS_ERR(pcie->pll)) { | ||
| 1555 | err = PTR_ERR(pcie->pll); | ||
| 1556 | dev_err(&pad->dev, "failed to get PLL: %d\n", err); | ||
| 1557 | goto unregister; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | pcie->rst = devm_reset_control_get(&pad->dev, "phy"); | ||
| 1561 | if (IS_ERR(pcie->rst)) { | ||
| 1562 | err = PTR_ERR(pcie->rst); | ||
| 1563 | dev_err(&pad->dev, "failed to get PCIe pad reset: %d\n", err); | ||
| 1564 | goto unregister; | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | err = tegra_xusb_pad_register(pad, &tegra210_pcie_phy_ops); | ||
| 1568 | if (err < 0) | ||
| 1569 | goto unregister; | ||
| 1570 | |||
| 1571 | dev_set_drvdata(&pad->dev, pad); | ||
| 1572 | |||
| 1573 | return pad; | ||
| 1574 | |||
| 1575 | unregister: | ||
| 1576 | device_unregister(&pad->dev); | ||
| 1577 | out: | ||
| 1578 | return ERR_PTR(err); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | static void tegra210_pcie_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1582 | { | ||
| 1583 | struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); | ||
| 1584 | |||
| 1585 | kfree(pcie); | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | static const struct tegra_xusb_pad_ops tegra210_pcie_ops = { | ||
| 1589 | .probe = tegra210_pcie_pad_probe, | ||
| 1590 | .remove = tegra210_pcie_pad_remove, | ||
| 1591 | }; | ||
| 1592 | |||
| 1593 | static const struct tegra_xusb_pad_soc tegra210_pcie_pad = { | ||
| 1594 | .name = "pcie", | ||
| 1595 | .num_lanes = ARRAY_SIZE(tegra210_pcie_lanes), | ||
| 1596 | .lanes = tegra210_pcie_lanes, | ||
| 1597 | .ops = &tegra210_pcie_ops, | ||
| 1598 | }; | ||
| 1599 | |||
| 1600 | static const struct tegra_xusb_lane_soc tegra210_sata_lanes[] = { | ||
| 1601 | TEGRA210_LANE("sata-0", 0x028, 30, 0x3, pcie), | ||
| 1602 | }; | ||
| 1603 | |||
| 1604 | static struct tegra_xusb_lane * | ||
| 1605 | tegra210_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, | ||
| 1606 | unsigned int index) | ||
| 1607 | { | ||
| 1608 | struct tegra_xusb_sata_lane *sata; | ||
| 1609 | int err; | ||
| 1610 | |||
| 1611 | sata = kzalloc(sizeof(*sata), GFP_KERNEL); | ||
| 1612 | if (!sata) | ||
| 1613 | return ERR_PTR(-ENOMEM); | ||
| 1614 | |||
| 1615 | INIT_LIST_HEAD(&sata->base.list); | ||
| 1616 | sata->base.soc = &pad->soc->lanes[index]; | ||
| 1617 | sata->base.index = index; | ||
| 1618 | sata->base.pad = pad; | ||
| 1619 | sata->base.np = np; | ||
| 1620 | |||
| 1621 | err = tegra_xusb_lane_parse_dt(&sata->base, np); | ||
| 1622 | if (err < 0) { | ||
| 1623 | kfree(sata); | ||
| 1624 | return ERR_PTR(err); | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | return &sata->base; | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | static void tegra210_sata_lane_remove(struct tegra_xusb_lane *lane) | ||
| 1631 | { | ||
| 1632 | struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); | ||
| 1633 | |||
| 1634 | kfree(sata); | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | static const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = { | ||
| 1638 | .probe = tegra210_sata_lane_probe, | ||
| 1639 | .remove = tegra210_sata_lane_remove, | ||
| 1640 | }; | ||
| 1641 | |||
| 1642 | static int tegra210_sata_phy_init(struct phy *phy) | ||
| 1643 | { | ||
| 1644 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1645 | |||
| 1646 | return tegra210_xusb_padctl_enable(lane->pad->padctl); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | static int tegra210_sata_phy_exit(struct phy *phy) | ||
| 1650 | { | ||
| 1651 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1652 | |||
| 1653 | return tegra210_xusb_padctl_disable(lane->pad->padctl); | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | static int tegra210_sata_phy_power_on(struct phy *phy) | ||
| 1657 | { | ||
| 1658 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1659 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1660 | u32 value; | ||
| 1661 | int err; | ||
| 1662 | |||
| 1663 | mutex_lock(&padctl->lock); | ||
| 1664 | |||
| 1665 | err = tegra210_sata_uphy_enable(padctl, false); | ||
| 1666 | if (err < 0) | ||
| 1667 | goto unlock; | ||
| 1668 | |||
| 1669 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1670 | value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); | ||
| 1671 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1672 | |||
| 1673 | unlock: | ||
| 1674 | mutex_unlock(&padctl->lock); | ||
| 1675 | return err; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | static int tegra210_sata_phy_power_off(struct phy *phy) | ||
| 1679 | { | ||
| 1680 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 1681 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 1682 | u32 value; | ||
| 1683 | |||
| 1684 | value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1685 | value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); | ||
| 1686 | padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); | ||
| 1687 | |||
| 1688 | tegra210_sata_uphy_disable(lane->pad->padctl); | ||
| 1689 | |||
| 1690 | return 0; | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | static const struct phy_ops tegra210_sata_phy_ops = { | ||
| 1694 | .init = tegra210_sata_phy_init, | ||
| 1695 | .exit = tegra210_sata_phy_exit, | ||
| 1696 | .power_on = tegra210_sata_phy_power_on, | ||
| 1697 | .power_off = tegra210_sata_phy_power_off, | ||
| 1698 | .owner = THIS_MODULE, | ||
| 1699 | }; | ||
| 1700 | |||
| 1701 | static struct tegra_xusb_pad * | ||
| 1702 | tegra210_sata_pad_probe(struct tegra_xusb_padctl *padctl, | ||
| 1703 | const struct tegra_xusb_pad_soc *soc, | ||
| 1704 | struct device_node *np) | ||
| 1705 | { | ||
| 1706 | struct tegra_xusb_sata_pad *sata; | ||
| 1707 | struct tegra_xusb_pad *pad; | ||
| 1708 | int err; | ||
| 1709 | |||
| 1710 | sata = kzalloc(sizeof(*sata), GFP_KERNEL); | ||
| 1711 | if (!sata) | ||
| 1712 | return ERR_PTR(-ENOMEM); | ||
| 1713 | |||
| 1714 | pad = &sata->base; | ||
| 1715 | pad->ops = &tegra210_sata_lane_ops; | ||
| 1716 | pad->soc = soc; | ||
| 1717 | |||
| 1718 | err = tegra_xusb_pad_init(pad, padctl, np); | ||
| 1719 | if (err < 0) { | ||
| 1720 | kfree(sata); | ||
| 1721 | goto out; | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | sata->rst = devm_reset_control_get(&pad->dev, "phy"); | ||
| 1725 | if (IS_ERR(sata->rst)) { | ||
| 1726 | err = PTR_ERR(sata->rst); | ||
| 1727 | dev_err(&pad->dev, "failed to get SATA pad reset: %d\n", err); | ||
| 1728 | goto unregister; | ||
| 1729 | } | ||
| 1730 | |||
| 1731 | err = tegra_xusb_pad_register(pad, &tegra210_sata_phy_ops); | ||
| 1732 | if (err < 0) | ||
| 1733 | goto unregister; | ||
| 1734 | |||
| 1735 | dev_set_drvdata(&pad->dev, pad); | ||
| 1736 | |||
| 1737 | return pad; | ||
| 1738 | |||
| 1739 | unregister: | ||
| 1740 | device_unregister(&pad->dev); | ||
| 1741 | out: | ||
| 1742 | return ERR_PTR(err); | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | static void tegra210_sata_pad_remove(struct tegra_xusb_pad *pad) | ||
| 1746 | { | ||
| 1747 | struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); | ||
| 1748 | |||
| 1749 | kfree(sata); | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | static const struct tegra_xusb_pad_ops tegra210_sata_ops = { | ||
| 1753 | .probe = tegra210_sata_pad_probe, | ||
| 1754 | .remove = tegra210_sata_pad_remove, | ||
| 1755 | }; | ||
| 1756 | |||
| 1757 | static const struct tegra_xusb_pad_soc tegra210_sata_pad = { | ||
| 1758 | .name = "sata", | ||
| 1759 | .num_lanes = ARRAY_SIZE(tegra210_sata_lanes), | ||
| 1760 | .lanes = tegra210_sata_lanes, | ||
| 1761 | .ops = &tegra210_sata_ops, | ||
| 1762 | }; | ||
| 1763 | |||
| 1764 | static const struct tegra_xusb_pad_soc * const tegra210_pads[] = { | ||
| 1765 | &tegra210_usb2_pad, | ||
| 1766 | &tegra210_hsic_pad, | ||
| 1767 | &tegra210_pcie_pad, | ||
| 1768 | &tegra210_sata_pad, | ||
| 1769 | }; | ||
| 1770 | |||
| 1771 | static int tegra210_usb2_port_enable(struct tegra_xusb_port *port) | ||
| 1772 | { | ||
| 1773 | return 0; | ||
| 1774 | } | ||
| 1775 | |||
| 1776 | static void tegra210_usb2_port_disable(struct tegra_xusb_port *port) | ||
| 1777 | { | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | static struct tegra_xusb_lane * | ||
| 1781 | tegra210_usb2_port_map(struct tegra_xusb_port *port) | ||
| 1782 | { | ||
| 1783 | return tegra_xusb_find_lane(port->padctl, "usb2", port->index); | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static const struct tegra_xusb_port_ops tegra210_usb2_port_ops = { | ||
| 1787 | .enable = tegra210_usb2_port_enable, | ||
| 1788 | .disable = tegra210_usb2_port_disable, | ||
| 1789 | .map = tegra210_usb2_port_map, | ||
| 1790 | }; | ||
| 1791 | |||
| 1792 | static int tegra210_hsic_port_enable(struct tegra_xusb_port *port) | ||
| 1793 | { | ||
| 1794 | return 0; | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | static void tegra210_hsic_port_disable(struct tegra_xusb_port *port) | ||
| 1798 | { | ||
| 1799 | } | ||
| 1800 | |||
| 1801 | static struct tegra_xusb_lane * | ||
| 1802 | tegra210_hsic_port_map(struct tegra_xusb_port *port) | ||
| 1803 | { | ||
| 1804 | return tegra_xusb_find_lane(port->padctl, "hsic", port->index); | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | static const struct tegra_xusb_port_ops tegra210_hsic_port_ops = { | ||
| 1808 | .enable = tegra210_hsic_port_enable, | ||
| 1809 | .disable = tegra210_hsic_port_disable, | ||
| 1810 | .map = tegra210_hsic_port_map, | ||
| 1811 | }; | ||
| 1812 | |||
| 1813 | static int tegra210_usb3_port_enable(struct tegra_xusb_port *port) | ||
| 1814 | { | ||
| 1815 | struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); | ||
| 1816 | struct tegra_xusb_padctl *padctl = port->padctl; | ||
| 1817 | struct tegra_xusb_lane *lane = usb3->base.lane; | ||
| 1818 | unsigned int index = port->index; | ||
| 1819 | u32 value; | ||
| 1820 | int err; | ||
| 1821 | |||
| 1822 | value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1823 | |||
| 1824 | if (!usb3->internal) | ||
| 1825 | value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); | ||
| 1826 | else | ||
| 1827 | value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); | ||
| 1828 | |||
| 1829 | value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); | ||
| 1830 | value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); | ||
| 1831 | padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1832 | |||
| 1833 | /* | ||
| 1834 | * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks | ||
| 1835 | * and conditionalize based on mux function? This seems to work, but | ||
| 1836 | * might not be the exact proper sequence. | ||
| 1837 | */ | ||
| 1838 | err = regulator_enable(usb3->supply); | ||
| 1839 | if (err < 0) | ||
| 1840 | return err; | ||
| 1841 | |||
| 1842 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); | ||
| 1843 | value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK << | ||
| 1844 | XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT); | ||
| 1845 | value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL << | ||
| 1846 | XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT; | ||
| 1847 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); | ||
| 1848 | |||
| 1849 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); | ||
| 1850 | value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK << | ||
| 1851 | XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT); | ||
| 1852 | value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL << | ||
| 1853 | XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT; | ||
| 1854 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); | ||
| 1855 | |||
| 1856 | padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL, | ||
| 1857 | XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index)); | ||
| 1858 | |||
| 1859 | value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); | ||
| 1860 | value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK << | ||
| 1861 | XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT); | ||
| 1862 | value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL << | ||
| 1863 | XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT; | ||
| 1864 | padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); | ||
| 1865 | |||
| 1866 | padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL, | ||
| 1867 | XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index)); | ||
| 1868 | |||
| 1869 | if (lane->pad == padctl->sata) | ||
| 1870 | err = tegra210_sata_uphy_enable(padctl, true); | ||
| 1871 | else | ||
| 1872 | err = tegra210_pex_uphy_enable(padctl); | ||
| 1873 | |||
| 1874 | if (err) { | ||
| 1875 | dev_err(&port->dev, "%s: failed to enable UPHY: %d\n", | ||
| 1876 | __func__, err); | ||
| 1877 | return err; | ||
| 1878 | } | ||
| 1879 | |||
| 1880 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1881 | value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); | ||
| 1882 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1883 | |||
| 1884 | usleep_range(100, 200); | ||
| 1885 | |||
| 1886 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1887 | value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); | ||
| 1888 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1889 | |||
| 1890 | usleep_range(100, 200); | ||
| 1891 | |||
| 1892 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1893 | value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); | ||
| 1894 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1895 | |||
| 1896 | return 0; | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | static void tegra210_usb3_port_disable(struct tegra_xusb_port *port) | ||
| 1900 | { | ||
| 1901 | struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); | ||
| 1902 | struct tegra_xusb_padctl *padctl = port->padctl; | ||
| 1903 | struct tegra_xusb_lane *lane = port->lane; | ||
| 1904 | unsigned int index = port->index; | ||
| 1905 | u32 value; | ||
| 1906 | |||
| 1907 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1908 | value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); | ||
| 1909 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1910 | |||
| 1911 | usleep_range(100, 200); | ||
| 1912 | |||
| 1913 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1914 | value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); | ||
| 1915 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1916 | |||
| 1917 | usleep_range(250, 350); | ||
| 1918 | |||
| 1919 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1920 | value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); | ||
| 1921 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); | ||
| 1922 | |||
| 1923 | if (lane->pad == padctl->sata) | ||
| 1924 | tegra210_sata_uphy_disable(padctl); | ||
| 1925 | else | ||
| 1926 | tegra210_pex_uphy_disable(padctl); | ||
| 1927 | |||
| 1928 | regulator_disable(usb3->supply); | ||
| 1929 | |||
| 1930 | value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1931 | value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); | ||
| 1932 | value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, 0x7); | ||
| 1933 | padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); | ||
| 1934 | } | ||
| 1935 | |||
| 1936 | static const struct tegra_xusb_lane_map tegra210_usb3_map[] = { | ||
| 1937 | { 0, "pcie", 6 }, | ||
| 1938 | { 1, "pcie", 5 }, | ||
| 1939 | { 2, "pcie", 0 }, | ||
| 1940 | { 2, "pcie", 3 }, | ||
| 1941 | { 3, "pcie", 4 }, | ||
| 1942 | { 3, "pcie", 4 }, | ||
| 1943 | { 0, NULL, 0 } | ||
| 1944 | }; | ||
| 1945 | |||
| 1946 | static struct tegra_xusb_lane * | ||
| 1947 | tegra210_usb3_port_map(struct tegra_xusb_port *port) | ||
| 1948 | { | ||
| 1949 | return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss"); | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = { | ||
| 1953 | .enable = tegra210_usb3_port_enable, | ||
| 1954 | .disable = tegra210_usb3_port_disable, | ||
| 1955 | .map = tegra210_usb3_port_map, | ||
| 1956 | }; | ||
| 1957 | |||
| 1958 | static int | ||
| 1959 | tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse) | ||
| 1960 | { | ||
| 1961 | unsigned int i; | ||
| 1962 | u32 value; | ||
| 1963 | int err; | ||
| 1964 | |||
| 1965 | err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); | ||
| 1966 | if (err < 0) | ||
| 1967 | return err; | ||
| 1968 | |||
| 1969 | for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { | ||
| 1970 | fuse->hs_curr_level[i] = | ||
| 1971 | (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & | ||
| 1972 | FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; | ||
| 1973 | } | ||
| 1974 | |||
| 1975 | fuse->hs_term_range_adj = | ||
| 1976 | (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & | ||
| 1977 | FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; | ||
| 1978 | |||
| 1979 | err = tegra_fuse_readl(TEGRA_FUSE_USB_CALIB_EXT_0, &value); | ||
| 1980 | if (err < 0) | ||
| 1981 | return err; | ||
| 1982 | |||
| 1983 | fuse->rpd_ctrl = | ||
| 1984 | (value >> FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT) & | ||
| 1985 | FUSE_USB_CALIB_EXT_RPD_CTRL_MASK; | ||
| 1986 | |||
| 1987 | return 0; | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | static struct tegra_xusb_padctl * | ||
| 1991 | tegra210_xusb_padctl_probe(struct device *dev, | ||
| 1992 | const struct tegra_xusb_padctl_soc *soc) | ||
| 1993 | { | ||
| 1994 | struct tegra210_xusb_padctl *padctl; | ||
| 1995 | int err; | ||
| 1996 | |||
| 1997 | padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); | ||
| 1998 | if (!padctl) | ||
| 1999 | return ERR_PTR(-ENOMEM); | ||
| 2000 | |||
| 2001 | padctl->base.dev = dev; | ||
| 2002 | padctl->base.soc = soc; | ||
| 2003 | |||
| 2004 | err = tegra210_xusb_read_fuse_calibration(&padctl->fuse); | ||
| 2005 | if (err < 0) | ||
| 2006 | return ERR_PTR(err); | ||
| 2007 | |||
| 2008 | return &padctl->base; | ||
| 2009 | } | ||
| 2010 | |||
| 2011 | static void tegra210_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) | ||
| 2012 | { | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | static const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = { | ||
| 2016 | .probe = tegra210_xusb_padctl_probe, | ||
| 2017 | .remove = tegra210_xusb_padctl_remove, | ||
| 2018 | .usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect, | ||
| 2019 | .hsic_set_idle = tegra210_hsic_set_idle, | ||
| 2020 | }; | ||
| 2021 | |||
| 2022 | const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = { | ||
| 2023 | .num_pads = ARRAY_SIZE(tegra210_pads), | ||
| 2024 | .pads = tegra210_pads, | ||
| 2025 | .ports = { | ||
| 2026 | .usb2 = { | ||
| 2027 | .ops = &tegra210_usb2_port_ops, | ||
| 2028 | .count = 4, | ||
| 2029 | }, | ||
| 2030 | .hsic = { | ||
| 2031 | .ops = &tegra210_hsic_port_ops, | ||
| 2032 | .count = 1, | ||
| 2033 | }, | ||
| 2034 | .usb3 = { | ||
| 2035 | .ops = &tegra210_usb3_port_ops, | ||
| 2036 | .count = 4, | ||
| 2037 | }, | ||
| 2038 | }, | ||
| 2039 | .ops = &tegra210_xusb_padctl_ops, | ||
| 2040 | }; | ||
| 2041 | EXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc); | ||
| 2042 | |||
| 2043 | MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>"); | ||
| 2044 | MODULE_DESCRIPTION("NVIDIA Tegra 210 XUSB Pad Controller driver"); | ||
| 2045 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c new file mode 100644 index 000000000000..ec83dfdbc206 --- /dev/null +++ b/drivers/phy/tegra/xusb.c | |||
| @@ -0,0 +1,1021 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/mailbox_client.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/of_device.h> | ||
| 20 | #include <linux/phy/phy.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/regulator/consumer.h> | ||
| 23 | #include <linux/reset.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/workqueue.h> | ||
| 26 | |||
| 27 | #include <soc/tegra/fuse.h> | ||
| 28 | |||
| 29 | #include "xusb.h" | ||
| 30 | |||
| 31 | static struct phy *tegra_xusb_pad_of_xlate(struct device *dev, | ||
| 32 | struct of_phandle_args *args) | ||
| 33 | { | ||
| 34 | struct tegra_xusb_pad *pad = dev_get_drvdata(dev); | ||
| 35 | struct phy *phy = NULL; | ||
| 36 | unsigned int i; | ||
| 37 | |||
| 38 | if (args->args_count != 0) | ||
| 39 | return ERR_PTR(-EINVAL); | ||
| 40 | |||
| 41 | for (i = 0; i < pad->soc->num_lanes; i++) { | ||
| 42 | if (!pad->lanes[i]) | ||
| 43 | continue; | ||
| 44 | |||
| 45 | if (pad->lanes[i]->dev.of_node == args->np) { | ||
| 46 | phy = pad->lanes[i]; | ||
| 47 | break; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | if (phy == NULL) | ||
| 52 | phy = ERR_PTR(-ENODEV); | ||
| 53 | |||
| 54 | return phy; | ||
| 55 | } | ||
| 56 | |||
| 57 | static const struct of_device_id tegra_xusb_padctl_of_match[] = { | ||
| 58 | #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) | ||
| 59 | { | ||
| 60 | .compatible = "nvidia,tegra124-xusb-padctl", | ||
| 61 | .data = &tegra124_xusb_padctl_soc, | ||
| 62 | }, | ||
| 63 | #endif | ||
| 64 | #if defined(CONFIG_ARCH_TEGRA_210_SOC) | ||
| 65 | { | ||
| 66 | .compatible = "nvidia,tegra210-xusb-padctl", | ||
| 67 | .data = &tegra210_xusb_padctl_soc, | ||
| 68 | }, | ||
| 69 | #endif | ||
| 70 | { } | ||
| 71 | }; | ||
| 72 | MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); | ||
| 73 | |||
| 74 | static struct device_node * | ||
| 75 | tegra_xusb_find_pad_node(struct tegra_xusb_padctl *padctl, const char *name) | ||
| 76 | { | ||
| 77 | /* | ||
| 78 | * of_find_node_by_name() drops a reference, so make sure to grab one. | ||
| 79 | */ | ||
| 80 | struct device_node *np = of_node_get(padctl->dev->of_node); | ||
| 81 | |||
| 82 | np = of_find_node_by_name(np, "pads"); | ||
| 83 | if (np) | ||
| 84 | np = of_find_node_by_name(np, name); | ||
| 85 | |||
| 86 | return np; | ||
| 87 | } | ||
| 88 | |||
| 89 | static struct device_node * | ||
| 90 | tegra_xusb_pad_find_phy_node(struct tegra_xusb_pad *pad, unsigned int index) | ||
| 91 | { | ||
| 92 | /* | ||
| 93 | * of_find_node_by_name() drops a reference, so make sure to grab one. | ||
| 94 | */ | ||
| 95 | struct device_node *np = of_node_get(pad->dev.of_node); | ||
| 96 | |||
| 97 | np = of_find_node_by_name(np, "lanes"); | ||
| 98 | if (!np) | ||
| 99 | return NULL; | ||
| 100 | |||
| 101 | return of_find_node_by_name(np, pad->soc->lanes[index].name); | ||
| 102 | } | ||
| 103 | |||
| 104 | int tegra_xusb_lane_lookup_function(struct tegra_xusb_lane *lane, | ||
| 105 | const char *function) | ||
| 106 | { | ||
| 107 | unsigned int i; | ||
| 108 | |||
| 109 | for (i = 0; i < lane->soc->num_funcs; i++) | ||
| 110 | if (strcmp(function, lane->soc->funcs[i]) == 0) | ||
| 111 | return i; | ||
| 112 | |||
| 113 | return -EINVAL; | ||
| 114 | } | ||
| 115 | |||
| 116 | int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane, | ||
| 117 | struct device_node *np) | ||
| 118 | { | ||
| 119 | struct device *dev = &lane->pad->dev; | ||
| 120 | const char *function; | ||
| 121 | int err; | ||
| 122 | |||
| 123 | err = of_property_read_string(np, "nvidia,function", &function); | ||
| 124 | if (err < 0) | ||
| 125 | return err; | ||
| 126 | |||
| 127 | err = tegra_xusb_lane_lookup_function(lane, function); | ||
| 128 | if (err < 0) { | ||
| 129 | dev_err(dev, "invalid function \"%s\" for lane \"%s\"\n", | ||
| 130 | function, np->name); | ||
| 131 | return err; | ||
| 132 | } | ||
| 133 | |||
| 134 | lane->function = err; | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static void tegra_xusb_lane_destroy(struct phy *phy) | ||
| 140 | { | ||
| 141 | if (phy) { | ||
| 142 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | ||
| 143 | |||
| 144 | lane->pad->ops->remove(lane); | ||
| 145 | phy_destroy(phy); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | static void tegra_xusb_pad_release(struct device *dev) | ||
| 150 | { | ||
| 151 | struct tegra_xusb_pad *pad = to_tegra_xusb_pad(dev); | ||
| 152 | |||
| 153 | pad->soc->ops->remove(pad); | ||
| 154 | } | ||
| 155 | |||
| 156 | static struct device_type tegra_xusb_pad_type = { | ||
| 157 | .release = tegra_xusb_pad_release, | ||
| 158 | }; | ||
| 159 | |||
| 160 | int tegra_xusb_pad_init(struct tegra_xusb_pad *pad, | ||
| 161 | struct tegra_xusb_padctl *padctl, | ||
| 162 | struct device_node *np) | ||
| 163 | { | ||
| 164 | int err; | ||
| 165 | |||
| 166 | device_initialize(&pad->dev); | ||
| 167 | INIT_LIST_HEAD(&pad->list); | ||
| 168 | pad->dev.parent = padctl->dev; | ||
| 169 | pad->dev.type = &tegra_xusb_pad_type; | ||
| 170 | pad->dev.of_node = np; | ||
| 171 | pad->padctl = padctl; | ||
| 172 | |||
| 173 | err = dev_set_name(&pad->dev, "%s", pad->soc->name); | ||
| 174 | if (err < 0) | ||
| 175 | goto unregister; | ||
| 176 | |||
| 177 | err = device_add(&pad->dev); | ||
| 178 | if (err < 0) | ||
| 179 | goto unregister; | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | |||
| 183 | unregister: | ||
| 184 | device_unregister(&pad->dev); | ||
| 185 | return err; | ||
| 186 | } | ||
| 187 | |||
| 188 | int tegra_xusb_pad_register(struct tegra_xusb_pad *pad, | ||
| 189 | const struct phy_ops *ops) | ||
| 190 | { | ||
| 191 | struct device_node *children; | ||
| 192 | struct phy *lane; | ||
| 193 | unsigned int i; | ||
| 194 | int err; | ||
| 195 | |||
| 196 | children = of_find_node_by_name(pad->dev.of_node, "lanes"); | ||
| 197 | if (!children) | ||
| 198 | return -ENODEV; | ||
| 199 | |||
| 200 | pad->lanes = devm_kcalloc(&pad->dev, pad->soc->num_lanes, sizeof(lane), | ||
| 201 | GFP_KERNEL); | ||
| 202 | if (!pad->lanes) { | ||
| 203 | of_node_put(children); | ||
| 204 | return -ENOMEM; | ||
| 205 | } | ||
| 206 | |||
| 207 | for (i = 0; i < pad->soc->num_lanes; i++) { | ||
| 208 | struct device_node *np = tegra_xusb_pad_find_phy_node(pad, i); | ||
| 209 | struct tegra_xusb_lane *lane; | ||
| 210 | |||
| 211 | /* skip disabled lanes */ | ||
| 212 | if (!np || !of_device_is_available(np)) { | ||
| 213 | of_node_put(np); | ||
| 214 | continue; | ||
| 215 | } | ||
| 216 | |||
| 217 | pad->lanes[i] = phy_create(&pad->dev, np, ops); | ||
| 218 | if (IS_ERR(pad->lanes[i])) { | ||
| 219 | err = PTR_ERR(pad->lanes[i]); | ||
| 220 | of_node_put(np); | ||
| 221 | goto remove; | ||
| 222 | } | ||
| 223 | |||
| 224 | lane = pad->ops->probe(pad, np, i); | ||
| 225 | if (IS_ERR(lane)) { | ||
| 226 | phy_destroy(pad->lanes[i]); | ||
| 227 | err = PTR_ERR(lane); | ||
| 228 | goto remove; | ||
| 229 | } | ||
| 230 | |||
| 231 | list_add_tail(&lane->list, &pad->padctl->lanes); | ||
| 232 | phy_set_drvdata(pad->lanes[i], lane); | ||
| 233 | } | ||
| 234 | |||
| 235 | pad->provider = of_phy_provider_register_full(&pad->dev, children, | ||
| 236 | tegra_xusb_pad_of_xlate); | ||
| 237 | if (IS_ERR(pad->provider)) { | ||
| 238 | err = PTR_ERR(pad->provider); | ||
| 239 | goto remove; | ||
| 240 | } | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | |||
| 244 | remove: | ||
| 245 | while (i--) | ||
| 246 | tegra_xusb_lane_destroy(pad->lanes[i]); | ||
| 247 | |||
| 248 | of_node_put(children); | ||
| 249 | |||
| 250 | return err; | ||
| 251 | } | ||
| 252 | |||
| 253 | void tegra_xusb_pad_unregister(struct tegra_xusb_pad *pad) | ||
| 254 | { | ||
| 255 | unsigned int i = pad->soc->num_lanes; | ||
| 256 | |||
| 257 | of_phy_provider_unregister(pad->provider); | ||
| 258 | |||
| 259 | while (i--) | ||
| 260 | tegra_xusb_lane_destroy(pad->lanes[i]); | ||
| 261 | |||
| 262 | device_unregister(&pad->dev); | ||
| 263 | } | ||
| 264 | |||
| 265 | static struct tegra_xusb_pad * | ||
| 266 | tegra_xusb_pad_create(struct tegra_xusb_padctl *padctl, | ||
| 267 | const struct tegra_xusb_pad_soc *soc) | ||
| 268 | { | ||
| 269 | struct tegra_xusb_pad *pad; | ||
| 270 | struct device_node *np; | ||
| 271 | int err; | ||
| 272 | |||
| 273 | np = tegra_xusb_find_pad_node(padctl, soc->name); | ||
| 274 | if (!np || !of_device_is_available(np)) | ||
| 275 | return NULL; | ||
| 276 | |||
| 277 | pad = soc->ops->probe(padctl, soc, np); | ||
| 278 | if (IS_ERR(pad)) { | ||
| 279 | err = PTR_ERR(pad); | ||
| 280 | dev_err(padctl->dev, "failed to create pad %s: %d\n", | ||
| 281 | soc->name, err); | ||
| 282 | return ERR_PTR(err); | ||
| 283 | } | ||
| 284 | |||
| 285 | /* XXX move this into ->probe() to avoid string comparison */ | ||
| 286 | if (strcmp(soc->name, "pcie") == 0) | ||
| 287 | padctl->pcie = pad; | ||
| 288 | |||
| 289 | if (strcmp(soc->name, "sata") == 0) | ||
| 290 | padctl->sata = pad; | ||
| 291 | |||
| 292 | if (strcmp(soc->name, "usb2") == 0) | ||
| 293 | padctl->usb2 = pad; | ||
| 294 | |||
| 295 | if (strcmp(soc->name, "ulpi") == 0) | ||
| 296 | padctl->ulpi = pad; | ||
| 297 | |||
| 298 | if (strcmp(soc->name, "hsic") == 0) | ||
| 299 | padctl->hsic = pad; | ||
| 300 | |||
| 301 | return pad; | ||
| 302 | } | ||
| 303 | |||
| 304 | static void __tegra_xusb_remove_pads(struct tegra_xusb_padctl *padctl) | ||
| 305 | { | ||
| 306 | struct tegra_xusb_pad *pad, *tmp; | ||
| 307 | |||
| 308 | list_for_each_entry_safe_reverse(pad, tmp, &padctl->pads, list) { | ||
| 309 | list_del(&pad->list); | ||
| 310 | tegra_xusb_pad_unregister(pad); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | static void tegra_xusb_remove_pads(struct tegra_xusb_padctl *padctl) | ||
| 315 | { | ||
| 316 | mutex_lock(&padctl->lock); | ||
| 317 | __tegra_xusb_remove_pads(padctl); | ||
| 318 | mutex_unlock(&padctl->lock); | ||
| 319 | } | ||
| 320 | |||
| 321 | static void tegra_xusb_lane_program(struct tegra_xusb_lane *lane) | ||
| 322 | { | ||
| 323 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | ||
| 324 | const struct tegra_xusb_lane_soc *soc = lane->soc; | ||
| 325 | u32 value; | ||
| 326 | |||
| 327 | /* choose function */ | ||
| 328 | value = padctl_readl(padctl, soc->offset); | ||
| 329 | value &= ~(soc->mask << soc->shift); | ||
| 330 | value |= lane->function << soc->shift; | ||
| 331 | padctl_writel(padctl, value, soc->offset); | ||
| 332 | } | ||
| 333 | |||
| 334 | static void tegra_xusb_pad_program(struct tegra_xusb_pad *pad) | ||
| 335 | { | ||
| 336 | unsigned int i; | ||
| 337 | |||
| 338 | for (i = 0; i < pad->soc->num_lanes; i++) { | ||
| 339 | struct tegra_xusb_lane *lane; | ||
| 340 | |||
| 341 | if (pad->lanes[i]) { | ||
| 342 | lane = phy_get_drvdata(pad->lanes[i]); | ||
| 343 | tegra_xusb_lane_program(lane); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | static int tegra_xusb_setup_pads(struct tegra_xusb_padctl *padctl) | ||
| 349 | { | ||
| 350 | struct tegra_xusb_pad *pad; | ||
| 351 | unsigned int i; | ||
| 352 | |||
| 353 | mutex_lock(&padctl->lock); | ||
| 354 | |||
| 355 | for (i = 0; i < padctl->soc->num_pads; i++) { | ||
| 356 | const struct tegra_xusb_pad_soc *soc = padctl->soc->pads[i]; | ||
| 357 | int err; | ||
| 358 | |||
| 359 | pad = tegra_xusb_pad_create(padctl, soc); | ||
| 360 | if (IS_ERR(pad)) { | ||
| 361 | err = PTR_ERR(pad); | ||
| 362 | dev_err(padctl->dev, "failed to create pad %s: %d\n", | ||
| 363 | soc->name, err); | ||
| 364 | __tegra_xusb_remove_pads(padctl); | ||
| 365 | mutex_unlock(&padctl->lock); | ||
| 366 | return err; | ||
| 367 | } | ||
| 368 | |||
| 369 | if (!pad) | ||
| 370 | continue; | ||
| 371 | |||
| 372 | list_add_tail(&pad->list, &padctl->pads); | ||
| 373 | } | ||
| 374 | |||
| 375 | list_for_each_entry(pad, &padctl->pads, list) | ||
| 376 | tegra_xusb_pad_program(pad); | ||
| 377 | |||
| 378 | mutex_unlock(&padctl->lock); | ||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | static bool tegra_xusb_lane_check(struct tegra_xusb_lane *lane, | ||
| 383 | const char *function) | ||
| 384 | { | ||
| 385 | const char *func = lane->soc->funcs[lane->function]; | ||
| 386 | |||
| 387 | return strcmp(function, func) == 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | struct tegra_xusb_lane *tegra_xusb_find_lane(struct tegra_xusb_padctl *padctl, | ||
| 391 | const char *type, | ||
| 392 | unsigned int index) | ||
| 393 | { | ||
| 394 | struct tegra_xusb_lane *lane, *hit = ERR_PTR(-ENODEV); | ||
| 395 | char *name; | ||
| 396 | |||
| 397 | name = kasprintf(GFP_KERNEL, "%s-%u", type, index); | ||
| 398 | if (!name) | ||
| 399 | return ERR_PTR(-ENOMEM); | ||
| 400 | |||
| 401 | list_for_each_entry(lane, &padctl->lanes, list) { | ||
| 402 | if (strcmp(lane->soc->name, name) == 0) { | ||
| 403 | hit = lane; | ||
| 404 | break; | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | kfree(name); | ||
| 409 | return hit; | ||
| 410 | } | ||
| 411 | |||
| 412 | struct tegra_xusb_lane * | ||
| 413 | tegra_xusb_port_find_lane(struct tegra_xusb_port *port, | ||
| 414 | const struct tegra_xusb_lane_map *map, | ||
| 415 | const char *function) | ||
| 416 | { | ||
| 417 | struct tegra_xusb_lane *lane, *match = ERR_PTR(-ENODEV); | ||
| 418 | |||
| 419 | for (map = map; map->type; map++) { | ||
| 420 | if (port->index != map->port) | ||
| 421 | continue; | ||
| 422 | |||
| 423 | lane = tegra_xusb_find_lane(port->padctl, map->type, | ||
| 424 | map->index); | ||
| 425 | if (IS_ERR(lane)) | ||
| 426 | continue; | ||
| 427 | |||
| 428 | if (!tegra_xusb_lane_check(lane, function)) | ||
| 429 | continue; | ||
| 430 | |||
| 431 | if (!IS_ERR(match)) | ||
| 432 | dev_err(&port->dev, "conflicting match: %s-%u / %s\n", | ||
| 433 | map->type, map->index, match->soc->name); | ||
| 434 | else | ||
| 435 | match = lane; | ||
| 436 | } | ||
| 437 | |||
| 438 | return match; | ||
| 439 | } | ||
| 440 | |||
| 441 | static struct device_node * | ||
| 442 | tegra_xusb_find_port_node(struct tegra_xusb_padctl *padctl, const char *type, | ||
| 443 | unsigned int index) | ||
| 444 | { | ||
| 445 | /* | ||
| 446 | * of_find_node_by_name() drops a reference, so make sure to grab one. | ||
| 447 | */ | ||
| 448 | struct device_node *np = of_node_get(padctl->dev->of_node); | ||
| 449 | |||
| 450 | np = of_find_node_by_name(np, "ports"); | ||
| 451 | if (np) { | ||
| 452 | char *name; | ||
| 453 | |||
| 454 | name = kasprintf(GFP_KERNEL, "%s-%u", type, index); | ||
| 455 | np = of_find_node_by_name(np, name); | ||
| 456 | kfree(name); | ||
| 457 | } | ||
| 458 | |||
| 459 | return np; | ||
| 460 | } | ||
| 461 | |||
| 462 | struct tegra_xusb_port * | ||
| 463 | tegra_xusb_find_port(struct tegra_xusb_padctl *padctl, const char *type, | ||
| 464 | unsigned int index) | ||
| 465 | { | ||
| 466 | struct tegra_xusb_port *port; | ||
| 467 | struct device_node *np; | ||
| 468 | |||
| 469 | np = tegra_xusb_find_port_node(padctl, type, index); | ||
| 470 | if (!np) | ||
| 471 | return NULL; | ||
| 472 | |||
| 473 | list_for_each_entry(port, &padctl->ports, list) { | ||
| 474 | if (np == port->dev.of_node) { | ||
| 475 | of_node_put(np); | ||
| 476 | return port; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | of_node_put(np); | ||
| 481 | |||
| 482 | return NULL; | ||
| 483 | } | ||
| 484 | |||
| 485 | struct tegra_xusb_usb2_port * | ||
| 486 | tegra_xusb_find_usb2_port(struct tegra_xusb_padctl *padctl, unsigned int index) | ||
| 487 | { | ||
| 488 | struct tegra_xusb_port *port; | ||
| 489 | |||
| 490 | port = tegra_xusb_find_port(padctl, "usb2", index); | ||
| 491 | if (port) | ||
| 492 | return to_usb2_port(port); | ||
| 493 | |||
| 494 | return NULL; | ||
| 495 | } | ||
| 496 | |||
| 497 | struct tegra_xusb_usb3_port * | ||
| 498 | tegra_xusb_find_usb3_port(struct tegra_xusb_padctl *padctl, unsigned int index) | ||
| 499 | { | ||
| 500 | struct tegra_xusb_port *port; | ||
| 501 | |||
| 502 | port = tegra_xusb_find_port(padctl, "usb3", index); | ||
| 503 | if (port) | ||
| 504 | return to_usb3_port(port); | ||
| 505 | |||
| 506 | return NULL; | ||
| 507 | } | ||
| 508 | |||
| 509 | static void tegra_xusb_port_release(struct device *dev) | ||
| 510 | { | ||
| 511 | } | ||
| 512 | |||
| 513 | static struct device_type tegra_xusb_port_type = { | ||
| 514 | .release = tegra_xusb_port_release, | ||
| 515 | }; | ||
| 516 | |||
| 517 | static int tegra_xusb_port_init(struct tegra_xusb_port *port, | ||
| 518 | struct tegra_xusb_padctl *padctl, | ||
| 519 | struct device_node *np, | ||
| 520 | const char *name, | ||
| 521 | unsigned int index) | ||
| 522 | { | ||
| 523 | int err; | ||
| 524 | |||
| 525 | INIT_LIST_HEAD(&port->list); | ||
| 526 | port->padctl = padctl; | ||
| 527 | port->index = index; | ||
| 528 | |||
| 529 | device_initialize(&port->dev); | ||
| 530 | port->dev.type = &tegra_xusb_port_type; | ||
| 531 | port->dev.of_node = of_node_get(np); | ||
| 532 | port->dev.parent = padctl->dev; | ||
| 533 | |||
| 534 | err = dev_set_name(&port->dev, "%s-%u", name, index); | ||
| 535 | if (err < 0) | ||
| 536 | goto unregister; | ||
| 537 | |||
| 538 | err = device_add(&port->dev); | ||
| 539 | if (err < 0) | ||
| 540 | goto unregister; | ||
| 541 | |||
| 542 | return 0; | ||
| 543 | |||
| 544 | unregister: | ||
| 545 | device_unregister(&port->dev); | ||
| 546 | return err; | ||
| 547 | } | ||
| 548 | |||
| 549 | static void tegra_xusb_port_unregister(struct tegra_xusb_port *port) | ||
| 550 | { | ||
| 551 | device_unregister(&port->dev); | ||
| 552 | } | ||
| 553 | |||
| 554 | static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2) | ||
| 555 | { | ||
| 556 | struct tegra_xusb_port *port = &usb2->base; | ||
| 557 | struct device_node *np = port->dev.of_node; | ||
| 558 | |||
| 559 | usb2->internal = of_property_read_bool(np, "nvidia,internal"); | ||
| 560 | |||
| 561 | usb2->supply = devm_regulator_get(&port->dev, "vbus"); | ||
| 562 | if (IS_ERR(usb2->supply)) | ||
| 563 | return PTR_ERR(usb2->supply); | ||
| 564 | |||
| 565 | return 0; | ||
| 566 | } | ||
| 567 | |||
| 568 | static int tegra_xusb_add_usb2_port(struct tegra_xusb_padctl *padctl, | ||
| 569 | unsigned int index) | ||
| 570 | { | ||
| 571 | struct tegra_xusb_usb2_port *usb2; | ||
| 572 | struct device_node *np; | ||
| 573 | int err = 0; | ||
| 574 | |||
| 575 | /* | ||
| 576 | * USB2 ports don't require additional properties, but if the port is | ||
| 577 | * marked as disabled there is no reason to register it. | ||
| 578 | */ | ||
| 579 | np = tegra_xusb_find_port_node(padctl, "usb2", index); | ||
| 580 | if (!np || !of_device_is_available(np)) | ||
| 581 | goto out; | ||
| 582 | |||
| 583 | usb2 = devm_kzalloc(padctl->dev, sizeof(*usb2), GFP_KERNEL); | ||
| 584 | if (!usb2) { | ||
| 585 | err = -ENOMEM; | ||
| 586 | goto out; | ||
| 587 | } | ||
| 588 | |||
| 589 | err = tegra_xusb_port_init(&usb2->base, padctl, np, "usb2", index); | ||
| 590 | if (err < 0) | ||
| 591 | goto out; | ||
| 592 | |||
| 593 | usb2->base.ops = padctl->soc->ports.usb2.ops; | ||
| 594 | |||
| 595 | usb2->base.lane = usb2->base.ops->map(&usb2->base); | ||
| 596 | if (IS_ERR(usb2->base.lane)) { | ||
| 597 | err = PTR_ERR(usb2->base.lane); | ||
| 598 | goto out; | ||
| 599 | } | ||
| 600 | |||
| 601 | err = tegra_xusb_usb2_port_parse_dt(usb2); | ||
| 602 | if (err < 0) { | ||
| 603 | tegra_xusb_port_unregister(&usb2->base); | ||
| 604 | goto out; | ||
| 605 | } | ||
| 606 | |||
| 607 | list_add_tail(&usb2->base.list, &padctl->ports); | ||
| 608 | |||
| 609 | out: | ||
| 610 | of_node_put(np); | ||
| 611 | return err; | ||
| 612 | } | ||
| 613 | |||
| 614 | static int tegra_xusb_ulpi_port_parse_dt(struct tegra_xusb_ulpi_port *ulpi) | ||
| 615 | { | ||
| 616 | struct tegra_xusb_port *port = &ulpi->base; | ||
| 617 | struct device_node *np = port->dev.of_node; | ||
| 618 | |||
| 619 | ulpi->internal = of_property_read_bool(np, "nvidia,internal"); | ||
| 620 | |||
| 621 | return 0; | ||
| 622 | } | ||
| 623 | |||
| 624 | static int tegra_xusb_add_ulpi_port(struct tegra_xusb_padctl *padctl, | ||
| 625 | unsigned int index) | ||
| 626 | { | ||
| 627 | struct tegra_xusb_ulpi_port *ulpi; | ||
| 628 | struct device_node *np; | ||
| 629 | int err = 0; | ||
| 630 | |||
| 631 | np = tegra_xusb_find_port_node(padctl, "ulpi", index); | ||
| 632 | if (!np || !of_device_is_available(np)) | ||
| 633 | goto out; | ||
| 634 | |||
| 635 | ulpi = devm_kzalloc(padctl->dev, sizeof(*ulpi), GFP_KERNEL); | ||
| 636 | if (!ulpi) { | ||
| 637 | err = -ENOMEM; | ||
| 638 | goto out; | ||
| 639 | } | ||
| 640 | |||
| 641 | err = tegra_xusb_port_init(&ulpi->base, padctl, np, "ulpi", index); | ||
| 642 | if (err < 0) | ||
| 643 | goto out; | ||
| 644 | |||
| 645 | ulpi->base.ops = padctl->soc->ports.ulpi.ops; | ||
| 646 | |||
| 647 | ulpi->base.lane = ulpi->base.ops->map(&ulpi->base); | ||
| 648 | if (IS_ERR(ulpi->base.lane)) { | ||
| 649 | err = PTR_ERR(ulpi->base.lane); | ||
| 650 | goto out; | ||
| 651 | } | ||
| 652 | |||
| 653 | err = tegra_xusb_ulpi_port_parse_dt(ulpi); | ||
| 654 | if (err < 0) { | ||
| 655 | tegra_xusb_port_unregister(&ulpi->base); | ||
| 656 | goto out; | ||
| 657 | } | ||
| 658 | |||
| 659 | list_add_tail(&ulpi->base.list, &padctl->ports); | ||
| 660 | |||
| 661 | out: | ||
| 662 | of_node_put(np); | ||
| 663 | return err; | ||
| 664 | } | ||
| 665 | |||
| 666 | static int tegra_xusb_hsic_port_parse_dt(struct tegra_xusb_hsic_port *hsic) | ||
| 667 | { | ||
| 668 | /* XXX */ | ||
| 669 | return 0; | ||
| 670 | } | ||
| 671 | |||
| 672 | static int tegra_xusb_add_hsic_port(struct tegra_xusb_padctl *padctl, | ||
| 673 | unsigned int index) | ||
| 674 | { | ||
| 675 | struct tegra_xusb_hsic_port *hsic; | ||
| 676 | struct device_node *np; | ||
| 677 | int err = 0; | ||
| 678 | |||
| 679 | np = tegra_xusb_find_port_node(padctl, "hsic", index); | ||
| 680 | if (!np || !of_device_is_available(np)) | ||
| 681 | goto out; | ||
| 682 | |||
| 683 | hsic = devm_kzalloc(padctl->dev, sizeof(*hsic), GFP_KERNEL); | ||
| 684 | if (!hsic) { | ||
| 685 | err = -ENOMEM; | ||
| 686 | goto out; | ||
| 687 | } | ||
| 688 | |||
| 689 | err = tegra_xusb_port_init(&hsic->base, padctl, np, "hsic", index); | ||
| 690 | if (err < 0) | ||
| 691 | goto out; | ||
| 692 | |||
| 693 | hsic->base.ops = padctl->soc->ports.hsic.ops; | ||
| 694 | |||
| 695 | hsic->base.lane = hsic->base.ops->map(&hsic->base); | ||
| 696 | if (IS_ERR(hsic->base.lane)) { | ||
| 697 | err = PTR_ERR(hsic->base.lane); | ||
| 698 | goto out; | ||
| 699 | } | ||
| 700 | |||
| 701 | err = tegra_xusb_hsic_port_parse_dt(hsic); | ||
| 702 | if (err < 0) { | ||
| 703 | tegra_xusb_port_unregister(&hsic->base); | ||
| 704 | goto out; | ||
| 705 | } | ||
| 706 | |||
| 707 | list_add_tail(&hsic->base.list, &padctl->ports); | ||
| 708 | |||
| 709 | out: | ||
| 710 | of_node_put(np); | ||
| 711 | return err; | ||
| 712 | } | ||
| 713 | |||
| 714 | static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3) | ||
| 715 | { | ||
| 716 | struct tegra_xusb_port *port = &usb3->base; | ||
| 717 | struct device_node *np = port->dev.of_node; | ||
| 718 | u32 value; | ||
| 719 | int err; | ||
| 720 | |||
| 721 | err = of_property_read_u32(np, "nvidia,usb2-companion", &value); | ||
| 722 | if (err < 0) { | ||
| 723 | dev_err(&port->dev, "failed to read port: %d\n", err); | ||
| 724 | return err; | ||
| 725 | } | ||
| 726 | |||
| 727 | usb3->port = value; | ||
| 728 | |||
| 729 | usb3->internal = of_property_read_bool(np, "nvidia,internal"); | ||
| 730 | |||
| 731 | usb3->supply = devm_regulator_get(&port->dev, "vbus"); | ||
| 732 | if (IS_ERR(usb3->supply)) | ||
| 733 | return PTR_ERR(usb3->supply); | ||
| 734 | |||
| 735 | return 0; | ||
| 736 | } | ||
| 737 | |||
| 738 | static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl, | ||
| 739 | unsigned int index) | ||
| 740 | { | ||
| 741 | struct tegra_xusb_usb3_port *usb3; | ||
| 742 | struct device_node *np; | ||
| 743 | int err = 0; | ||
| 744 | |||
| 745 | /* | ||
| 746 | * If there is no supplemental configuration in the device tree the | ||
| 747 | * port is unusable. But it is valid to configure only a single port, | ||
| 748 | * hence return 0 instead of an error to allow ports to be optional. | ||
| 749 | */ | ||
| 750 | np = tegra_xusb_find_port_node(padctl, "usb3", index); | ||
| 751 | if (!np || !of_device_is_available(np)) | ||
| 752 | goto out; | ||
| 753 | |||
| 754 | usb3 = devm_kzalloc(padctl->dev, sizeof(*usb3), GFP_KERNEL); | ||
| 755 | if (!usb3) { | ||
| 756 | err = -ENOMEM; | ||
| 757 | goto out; | ||
| 758 | } | ||
| 759 | |||
| 760 | err = tegra_xusb_port_init(&usb3->base, padctl, np, "usb3", index); | ||
| 761 | if (err < 0) | ||
| 762 | goto out; | ||
| 763 | |||
| 764 | usb3->base.ops = padctl->soc->ports.usb3.ops; | ||
| 765 | |||
| 766 | usb3->base.lane = usb3->base.ops->map(&usb3->base); | ||
| 767 | if (IS_ERR(usb3->base.lane)) { | ||
| 768 | err = PTR_ERR(usb3->base.lane); | ||
| 769 | goto out; | ||
| 770 | } | ||
| 771 | |||
| 772 | err = tegra_xusb_usb3_port_parse_dt(usb3); | ||
| 773 | if (err < 0) { | ||
| 774 | tegra_xusb_port_unregister(&usb3->base); | ||
| 775 | goto out; | ||
| 776 | } | ||
| 777 | |||
| 778 | list_add_tail(&usb3->base.list, &padctl->ports); | ||
| 779 | |||
| 780 | out: | ||
| 781 | of_node_put(np); | ||
| 782 | return err; | ||
| 783 | } | ||
| 784 | |||
| 785 | static void __tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl) | ||
| 786 | { | ||
| 787 | struct tegra_xusb_port *port, *tmp; | ||
| 788 | |||
| 789 | list_for_each_entry_safe_reverse(port, tmp, &padctl->ports, list) { | ||
| 790 | list_del(&port->list); | ||
| 791 | tegra_xusb_port_unregister(port); | ||
| 792 | } | ||
| 793 | } | ||
| 794 | |||
| 795 | static int tegra_xusb_setup_ports(struct tegra_xusb_padctl *padctl) | ||
| 796 | { | ||
| 797 | struct tegra_xusb_port *port; | ||
| 798 | unsigned int i; | ||
| 799 | int err = 0; | ||
| 800 | |||
| 801 | mutex_lock(&padctl->lock); | ||
| 802 | |||
| 803 | for (i = 0; i < padctl->soc->ports.usb2.count; i++) { | ||
| 804 | err = tegra_xusb_add_usb2_port(padctl, i); | ||
| 805 | if (err < 0) | ||
| 806 | goto remove_ports; | ||
| 807 | } | ||
| 808 | |||
| 809 | for (i = 0; i < padctl->soc->ports.ulpi.count; i++) { | ||
| 810 | err = tegra_xusb_add_ulpi_port(padctl, i); | ||
| 811 | if (err < 0) | ||
| 812 | goto remove_ports; | ||
| 813 | } | ||
| 814 | |||
| 815 | for (i = 0; i < padctl->soc->ports.hsic.count; i++) { | ||
| 816 | err = tegra_xusb_add_hsic_port(padctl, i); | ||
| 817 | if (err < 0) | ||
| 818 | goto remove_ports; | ||
| 819 | } | ||
| 820 | |||
| 821 | for (i = 0; i < padctl->soc->ports.usb3.count; i++) { | ||
| 822 | err = tegra_xusb_add_usb3_port(padctl, i); | ||
| 823 | if (err < 0) | ||
| 824 | goto remove_ports; | ||
| 825 | } | ||
| 826 | |||
| 827 | list_for_each_entry(port, &padctl->ports, list) { | ||
| 828 | err = port->ops->enable(port); | ||
| 829 | if (err < 0) | ||
| 830 | dev_err(padctl->dev, "failed to enable port %s: %d\n", | ||
| 831 | dev_name(&port->dev), err); | ||
| 832 | } | ||
| 833 | |||
| 834 | goto unlock; | ||
| 835 | |||
| 836 | remove_ports: | ||
| 837 | __tegra_xusb_remove_ports(padctl); | ||
| 838 | unlock: | ||
| 839 | mutex_unlock(&padctl->lock); | ||
| 840 | return err; | ||
| 841 | } | ||
| 842 | |||
| 843 | static void tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl) | ||
| 844 | { | ||
| 845 | mutex_lock(&padctl->lock); | ||
| 846 | __tegra_xusb_remove_ports(padctl); | ||
| 847 | mutex_unlock(&padctl->lock); | ||
| 848 | } | ||
| 849 | |||
| 850 | static int tegra_xusb_padctl_probe(struct platform_device *pdev) | ||
| 851 | { | ||
| 852 | struct device_node *np = of_node_get(pdev->dev.of_node); | ||
| 853 | const struct tegra_xusb_padctl_soc *soc; | ||
| 854 | struct tegra_xusb_padctl *padctl; | ||
| 855 | const struct of_device_id *match; | ||
| 856 | struct resource *res; | ||
| 857 | int err; | ||
| 858 | |||
| 859 | /* for backwards compatibility with old device trees */ | ||
| 860 | np = of_find_node_by_name(np, "pads"); | ||
| 861 | if (!np) { | ||
| 862 | dev_warn(&pdev->dev, "deprecated DT, using legacy driver\n"); | ||
| 863 | return tegra_xusb_padctl_legacy_probe(pdev); | ||
| 864 | } | ||
| 865 | |||
| 866 | of_node_put(np); | ||
| 867 | |||
| 868 | match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); | ||
| 869 | soc = match->data; | ||
| 870 | |||
| 871 | padctl = soc->ops->probe(&pdev->dev, soc); | ||
| 872 | if (IS_ERR(padctl)) | ||
| 873 | return PTR_ERR(padctl); | ||
| 874 | |||
| 875 | platform_set_drvdata(pdev, padctl); | ||
| 876 | INIT_LIST_HEAD(&padctl->ports); | ||
| 877 | INIT_LIST_HEAD(&padctl->lanes); | ||
| 878 | INIT_LIST_HEAD(&padctl->pads); | ||
| 879 | mutex_init(&padctl->lock); | ||
| 880 | |||
| 881 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 882 | padctl->regs = devm_ioremap_resource(&pdev->dev, res); | ||
| 883 | if (IS_ERR(padctl->regs)) { | ||
| 884 | err = PTR_ERR(padctl->regs); | ||
| 885 | goto remove; | ||
| 886 | } | ||
| 887 | |||
| 888 | padctl->rst = devm_reset_control_get(&pdev->dev, NULL); | ||
| 889 | if (IS_ERR(padctl->rst)) { | ||
| 890 | err = PTR_ERR(padctl->rst); | ||
| 891 | goto remove; | ||
| 892 | } | ||
| 893 | |||
| 894 | err = reset_control_deassert(padctl->rst); | ||
| 895 | if (err < 0) | ||
| 896 | goto remove; | ||
| 897 | |||
| 898 | err = tegra_xusb_setup_pads(padctl); | ||
| 899 | if (err < 0) { | ||
| 900 | dev_err(&pdev->dev, "failed to setup pads: %d\n", err); | ||
| 901 | goto reset; | ||
| 902 | } | ||
| 903 | |||
| 904 | err = tegra_xusb_setup_ports(padctl); | ||
| 905 | if (err) { | ||
| 906 | dev_err(&pdev->dev, "failed to setup XUSB ports: %d\n", err); | ||
| 907 | goto remove_pads; | ||
| 908 | } | ||
| 909 | |||
| 910 | return 0; | ||
| 911 | |||
| 912 | remove_pads: | ||
| 913 | tegra_xusb_remove_pads(padctl); | ||
| 914 | reset: | ||
| 915 | reset_control_assert(padctl->rst); | ||
| 916 | remove: | ||
| 917 | soc->ops->remove(padctl); | ||
| 918 | return err; | ||
| 919 | } | ||
| 920 | |||
| 921 | static int tegra_xusb_padctl_remove(struct platform_device *pdev) | ||
| 922 | { | ||
| 923 | struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); | ||
| 924 | int err; | ||
| 925 | |||
| 926 | tegra_xusb_remove_ports(padctl); | ||
| 927 | tegra_xusb_remove_pads(padctl); | ||
| 928 | |||
| 929 | err = reset_control_assert(padctl->rst); | ||
| 930 | if (err < 0) | ||
| 931 | dev_err(&pdev->dev, "failed to assert reset: %d\n", err); | ||
| 932 | |||
| 933 | padctl->soc->ops->remove(padctl); | ||
| 934 | |||
| 935 | return err; | ||
| 936 | } | ||
| 937 | |||
| 938 | static struct platform_driver tegra_xusb_padctl_driver = { | ||
| 939 | .driver = { | ||
| 940 | .name = "tegra-xusb-padctl", | ||
| 941 | .of_match_table = tegra_xusb_padctl_of_match, | ||
| 942 | }, | ||
| 943 | .probe = tegra_xusb_padctl_probe, | ||
| 944 | .remove = tegra_xusb_padctl_remove, | ||
| 945 | }; | ||
| 946 | module_platform_driver(tegra_xusb_padctl_driver); | ||
| 947 | |||
| 948 | struct tegra_xusb_padctl *tegra_xusb_padctl_get(struct device *dev) | ||
| 949 | { | ||
| 950 | struct tegra_xusb_padctl *padctl; | ||
| 951 | struct platform_device *pdev; | ||
| 952 | struct device_node *np; | ||
| 953 | |||
| 954 | np = of_parse_phandle(dev->of_node, "nvidia,xusb-padctl", 0); | ||
| 955 | if (!np) | ||
| 956 | return ERR_PTR(-EINVAL); | ||
| 957 | |||
| 958 | /* | ||
| 959 | * This is slightly ugly. A better implementation would be to keep a | ||
| 960 | * registry of pad controllers, but since there will almost certainly | ||
| 961 | * only ever be one per SoC that would be a little overkill. | ||
| 962 | */ | ||
| 963 | pdev = of_find_device_by_node(np); | ||
| 964 | if (!pdev) { | ||
| 965 | of_node_put(np); | ||
| 966 | return ERR_PTR(-ENODEV); | ||
| 967 | } | ||
| 968 | |||
| 969 | of_node_put(np); | ||
| 970 | |||
| 971 | padctl = platform_get_drvdata(pdev); | ||
| 972 | if (!padctl) { | ||
| 973 | put_device(&pdev->dev); | ||
| 974 | return ERR_PTR(-EPROBE_DEFER); | ||
| 975 | } | ||
| 976 | |||
| 977 | return padctl; | ||
| 978 | } | ||
| 979 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get); | ||
| 980 | |||
| 981 | void tegra_xusb_padctl_put(struct tegra_xusb_padctl *padctl) | ||
| 982 | { | ||
| 983 | if (padctl) | ||
| 984 | put_device(padctl->dev); | ||
| 985 | } | ||
| 986 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_put); | ||
| 987 | |||
| 988 | int tegra_xusb_padctl_usb3_save_context(struct tegra_xusb_padctl *padctl, | ||
| 989 | unsigned int port) | ||
| 990 | { | ||
| 991 | if (padctl->soc->ops->usb3_save_context) | ||
| 992 | return padctl->soc->ops->usb3_save_context(padctl, port); | ||
| 993 | |||
| 994 | return -ENOSYS; | ||
| 995 | } | ||
| 996 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_usb3_save_context); | ||
| 997 | |||
| 998 | int tegra_xusb_padctl_hsic_set_idle(struct tegra_xusb_padctl *padctl, | ||
| 999 | unsigned int port, bool idle) | ||
| 1000 | { | ||
| 1001 | if (padctl->soc->ops->hsic_set_idle) | ||
| 1002 | return padctl->soc->ops->hsic_set_idle(padctl, port, idle); | ||
| 1003 | |||
| 1004 | return -ENOSYS; | ||
| 1005 | } | ||
| 1006 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_hsic_set_idle); | ||
| 1007 | |||
| 1008 | int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, | ||
| 1009 | unsigned int port, bool enable) | ||
| 1010 | { | ||
| 1011 | if (padctl->soc->ops->usb3_set_lfps_detect) | ||
| 1012 | return padctl->soc->ops->usb3_set_lfps_detect(padctl, port, | ||
| 1013 | enable); | ||
| 1014 | |||
| 1015 | return -ENOSYS; | ||
| 1016 | } | ||
| 1017 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_usb3_set_lfps_detect); | ||
| 1018 | |||
| 1019 | MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); | ||
| 1020 | MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver"); | ||
| 1021 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h new file mode 100644 index 000000000000..b49dbc36efa3 --- /dev/null +++ b/drivers/phy/tegra/xusb.h | |||
| @@ -0,0 +1,421 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. | ||
| 3 | * Copyright (c) 2015, Google Inc. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __PHY_TEGRA_XUSB_H | ||
| 16 | #define __PHY_TEGRA_XUSB_H | ||
| 17 | |||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/workqueue.h> | ||
| 21 | |||
| 22 | /* legacy entry points for backwards-compatibility */ | ||
| 23 | int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev); | ||
| 24 | int tegra_xusb_padctl_legacy_remove(struct platform_device *pdev); | ||
| 25 | |||
| 26 | struct phy; | ||
| 27 | struct phy_provider; | ||
| 28 | struct platform_device; | ||
| 29 | struct regulator; | ||
| 30 | |||
| 31 | /* | ||
| 32 | * lanes | ||
| 33 | */ | ||
| 34 | struct tegra_xusb_lane_soc { | ||
| 35 | const char *name; | ||
| 36 | |||
| 37 | unsigned int offset; | ||
| 38 | unsigned int shift; | ||
| 39 | unsigned int mask; | ||
| 40 | |||
| 41 | const char * const *funcs; | ||
| 42 | unsigned int num_funcs; | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct tegra_xusb_lane { | ||
| 46 | const struct tegra_xusb_lane_soc *soc; | ||
| 47 | struct tegra_xusb_pad *pad; | ||
| 48 | struct device_node *np; | ||
| 49 | struct list_head list; | ||
| 50 | unsigned int function; | ||
| 51 | unsigned int index; | ||
| 52 | }; | ||
| 53 | |||
| 54 | int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane, | ||
| 55 | struct device_node *np); | ||
| 56 | |||
| 57 | struct tegra_xusb_usb2_lane { | ||
| 58 | struct tegra_xusb_lane base; | ||
| 59 | |||
| 60 | u32 hs_curr_level_offset; | ||
| 61 | }; | ||
| 62 | |||
| 63 | static inline struct tegra_xusb_usb2_lane * | ||
| 64 | to_usb2_lane(struct tegra_xusb_lane *lane) | ||
| 65 | { | ||
| 66 | return container_of(lane, struct tegra_xusb_usb2_lane, base); | ||
| 67 | } | ||
| 68 | |||
| 69 | struct tegra_xusb_ulpi_lane { | ||
| 70 | struct tegra_xusb_lane base; | ||
| 71 | }; | ||
| 72 | |||
| 73 | static inline struct tegra_xusb_ulpi_lane * | ||
| 74 | to_ulpi_lane(struct tegra_xusb_lane *lane) | ||
| 75 | { | ||
| 76 | return container_of(lane, struct tegra_xusb_ulpi_lane, base); | ||
| 77 | } | ||
| 78 | |||
| 79 | struct tegra_xusb_hsic_lane { | ||
| 80 | struct tegra_xusb_lane base; | ||
| 81 | |||
| 82 | u32 strobe_trim; | ||
| 83 | u32 rx_strobe_trim; | ||
| 84 | u32 rx_data_trim; | ||
| 85 | u32 tx_rtune_n; | ||
| 86 | u32 tx_rtune_p; | ||
| 87 | u32 tx_rslew_n; | ||
| 88 | u32 tx_rslew_p; | ||
| 89 | bool auto_term; | ||
| 90 | }; | ||
| 91 | |||
| 92 | static inline struct tegra_xusb_hsic_lane * | ||
| 93 | to_hsic_lane(struct tegra_xusb_lane *lane) | ||
| 94 | { | ||
| 95 | return container_of(lane, struct tegra_xusb_hsic_lane, base); | ||
| 96 | } | ||
| 97 | |||
| 98 | struct tegra_xusb_pcie_lane { | ||
| 99 | struct tegra_xusb_lane base; | ||
| 100 | }; | ||
| 101 | |||
| 102 | static inline struct tegra_xusb_pcie_lane * | ||
| 103 | to_pcie_lane(struct tegra_xusb_lane *lane) | ||
| 104 | { | ||
| 105 | return container_of(lane, struct tegra_xusb_pcie_lane, base); | ||
| 106 | } | ||
| 107 | |||
| 108 | struct tegra_xusb_sata_lane { | ||
| 109 | struct tegra_xusb_lane base; | ||
| 110 | }; | ||
| 111 | |||
| 112 | static inline struct tegra_xusb_sata_lane * | ||
| 113 | to_sata_lane(struct tegra_xusb_lane *lane) | ||
| 114 | { | ||
| 115 | return container_of(lane, struct tegra_xusb_sata_lane, base); | ||
| 116 | } | ||
| 117 | |||
| 118 | struct tegra_xusb_lane_ops { | ||
| 119 | struct tegra_xusb_lane *(*probe)(struct tegra_xusb_pad *pad, | ||
| 120 | struct device_node *np, | ||
| 121 | unsigned int index); | ||
| 122 | void (*remove)(struct tegra_xusb_lane *lane); | ||
| 123 | }; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * pads | ||
| 127 | */ | ||
| 128 | struct tegra_xusb_pad_soc; | ||
| 129 | struct tegra_xusb_padctl; | ||
| 130 | |||
| 131 | struct tegra_xusb_pad_ops { | ||
| 132 | struct tegra_xusb_pad *(*probe)(struct tegra_xusb_padctl *padctl, | ||
| 133 | const struct tegra_xusb_pad_soc *soc, | ||
| 134 | struct device_node *np); | ||
| 135 | void (*remove)(struct tegra_xusb_pad *pad); | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct tegra_xusb_pad_soc { | ||
| 139 | const char *name; | ||
| 140 | |||
| 141 | const struct tegra_xusb_lane_soc *lanes; | ||
| 142 | unsigned int num_lanes; | ||
| 143 | |||
| 144 | const struct tegra_xusb_pad_ops *ops; | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct tegra_xusb_pad { | ||
| 148 | const struct tegra_xusb_pad_soc *soc; | ||
| 149 | struct tegra_xusb_padctl *padctl; | ||
| 150 | struct phy_provider *provider; | ||
| 151 | struct phy **lanes; | ||
| 152 | struct device dev; | ||
| 153 | |||
| 154 | const struct tegra_xusb_lane_ops *ops; | ||
| 155 | |||
| 156 | struct list_head list; | ||
| 157 | }; | ||
| 158 | |||
| 159 | static inline struct tegra_xusb_pad *to_tegra_xusb_pad(struct device *dev) | ||
| 160 | { | ||
| 161 | return container_of(dev, struct tegra_xusb_pad, dev); | ||
| 162 | } | ||
| 163 | |||
| 164 | int tegra_xusb_pad_init(struct tegra_xusb_pad *pad, | ||
| 165 | struct tegra_xusb_padctl *padctl, | ||
| 166 | struct device_node *np); | ||
| 167 | int tegra_xusb_pad_register(struct tegra_xusb_pad *pad, | ||
| 168 | const struct phy_ops *ops); | ||
| 169 | void tegra_xusb_pad_unregister(struct tegra_xusb_pad *pad); | ||
| 170 | |||
| 171 | struct tegra_xusb_usb2_pad { | ||
| 172 | struct tegra_xusb_pad base; | ||
| 173 | |||
| 174 | struct clk *clk; | ||
| 175 | unsigned int enable; | ||
| 176 | struct mutex lock; | ||
| 177 | }; | ||
| 178 | |||
| 179 | static inline struct tegra_xusb_usb2_pad * | ||
| 180 | to_usb2_pad(struct tegra_xusb_pad *pad) | ||
| 181 | { | ||
| 182 | return container_of(pad, struct tegra_xusb_usb2_pad, base); | ||
| 183 | } | ||
| 184 | |||
| 185 | struct tegra_xusb_ulpi_pad { | ||
| 186 | struct tegra_xusb_pad base; | ||
| 187 | }; | ||
| 188 | |||
| 189 | static inline struct tegra_xusb_ulpi_pad * | ||
| 190 | to_ulpi_pad(struct tegra_xusb_pad *pad) | ||
| 191 | { | ||
| 192 | return container_of(pad, struct tegra_xusb_ulpi_pad, base); | ||
| 193 | } | ||
| 194 | |||
| 195 | struct tegra_xusb_hsic_pad { | ||
| 196 | struct tegra_xusb_pad base; | ||
| 197 | |||
| 198 | struct regulator *supply; | ||
| 199 | struct clk *clk; | ||
| 200 | }; | ||
| 201 | |||
| 202 | static inline struct tegra_xusb_hsic_pad * | ||
| 203 | to_hsic_pad(struct tegra_xusb_pad *pad) | ||
| 204 | { | ||
| 205 | return container_of(pad, struct tegra_xusb_hsic_pad, base); | ||
| 206 | } | ||
| 207 | |||
| 208 | struct tegra_xusb_pcie_pad { | ||
| 209 | struct tegra_xusb_pad base; | ||
| 210 | |||
| 211 | struct reset_control *rst; | ||
| 212 | struct clk *pll; | ||
| 213 | |||
| 214 | unsigned int enable; | ||
| 215 | }; | ||
| 216 | |||
| 217 | static inline struct tegra_xusb_pcie_pad * | ||
| 218 | to_pcie_pad(struct tegra_xusb_pad *pad) | ||
| 219 | { | ||
| 220 | return container_of(pad, struct tegra_xusb_pcie_pad, base); | ||
| 221 | } | ||
| 222 | |||
| 223 | struct tegra_xusb_sata_pad { | ||
| 224 | struct tegra_xusb_pad base; | ||
| 225 | |||
| 226 | struct reset_control *rst; | ||
| 227 | struct clk *pll; | ||
| 228 | |||
| 229 | unsigned int enable; | ||
| 230 | }; | ||
| 231 | |||
| 232 | static inline struct tegra_xusb_sata_pad * | ||
| 233 | to_sata_pad(struct tegra_xusb_pad *pad) | ||
| 234 | { | ||
| 235 | return container_of(pad, struct tegra_xusb_sata_pad, base); | ||
| 236 | } | ||
| 237 | |||
| 238 | /* | ||
| 239 | * ports | ||
| 240 | */ | ||
| 241 | struct tegra_xusb_port_ops; | ||
| 242 | |||
| 243 | struct tegra_xusb_port { | ||
| 244 | struct tegra_xusb_padctl *padctl; | ||
| 245 | struct tegra_xusb_lane *lane; | ||
| 246 | unsigned int index; | ||
| 247 | |||
| 248 | struct list_head list; | ||
| 249 | struct device dev; | ||
| 250 | |||
| 251 | const struct tegra_xusb_port_ops *ops; | ||
| 252 | }; | ||
| 253 | |||
| 254 | struct tegra_xusb_lane_map { | ||
| 255 | unsigned int port; | ||
| 256 | const char *type; | ||
| 257 | unsigned int index; | ||
| 258 | const char *func; | ||
| 259 | }; | ||
| 260 | |||
| 261 | struct tegra_xusb_lane * | ||
| 262 | tegra_xusb_port_find_lane(struct tegra_xusb_port *port, | ||
| 263 | const struct tegra_xusb_lane_map *map, | ||
| 264 | const char *function); | ||
| 265 | |||
| 266 | struct tegra_xusb_port * | ||
| 267 | tegra_xusb_find_port(struct tegra_xusb_padctl *padctl, const char *type, | ||
| 268 | unsigned int index); | ||
| 269 | |||
| 270 | struct tegra_xusb_usb2_port { | ||
| 271 | struct tegra_xusb_port base; | ||
| 272 | |||
| 273 | struct regulator *supply; | ||
| 274 | bool internal; | ||
| 275 | }; | ||
| 276 | |||
| 277 | static inline struct tegra_xusb_usb2_port * | ||
| 278 | to_usb2_port(struct tegra_xusb_port *port) | ||
| 279 | { | ||
| 280 | return container_of(port, struct tegra_xusb_usb2_port, base); | ||
| 281 | } | ||
| 282 | |||
| 283 | struct tegra_xusb_usb2_port * | ||
| 284 | tegra_xusb_find_usb2_port(struct tegra_xusb_padctl *padctl, | ||
| 285 | unsigned int index); | ||
| 286 | |||
| 287 | struct tegra_xusb_ulpi_port { | ||
| 288 | struct tegra_xusb_port base; | ||
| 289 | |||
| 290 | struct regulator *supply; | ||
| 291 | bool internal; | ||
| 292 | }; | ||
| 293 | |||
| 294 | static inline struct tegra_xusb_ulpi_port * | ||
| 295 | to_ulpi_port(struct tegra_xusb_port *port) | ||
| 296 | { | ||
| 297 | return container_of(port, struct tegra_xusb_ulpi_port, base); | ||
| 298 | } | ||
| 299 | |||
| 300 | struct tegra_xusb_hsic_port { | ||
| 301 | struct tegra_xusb_port base; | ||
| 302 | }; | ||
| 303 | |||
| 304 | static inline struct tegra_xusb_hsic_port * | ||
| 305 | to_hsic_port(struct tegra_xusb_port *port) | ||
| 306 | { | ||
| 307 | return container_of(port, struct tegra_xusb_hsic_port, base); | ||
| 308 | } | ||
| 309 | |||
| 310 | struct tegra_xusb_usb3_port { | ||
| 311 | struct tegra_xusb_port base; | ||
| 312 | struct regulator *supply; | ||
| 313 | bool context_saved; | ||
| 314 | unsigned int port; | ||
| 315 | bool internal; | ||
| 316 | |||
| 317 | u32 tap1; | ||
| 318 | u32 amp; | ||
| 319 | u32 ctle_z; | ||
| 320 | u32 ctle_g; | ||
| 321 | }; | ||
| 322 | |||
| 323 | static inline struct tegra_xusb_usb3_port * | ||
| 324 | to_usb3_port(struct tegra_xusb_port *port) | ||
| 325 | { | ||
| 326 | return container_of(port, struct tegra_xusb_usb3_port, base); | ||
| 327 | } | ||
| 328 | |||
| 329 | struct tegra_xusb_usb3_port * | ||
| 330 | tegra_xusb_find_usb3_port(struct tegra_xusb_padctl *padctl, | ||
| 331 | unsigned int index); | ||
| 332 | |||
| 333 | struct tegra_xusb_port_ops { | ||
| 334 | int (*enable)(struct tegra_xusb_port *port); | ||
| 335 | void (*disable)(struct tegra_xusb_port *port); | ||
| 336 | struct tegra_xusb_lane *(*map)(struct tegra_xusb_port *port); | ||
| 337 | }; | ||
| 338 | |||
| 339 | /* | ||
| 340 | * pad controller | ||
| 341 | */ | ||
| 342 | struct tegra_xusb_padctl_soc; | ||
| 343 | |||
| 344 | struct tegra_xusb_padctl_ops { | ||
| 345 | struct tegra_xusb_padctl * | ||
| 346 | (*probe)(struct device *dev, | ||
| 347 | const struct tegra_xusb_padctl_soc *soc); | ||
| 348 | void (*remove)(struct tegra_xusb_padctl *padctl); | ||
| 349 | |||
| 350 | int (*usb3_save_context)(struct tegra_xusb_padctl *padctl, | ||
| 351 | unsigned int index); | ||
| 352 | int (*hsic_set_idle)(struct tegra_xusb_padctl *padctl, | ||
| 353 | unsigned int index, bool idle); | ||
| 354 | int (*usb3_set_lfps_detect)(struct tegra_xusb_padctl *padctl, | ||
| 355 | unsigned int index, bool enable); | ||
| 356 | }; | ||
| 357 | |||
| 358 | struct tegra_xusb_padctl_soc { | ||
| 359 | const struct tegra_xusb_pad_soc * const *pads; | ||
| 360 | unsigned int num_pads; | ||
| 361 | |||
| 362 | struct { | ||
| 363 | struct { | ||
| 364 | const struct tegra_xusb_port_ops *ops; | ||
| 365 | unsigned int count; | ||
| 366 | } usb2, ulpi, hsic, usb3; | ||
| 367 | } ports; | ||
| 368 | |||
| 369 | const struct tegra_xusb_padctl_ops *ops; | ||
| 370 | }; | ||
| 371 | |||
| 372 | struct tegra_xusb_padctl { | ||
| 373 | struct device *dev; | ||
| 374 | void __iomem *regs; | ||
| 375 | struct mutex lock; | ||
| 376 | struct reset_control *rst; | ||
| 377 | |||
| 378 | const struct tegra_xusb_padctl_soc *soc; | ||
| 379 | |||
| 380 | struct tegra_xusb_pad *pcie; | ||
| 381 | struct tegra_xusb_pad *sata; | ||
| 382 | struct tegra_xusb_pad *ulpi; | ||
| 383 | struct tegra_xusb_pad *usb2; | ||
| 384 | struct tegra_xusb_pad *hsic; | ||
| 385 | |||
| 386 | struct list_head ports; | ||
| 387 | struct list_head lanes; | ||
| 388 | struct list_head pads; | ||
| 389 | |||
| 390 | unsigned int enable; | ||
| 391 | |||
| 392 | struct clk *clk; | ||
| 393 | }; | ||
| 394 | |||
| 395 | static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, | ||
| 396 | unsigned long offset) | ||
| 397 | { | ||
| 398 | dev_dbg(padctl->dev, "%08lx < %08x\n", offset, value); | ||
| 399 | writel(value, padctl->regs + offset); | ||
| 400 | } | ||
| 401 | |||
| 402 | static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, | ||
| 403 | unsigned long offset) | ||
| 404 | { | ||
| 405 | u32 value = readl(padctl->regs + offset); | ||
| 406 | dev_dbg(padctl->dev, "%08lx > %08x\n", offset, value); | ||
| 407 | return value; | ||
| 408 | } | ||
| 409 | |||
| 410 | struct tegra_xusb_lane *tegra_xusb_find_lane(struct tegra_xusb_padctl *padctl, | ||
| 411 | const char *name, | ||
| 412 | unsigned int index); | ||
| 413 | |||
| 414 | #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) | ||
| 415 | extern const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc; | ||
| 416 | #endif | ||
| 417 | #if defined(CONFIG_ARCH_TEGRA_210_SOC) | ||
| 418 | extern const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc; | ||
| 419 | #endif | ||
| 420 | |||
| 421 | #endif /* __PHY_TEGRA_XUSB_H */ | ||
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c index 2f06029c9405..946cda3fee35 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c | |||
| @@ -873,7 +873,7 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = { | |||
| 873 | }; | 873 | }; |
| 874 | MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); | 874 | MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); |
| 875 | 875 | ||
| 876 | static int tegra_xusb_padctl_probe(struct platform_device *pdev) | 876 | int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev) |
| 877 | { | 877 | { |
| 878 | struct tegra_xusb_padctl *padctl; | 878 | struct tegra_xusb_padctl *padctl; |
| 879 | const struct of_device_id *match; | 879 | const struct of_device_id *match; |
| @@ -955,8 +955,9 @@ reset: | |||
| 955 | reset_control_assert(padctl->rst); | 955 | reset_control_assert(padctl->rst); |
| 956 | return err; | 956 | return err; |
| 957 | } | 957 | } |
| 958 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_probe); | ||
| 958 | 959 | ||
| 959 | static int tegra_xusb_padctl_remove(struct platform_device *pdev) | 960 | int tegra_xusb_padctl_legacy_remove(struct platform_device *pdev) |
| 960 | { | 961 | { |
| 961 | struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); | 962 | struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); |
| 962 | int err; | 963 | int err; |
| @@ -969,17 +970,4 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) | |||
| 969 | 970 | ||
| 970 | return err; | 971 | return err; |
| 971 | } | 972 | } |
| 972 | 973 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_legacy_remove); | |
| 973 | static struct platform_driver tegra_xusb_padctl_driver = { | ||
| 974 | .driver = { | ||
| 975 | .name = "tegra-xusb-padctl", | ||
| 976 | .of_match_table = tegra_xusb_padctl_of_match, | ||
| 977 | }, | ||
| 978 | .probe = tegra_xusb_padctl_probe, | ||
| 979 | .remove = tegra_xusb_padctl_remove, | ||
| 980 | }; | ||
| 981 | module_platform_driver(tegra_xusb_padctl_driver); | ||
| 982 | |||
| 983 | MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); | ||
| 984 | MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); | ||
| 985 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index 57bf7aab4516..7007a5f48080 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h | |||
| @@ -121,4 +121,9 @@ static inline void tegra_cpu_clock_resume(void) | |||
| 121 | } | 121 | } |
| 122 | #endif | 122 | #endif |
| 123 | 123 | ||
| 124 | extern void tegra210_xusb_pll_hw_control_enable(void); | ||
| 125 | extern void tegra210_xusb_pll_hw_sequence_start(void); | ||
| 126 | extern void tegra210_sata_pll_hw_control_enable(void); | ||
| 127 | extern void tegra210_sata_pll_hw_sequence_start(void); | ||
| 128 | |||
| 124 | #endif /* __LINUX_CLK_TEGRA_H_ */ | 129 | #endif /* __LINUX_CLK_TEGRA_H_ */ |
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 8cf05e341cff..a810f2a18842 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
| @@ -77,6 +77,7 @@ struct phy { | |||
| 77 | */ | 77 | */ |
| 78 | struct phy_provider { | 78 | struct phy_provider { |
| 79 | struct device *dev; | 79 | struct device *dev; |
| 80 | struct device_node *children; | ||
| 80 | struct module *owner; | 81 | struct module *owner; |
| 81 | struct list_head list; | 82 | struct list_head list; |
| 82 | struct phy * (*of_xlate)(struct device *dev, | 83 | struct phy * (*of_xlate)(struct device *dev, |
| @@ -93,10 +94,16 @@ struct phy_lookup { | |||
| 93 | #define to_phy(a) (container_of((a), struct phy, dev)) | 94 | #define to_phy(a) (container_of((a), struct phy, dev)) |
| 94 | 95 | ||
| 95 | #define of_phy_provider_register(dev, xlate) \ | 96 | #define of_phy_provider_register(dev, xlate) \ |
| 96 | __of_phy_provider_register((dev), THIS_MODULE, (xlate)) | 97 | __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate)) |
| 97 | 98 | ||
| 98 | #define devm_of_phy_provider_register(dev, xlate) \ | 99 | #define devm_of_phy_provider_register(dev, xlate) \ |
| 99 | __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate)) | 100 | __devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate)) |
| 101 | |||
| 102 | #define of_phy_provider_register_full(dev, children, xlate) \ | ||
| 103 | __of_phy_provider_register(dev, children, THIS_MODULE, xlate) | ||
| 104 | |||
| 105 | #define devm_of_phy_provider_register_full(dev, children, xlate) \ | ||
| 106 | __devm_of_phy_provider_register(dev, children, THIS_MODULE, xlate) | ||
| 100 | 107 | ||
| 101 | static inline void phy_set_drvdata(struct phy *phy, void *data) | 108 | static inline void phy_set_drvdata(struct phy *phy, void *data) |
| 102 | { | 109 | { |
| @@ -147,11 +154,13 @@ struct phy *devm_phy_create(struct device *dev, struct device_node *node, | |||
| 147 | void phy_destroy(struct phy *phy); | 154 | void phy_destroy(struct phy *phy); |
| 148 | void devm_phy_destroy(struct device *dev, struct phy *phy); | 155 | void devm_phy_destroy(struct device *dev, struct phy *phy); |
| 149 | struct phy_provider *__of_phy_provider_register(struct device *dev, | 156 | struct phy_provider *__of_phy_provider_register(struct device *dev, |
| 150 | struct module *owner, struct phy * (*of_xlate)(struct device *dev, | 157 | struct device_node *children, struct module *owner, |
| 151 | struct of_phandle_args *args)); | 158 | struct phy * (*of_xlate)(struct device *dev, |
| 159 | struct of_phandle_args *args)); | ||
| 152 | struct phy_provider *__devm_of_phy_provider_register(struct device *dev, | 160 | struct phy_provider *__devm_of_phy_provider_register(struct device *dev, |
| 153 | struct module *owner, struct phy * (*of_xlate)(struct device *dev, | 161 | struct device_node *children, struct module *owner, |
| 154 | struct of_phandle_args *args)); | 162 | struct phy * (*of_xlate)(struct device *dev, |
| 163 | struct of_phandle_args *args)); | ||
| 155 | void of_phy_provider_unregister(struct phy_provider *phy_provider); | 164 | void of_phy_provider_unregister(struct phy_provider *phy_provider); |
| 156 | void devm_of_phy_provider_unregister(struct device *dev, | 165 | void devm_of_phy_provider_unregister(struct device *dev, |
| 157 | struct phy_provider *phy_provider); | 166 | struct phy_provider *phy_provider); |
| @@ -312,15 +321,17 @@ static inline void devm_phy_destroy(struct device *dev, struct phy *phy) | |||
| 312 | } | 321 | } |
| 313 | 322 | ||
| 314 | static inline struct phy_provider *__of_phy_provider_register( | 323 | static inline struct phy_provider *__of_phy_provider_register( |
| 315 | struct device *dev, struct module *owner, struct phy * (*of_xlate)( | 324 | struct device *dev, struct device_node *children, struct module *owner, |
| 316 | struct device *dev, struct of_phandle_args *args)) | 325 | struct phy * (*of_xlate)(struct device *dev, |
| 326 | struct of_phandle_args *args)) | ||
| 317 | { | 327 | { |
| 318 | return ERR_PTR(-ENOSYS); | 328 | return ERR_PTR(-ENOSYS); |
| 319 | } | 329 | } |
| 320 | 330 | ||
| 321 | static inline struct phy_provider *__devm_of_phy_provider_register(struct device | 331 | static inline struct phy_provider *__devm_of_phy_provider_register(struct device |
| 322 | *dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev, | 332 | *dev, struct device_node *children, struct module *owner, |
| 323 | struct of_phandle_args *args)) | 333 | struct phy * (*of_xlate)(struct device *dev, |
| 334 | struct of_phandle_args *args)) | ||
| 324 | { | 335 | { |
| 325 | return ERR_PTR(-ENOSYS); | 336 | return ERR_PTR(-ENOSYS); |
| 326 | } | 337 | } |
diff --git a/include/linux/phy/tegra/xusb.h b/include/linux/phy/tegra/xusb.h new file mode 100644 index 000000000000..8e1a57a78d9f --- /dev/null +++ b/include/linux/phy/tegra/xusb.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef PHY_TEGRA_XUSB_H | ||
| 15 | #define PHY_TEGRA_XUSB_H | ||
| 16 | |||
| 17 | struct tegra_xusb_padctl; | ||
| 18 | struct device; | ||
| 19 | |||
| 20 | struct tegra_xusb_padctl *tegra_xusb_padctl_get(struct device *dev); | ||
| 21 | void tegra_xusb_padctl_put(struct tegra_xusb_padctl *padctl); | ||
| 22 | |||
| 23 | int tegra_xusb_padctl_usb3_save_context(struct tegra_xusb_padctl *padctl, | ||
| 24 | unsigned int port); | ||
| 25 | int tegra_xusb_padctl_hsic_set_idle(struct tegra_xusb_padctl *padctl, | ||
| 26 | unsigned int port, bool idle); | ||
| 27 | int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, | ||
| 28 | unsigned int port, bool enable); | ||
| 29 | |||
| 30 | #endif /* PHY_TEGRA_XUSB_H */ | ||
diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 961b821b6a46..b4c9219e7f95 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #define TEGRA_FUSE_SKU_CALIB_0 0xf0 | 27 | #define TEGRA_FUSE_SKU_CALIB_0 0xf0 |
| 28 | #define TEGRA30_FUSE_SATA_CALIB 0x124 | 28 | #define TEGRA30_FUSE_SATA_CALIB 0x124 |
| 29 | #define TEGRA_FUSE_USB_CALIB_EXT_0 0x250 | ||
| 29 | 30 | ||
| 30 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
| 31 | 32 | ||
